mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-10-03 11:16:46 -04:00
Interp BLK/BLS deformations
This commit is contained in:
@@ -1469,6 +1469,7 @@ set(DUSK_FILES
|
||||
src/dusk/interp/line.cpp
|
||||
src/dusk/interp/particle.cpp
|
||||
src/dusk/interp/samples.cpp
|
||||
src/dusk/interp/vertex.cpp
|
||||
src/dusk/io.cpp
|
||||
src/dusk/iso_validate.cpp
|
||||
src/dusk/language.cpp
|
||||
|
||||
@@ -8,7 +8,12 @@
|
||||
|
||||
#include "JSystem/JSupport/JSupport.h"
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/interp/vertex.h"
|
||||
#endif
|
||||
|
||||
J3DDeformData::J3DDeformData() {
|
||||
IF_DUSK(dusk::interp::vertex::invalidate(this));
|
||||
mClusterNum = 0;
|
||||
mClusterKeyNum = 0;
|
||||
mClusterVertexNum = 0;
|
||||
@@ -67,6 +72,7 @@ void J3DDeformData::deform(J3DVertexBuffer* buffer) {
|
||||
}
|
||||
|
||||
void J3DDeformData::setAnm(J3DAnmCluster* anm) {
|
||||
IF_DUSK(dusk::interp::vertex::invalidate(this));
|
||||
for (u16 i = 0; i < mClusterNum; i++) {
|
||||
DEFORMER(i)->setAnmCluster(anm);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/interp/frame_interpolation.h"
|
||||
#include "dusk/interp/vertex.h"
|
||||
#endif
|
||||
|
||||
#define J3D_ASSERTMSG(LINE, COND, MSG) JUT_ASSERT_MSG(LINE, (COND) != 0, MSG)
|
||||
@@ -131,6 +132,7 @@ void J3DModel::setAnmMtx(int jointNo, Mtx m) {
|
||||
}
|
||||
|
||||
void J3DModel::forgetMtx() {
|
||||
dusk::interp::vertex::reset(&mVertexBuffer);
|
||||
dusk::interp::forget_mtx(mPresentationBase);
|
||||
for (u16 i = 0; i < mModelData->getJointNum(); ++i) {
|
||||
dusk::interp::forget_mtx(getAnmMtx(i));
|
||||
@@ -494,7 +496,9 @@ void J3DModel::calc() {
|
||||
mCalcCallBack(this, 0);
|
||||
}
|
||||
|
||||
#ifdef TARGET_PC
|
||||
#if TARGET_PC
|
||||
dusk::interp::vertex::capture(&mVertexBuffer, mDeformData);
|
||||
|
||||
for (u16 i = 0; i < mModelData->getJointNum(); ++i) {
|
||||
dusk::interp::record_final_mtx(getAnmMtx(i));
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
#include "JSystem/JKernel/JKRHeap.h"
|
||||
#include <cstring>
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/interp/vertex.h"
|
||||
#endif
|
||||
|
||||
J3DVertexData::J3DVertexData() {
|
||||
mVtxNum = 0;
|
||||
mNrmNum = 0;
|
||||
@@ -31,6 +35,7 @@ J3DVertexData::J3DVertexData() {
|
||||
}
|
||||
|
||||
void J3DVertexBuffer::setVertexData(J3DVertexData* pVtxData) {
|
||||
IF_DUSK(dusk::interp::vertex::reset(this));
|
||||
J3D_ASSERT_NULLPTR(175, pVtxData != NULL);
|
||||
|
||||
mVtxData = pVtxData;
|
||||
@@ -50,6 +55,7 @@ void J3DVertexBuffer::setVertexData(J3DVertexData* pVtxData) {
|
||||
}
|
||||
|
||||
void J3DVertexBuffer::init() {
|
||||
IF_DUSK(dusk::interp::vertex::reset(this));
|
||||
mVtxData = NULL;
|
||||
|
||||
mVtxPosArray[0] = mVtxPosArray[1] = NULL;
|
||||
@@ -65,11 +71,15 @@ void J3DVertexBuffer::init() {
|
||||
frameInit();
|
||||
}
|
||||
|
||||
J3DVertexBuffer::~J3DVertexBuffer() {}
|
||||
J3DVertexBuffer::~J3DVertexBuffer() {
|
||||
IF_DUSK(dusk::interp::vertex::reset(this));
|
||||
}
|
||||
|
||||
void J3DVertexBuffer::setArray() const {
|
||||
j3dSys.setVtxPos(mCurrentVtxPos, mVtxData->getVtxNum());
|
||||
j3dSys.setVtxNrm(mCurrentVtxNrm, mVtxData->getNrmNum());
|
||||
j3dSys.setVtxPos(DUSK_IF_ELSE(dusk::interp::vertex::positions(this, mCurrentVtxPos), mCurrentVtxPos),
|
||||
mVtxData->getVtxNum());
|
||||
j3dSys.setVtxNrm(DUSK_IF_ELSE(dusk::interp::vertex::normals(this, mCurrentVtxNrm), mCurrentVtxNrm),
|
||||
mVtxData->getNrmNum());
|
||||
j3dSys.setVtxCol(mCurrentVtxCol, mVtxData->getColNum());
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "dusk/interp/lerp.h"
|
||||
#include "dusk/interp/particle.h"
|
||||
#include "dusk/interp/samples.h"
|
||||
#include "dusk/interp/vertex.h"
|
||||
|
||||
#include "mtx.h"
|
||||
|
||||
@@ -106,11 +107,12 @@ void clear_interpolation_history() {
|
||||
s_previousRecording = {};
|
||||
s_currentRecording = {};
|
||||
clear_replacements();
|
||||
dusk::interp::clear_owned_samples();
|
||||
dusk::interp::particle::clear();
|
||||
dusk::interp::clear_weather_samples();
|
||||
clear_callbacks();
|
||||
dusk::interp::camera_invalidate_snapshots();
|
||||
dusk::interp::clear_owned_samples();
|
||||
dusk::interp::clear_weather_samples();
|
||||
dusk::interp::particle::clear();
|
||||
dusk::interp::vertex::clear();
|
||||
s_presentationDepth = 0;
|
||||
s_cameraPresentationActive = false;
|
||||
}
|
||||
@@ -128,6 +130,7 @@ void begin_sim_tick() {
|
||||
camera_on_sim_tick();
|
||||
++s_simTickSeq;
|
||||
particle::prune();
|
||||
vertex::prune();
|
||||
}
|
||||
|
||||
uint64_t sim_tick_seq() {
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
#include "vertex.h"
|
||||
|
||||
#include "frame_interpolation.h"
|
||||
#include "dusk/game_clock.h"
|
||||
#include "JSystem/J3DGraphBase/J3DVertex.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace dusk::interp::vertex {
|
||||
namespace {
|
||||
|
||||
struct Array {
|
||||
std::vector<Vec> previous;
|
||||
std::vector<Vec> current;
|
||||
std::vector<Vec> presentation;
|
||||
const void* source = nullptr;
|
||||
float cached_step = -1.0f;
|
||||
|
||||
void capture(const void* data, u32 count, bool continuous, bool same_tick) {
|
||||
source = data;
|
||||
cached_step = -1.0f;
|
||||
if (data == nullptr || count == 0) {
|
||||
*this = {};
|
||||
return;
|
||||
}
|
||||
continuous &= current.size() == count;
|
||||
if (continuous && !same_tick) previous.swap(current);
|
||||
const auto* values = static_cast<const Vec*>(data);
|
||||
current.assign(values, values + count);
|
||||
if (!continuous) previous = current;
|
||||
}
|
||||
|
||||
void* read(void* requested, float step) {
|
||||
if (requested != source || current.empty() || step >= 1.0f) return requested;
|
||||
if (step <= 0.0f) return previous.data();
|
||||
if (step != cached_step) {
|
||||
presentation.resize(current.size());
|
||||
for (size_t i = 0; i < current.size(); ++i) {
|
||||
const auto& a = previous[i];
|
||||
const auto& b = current[i];
|
||||
presentation[i] = {a.x + (b.x - a.x) * step,
|
||||
a.y + (b.y - a.y) * step,
|
||||
a.z + (b.z - a.z) * step};
|
||||
}
|
||||
cached_step = step;
|
||||
}
|
||||
return presentation.data();
|
||||
}
|
||||
};
|
||||
|
||||
struct Record {
|
||||
const J3DDeformData* deformation = nullptr;
|
||||
const J3DVertexData* layout = nullptr;
|
||||
uint64_t tick = 0;
|
||||
uint64_t epoch = 0;
|
||||
Array positions;
|
||||
Array normals;
|
||||
};
|
||||
|
||||
auto& records() {
|
||||
static std::unordered_map<const J3DVertexBuffer*, Record> stored;
|
||||
return stored;
|
||||
}
|
||||
|
||||
void* read(const J3DVertexBuffer* buffer, void* current, Array Record::* array) {
|
||||
if (!is_enabled() || !is_presentation_active()) return current;
|
||||
auto it = records().find(buffer);
|
||||
if (it == records().end() || it->second.tick != sim_tick_seq() ||
|
||||
it->second.epoch != game_clock::g_frameTiming.presentationEpoch)
|
||||
{
|
||||
return current;
|
||||
}
|
||||
return (it->second.*array).read(current, get_interpolation_step());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void capture(J3DVertexBuffer* buffer, const J3DDeformData* deformation) {
|
||||
if (!should_capture() || is_presentation_active()) return;
|
||||
if (deformation == nullptr) {
|
||||
reset(buffer);
|
||||
return;
|
||||
}
|
||||
auto* layout = buffer->getVertexData();
|
||||
void* positions = buffer->getCurrentVtxPos();
|
||||
void* normals = buffer->getCurrentVtxNrm();
|
||||
if (layout->getVtxNum() == 0 || layout->getVtxPosType() != GX_F32 ||
|
||||
positions == layout->getVtxPosArray()) positions = nullptr;
|
||||
if (layout->getNrmNum() == 0 || layout->getVtxNrmType() != GX_F32 ||
|
||||
normals == layout->getVtxNrmArray()) normals = nullptr;
|
||||
if (positions == nullptr && normals == nullptr) {
|
||||
reset(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
auto& record = records()[buffer];
|
||||
const uint64_t tick = sim_tick_seq();
|
||||
const uint64_t epoch = game_clock::g_frameTiming.presentationEpoch;
|
||||
const bool same_tick = record.tick == tick;
|
||||
const bool continuous = record.deformation == deformation && record.layout == layout &&
|
||||
record.epoch == epoch && (same_tick || record.tick + 1 == tick);
|
||||
|
||||
record.positions.capture(positions, layout->getVtxNum(), continuous, same_tick);
|
||||
record.normals.capture(normals, layout->getNrmNum(), continuous, same_tick);
|
||||
record.deformation = deformation;
|
||||
record.layout = layout;
|
||||
record.tick = tick;
|
||||
record.epoch = epoch;
|
||||
}
|
||||
|
||||
void* positions(const J3DVertexBuffer* buffer, void* current) { return read(buffer, current, &Record::positions); }
|
||||
void* normals(const J3DVertexBuffer* buffer, void* current) { return read(buffer, current, &Record::normals); }
|
||||
void reset(const J3DVertexBuffer* buffer) { records().erase(buffer); }
|
||||
|
||||
void invalidate(const J3DDeformData* deformation) {
|
||||
std::erase_if(records(), [=](const auto& entry) { return entry.second.deformation == deformation; });
|
||||
}
|
||||
|
||||
void prune() {
|
||||
const uint64_t tick = sim_tick_seq();
|
||||
const uint64_t epoch = game_clock::g_frameTiming.presentationEpoch;
|
||||
std::erase_if(records(), [=](const auto& entry) {
|
||||
return entry.second.epoch != epoch || entry.second.tick < tick - (tick != 0);
|
||||
});
|
||||
}
|
||||
|
||||
void clear() { records().clear(); }
|
||||
|
||||
} // namespace dusk::interp::vertex
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
class J3DVertexBuffer;
|
||||
class J3DDeformData;
|
||||
|
||||
namespace dusk::interp::vertex {
|
||||
|
||||
void capture(J3DVertexBuffer* buffer, const J3DDeformData* deformation);
|
||||
void* positions(const J3DVertexBuffer* buffer, void* current);
|
||||
void* normals(const J3DVertexBuffer* buffer, void* current);
|
||||
void reset(const J3DVertexBuffer* buffer);
|
||||
void invalidate(const J3DDeformData* deformation);
|
||||
void prune();
|
||||
void clear();
|
||||
|
||||
} // namespace dusk::interp::vertex
|
||||
Reference in New Issue
Block a user