Interp BLK/BLS deformations

This commit is contained in:
Irastris
2026-09-11 15:46:00 -04:00
parent 9a94b3901b
commit 2c48204d42
7 changed files with 178 additions and 7 deletions
+1
View File
@@ -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));
}
+13 -3
View File
@@ -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());
}
+6 -3
View File
@@ -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() {
+131
View File
@@ -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
+16
View File
@@ -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