9using namespace Tempest;
26 for(
int i=0; i<4; ++i)
27 for(
int r=0; r<3; ++r)
28 pos[i][r] = m.at(i,r);
52 auto& obj = owner->objects[id];
54 owner->updateRtAs(
id);
56 owner->updateInstance(
id);
62 owner->setAsGhost(
id, g);
68 if(owner->objects[
id].fatness == f)
70 owner->objects[id].fatness = f;
71 owner->updateInstance(
id);
79 if(intensity!=0 && m==zenkit::AnimationType::NONE)
80 m = zenkit::AnimationType::WIND_ALT;
83 m = zenkit::AnimationType::NONE;
85 auto& obj = owner->objects[id];
87 const auto prev = obj.wind;
89 obj.windIntensity = intensity;
94 if(prev!=zenkit::AnimationType::NONE)
95 owner->objectsWind.erase(
id);
96 if(m!=zenkit::AnimationType::NONE)
97 owner->objectsWind.insert(
id);
102 owner->startMMAnim(
id, anim, intensity, timeUntil);
110 auto& bx = *owner->objects[id].bucketId;
118 auto& bx = *owner->objects[id].bucketId;
119 if(bx.staticMesh!=
nullptr)
120 return bx.staticMesh->
bbox;
121 if(bx.animMesh!=
nullptr)
122 return bx.animMesh->bbox;
128 return owner->objects[id].pos;
135 auto& bx = *owner->objects[id].bucketId;
136 return bx.staticMesh;
141 return std::pair<uint32_t, uint32_t>(0,0);
142 auto& obj = owner->objects[id];
143 return std::make_pair(obj.iboOff, obj.iboLen);
148 : scene(scene), drawCmd(*this, bucketsMem, clustersMem, scene) {
149 objectsMorph.reserve(1024);
155void VisualObjects::updateInstance(
size_t id, Matrix4x4* pos) {
156 auto& obj = objects[id];
161 d.setPosition(pos==
nullptr ? obj.pos : *pos);
162 d.animPtr = obj.animPtr;
163 d.fatness = obj.fatness*0.5f;
164 obj.objInstance.set(&d, 0,
sizeof(d));
166 auto cId = obj.clusterId;
167 auto npos = Vec3(obj.pos[3][0], obj.pos[3][1], obj.pos[3][2]);
168 if(clustersMem[cId].pos != npos) {
169 clustersMem[cId].pos = npos;
174void VisualObjects::updateRtAs(
size_t id) {
175 auto& obj = objects[id];
176 auto& mat = obj.bucketId->mat;
187 auto& mesh = *obj.bucketId->staticMesh;
188 if(
auto b = mesh.blas(obj.iboOff, obj.iboLen)) {
195 size_t iboOff,
size_t iboLen,
202 if(mat.
tex==
nullptr) {
203 Log::e(
"no texture?!");
207 const size_t id = implAlloc();
209 Object& obj = objects[id];
216 obj.iboOff = uint32_t(iboOff);
217 obj.iboLen = uint32_t(iboLen);
218 obj.bucketId = bucketsMem.
alloc(mat, mesh);
219 obj.cmdId = drawCmd.
commandId(mat, obj.type, obj.bucketId.toInt());
221 obj.alpha = mat.
alpha;
228 clustersMem[obj.clusterId].instanceId = obj.objInstance.offsetId<
InstanceDesc>();
234 obj.objMorphAnim.set(&d, 0,
sizeof(d));
239 return Item(*
this,
id);
243 size_t iboOff,
size_t iboLen,
250 if(mat.
tex==
nullptr) {
251 Log::e(
"no texture?!");
255 const size_t id = implAlloc();
257 Object& obj = objects[id];
260 obj.iboOff = uint32_t(iboOff);
261 obj.iboLen = uint32_t(iboLen);
262 obj.bucketId = bucketsMem.
alloc(mat, mesh);
263 obj.cmdId = drawCmd.
commandId(mat, obj.type, obj.bucketId.toInt());
265 obj.alpha = mat.
alpha;
270 obj.animPtr = anim.
offsetId<Matrix4x4>();
272 clustersMem[obj.clusterId].instanceId = obj.objInstance.offsetId<
InstanceDesc>();
276 return Item(*
this,
id);
287 const size_t id = implAlloc();
289 Object& obj = objects[id];
292 obj.iboOff = uint32_t(iboOff);
293 obj.iboLen = uint32_t(iboLen);
294 obj.bucketId = bucketsMem.
alloc(mat, mesh);
295 obj.cmdId = drawCmd.
commandId(mat, type, obj.bucketId.toInt());
297 obj.alpha = mat.
alpha;
303 return Item(*
this,
id);
306size_t VisualObjects::implAlloc() {
307 if(!objectsFree.empty()) {
308 auto id = *objectsFree.begin();
309 objectsFree.erase(objectsFree.begin());
313 objects.resize(objects.size()+1);
314 return objects.size()-1;
317void VisualObjects::free(
size_t id) {
318 Object& obj = objects[id];
324 clustersMem.
free(obj.clusterId, numCluster);
326 if(obj.wind==zenkit::AnimationType::NONE)
327 objectsWind.erase(
id);
329 objectsMorph.erase(
id);
332 while(objects.size()>0) {
333 if(!objects.back().isEmpty())
336 objectsFree.erase(objects.size());
338 if(
id<objects.size())
339 objectsFree.insert(
id);
343 return instanceMem.
alloc(size);
347 return instanceMem.
realloc(
id, size);
355 return instanceMem.
ssbo();
358uint32_t VisualObjects::clusterId(
const PackedMesh::Cluster* cx,
size_t firstMeshlet,
size_t meshletCount, uint16_t bucketId, uint16_t commandId) {
359 if(commandId==uint16_t(-1))
362 const auto ret = clustersMem.
alloc(cx, firstMeshlet, meshletCount, bucketId, commandId);
363 drawCmd.
addClusters(commandId, uint32_t(meshletCount));
364 return uint32_t(ret);
367uint32_t VisualObjects::clusterId(
const DrawBuckets::Bucket& bucket,
size_t firstMeshlet,
size_t meshletCount, uint16_t bucketId, uint16_t commandId) {
368 if(commandId==uint16_t(-1))
371 const auto ret = clustersMem.
alloc(bucket, firstMeshlet, meshletCount, bucketId, commandId);
372 drawCmd.
addClusters(commandId, uint32_t(meshletCount));
373 return uint32_t(ret);
376void VisualObjects::startMMAnim(
size_t i, std::string_view animName,
float intensity, uint64_t timeUntil) {
377 auto& obj = objects[i];
378 auto staticMesh = obj.bucketId->staticMesh;
379 if(staticMesh==
nullptr || staticMesh->morph.anim==
nullptr)
382 auto& anim = *staticMesh->morph.anim;
383 size_t id = size_t(-1);
384 for(
size_t i=0; i<anim.size(); ++i)
385 if(anim[i].name==animName) {
393 objectsMorph.insert(i);
396 if(timeUntil==uint64_t(-1) && m.duration>0)
397 timeUntil = scene.
tickCount + m.duration;
400 for(
auto& i:obj.morphAnim) {
401 if(i.id!=
id || i.timeUntil<scene.
tickCount)
403 i.timeUntil = timeUntil;
404 i.intensity = intensity;
409 for(
auto& i:obj.morphAnim) {
412 if(anim[i.id].layer!=m.layer)
415 i.timeUntil = timeUntil;
416 i.intensity = intensity;
422 if(obj.morphAnim[nId].timeStart<=obj.morphAnim[i].timeStart)
427 auto& ani = obj.morphAnim[nId];
430 ani.timeUntil = timeUntil;
431 ani.intensity = intensity;
434void VisualObjects::setAsGhost(
size_t id,
bool g) {
435 auto& obj= objects[id];
439 auto& bx = *obj.bucketId;
440 auto& cx = drawCmd[obj.cmdId];
449 if(bx.staticMesh!=
nullptr)
450 obj.bucketId = bucketsMem.
alloc(mat, *bx.staticMesh);
else
451 obj.bucketId = bucketsMem.
alloc(mat, *bx.animMesh);
453 obj.cmdId = drawCmd.
commandId(mat, cx.type, obj.bucketId.toInt());
457 for(
size_t i=0; i<numCluster; ++i) {
458 clustersMem[obj.clusterId + i].commandId = obj.cmdId;
459 clustersMem[obj.clusterId + i].bucketId = obj.bucketId.toInt();
465 instanceMem.
commit(enc, fId);
466 clustersMem.
commit(enc, fId);
468 bucketsMem.
commit(enc, fId);
472 preFrameUpdateWind();
473 preFrameUpdateMorph();
476void VisualObjects::preFrameUpdateWind() {
481 float ax = float(scene.
tickCount%period)/float(period);
484 for(
auto id:objectsWind) {
485 auto& i = objects[id];
489 case zenkit::AnimationType::WIND:
491 if(i.windIntensity>0.f)
495 case zenkit::AnimationType::WIND_ALT:
497 if(i.windIntensity>0.f && i.windIntensity<=1.0)
498 m = i.windIntensity * 0.1f;
else
501 case zenkit::AnimationType::NONE:
509 float shift = i.pos[3][0]*scene.
windDir.x + i.pos[3][2]*scene.
windDir.y;
510 const float a = m * std::cos(
float(ax*M_PI) + shift*0.0001f);
512 pos[1][0] += scene.
windDir.x*a;
513 pos[1][2] += scene.
windDir.y*a;
515 updateInstance(
id, &pos);
519void VisualObjects::preFrameUpdateMorph() {
520 for(
auto it=objectsMorph.begin(); it!=objectsMorph.end(); ) {
521 auto& obj = objects[*it];
523 bool reschedule =
false;
526 auto& ani = obj.morphAnim[i];
527 auto& bk = *obj.bucketId;
528 auto& anim = (*bk.staticMesh->morph.anim)[ani.id];
529 uint64_t time = (scene.
tickCount-ani.timeStart);
531 float alpha = float(time%anim.tickPerFrame)/float(anim.tickPerFrame);
532 float intensity = ani.intensity;
535 data.morph[i].intensity = 0;
542 const uint32_t samplesPerFrame = uint32_t(anim.samplesPerFrame);
543 data.morph[i].indexOffset = uint32_t(anim.index);
544 data.morph[i].sample0 = uint32_t((time/anim.tickPerFrame+0)%anim.numFrames)*samplesPerFrame;
545 data.morph[i].sample1 = uint32_t((time/anim.tickPerFrame+1)%anim.numFrames)*samplesPerFrame;
546 data.morph[i].alpha = uint16_t(alpha*uint16_t(-1));
547 data.morph[i].intensity = uint16_t(intensity*uint16_t(-1));
550 obj.objMorphAnim.set(&data, 0,
sizeof(data));
552 it = objectsMorph.erase(it);
else
611 for(
auto& obj:objects) {
614 auto& bucket = *obj.bucketId;
616 auto& mat = bucket.
mat;
619 if(
auto blas = mesh->blas(obj.iboOff, obj.iboLen)) {
651 cam.
view().project(c);
653 const float R = cx.
r;
654 const float znear = cam.
zNear();
662 float P00 = project[0][0];
663 float P11 = project[1][1];
666 float czr2 = c.z * c.z - R * R;
668 float vx = std::sqrt(c.x * c.x + czr2);
669 float minx = (vx * c.x - cr.z) / (vx * c.z + cr.x);
670 float maxx = (vx * c.x + cr.z) / (vx * c.z - cr.x);
672 float vy = std::sqrt(c.y * c.y + czr2);
673 float miny = (vy * c.y - cr.z) / (vy * c.z + cr.y);
674 float maxy = (vy * c.y + cr.z) / (vy * c.z - cr.y);
677 aabb = Vec4(minx * P00, miny * P11, maxx * P00, maxy * P11);
678 aabb = aabb*0.5 + Vec4(0.5);
680 aabb.x = aabb.x * wsz.x;
681 aabb.z = aabb.z * wsz.x;
683 aabb.y = aabb.y * wsz.y;
684 aabb.w = aabb.w * wsz.y;
691 p.setBrush(Color(0,0,1,0.1f));
692 p.drawRect(
int(aabb.x),
int(aabb.y),
int(aabb.z-aabb.x),
int(aabb.w-aabb.y));
Tempest::Matrix4x4 view() const
Tempest::Matrix4x4 projective() const
Id alloc(const Material &mat, const StaticMesh &mesh)
bool commit(Tempest::Encoder< Tempest::CommandBuffer > &cmd, uint8_t fId)
bool commit(Tempest::Encoder< Tempest::CommandBuffer > &cmd, uint8_t fId)
uint32_t alloc(const PackedMesh::Cluster *cluster, size_t firstMeshlet, size_t meshletCount, uint16_t bucketId, uint16_t commandId)
void free(uint32_t id, uint32_t numCluster)
void markClusters(size_t id, size_t count=1)
void addClusters(uint16_t cmdId, uint32_t meshletCount)
void visibilityVsm(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
uint16_t commandId(const Material &m, Type type, uint32_t bucketId)
void drawVsm(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
void drawHiZ(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
void commit(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
void drawCommon(Tempest::Encoder< Tempest::CommandBuffer > &cmd, SceneGlobals::VisCamera viewId, Material::AlphaFunc func)
void visibilityPass(Tempest::Encoder< Tempest::CommandBuffer > &cmd, int pass)
const uint32_t offsetId() const
Id alloc(const size_t size)
bool commit(Tempest::Encoder< Tempest::CommandBuffer > &cmd, uint8_t fId)
auto ssbo() const -> const Tempest::StorageBuffer &
bool realloc(Id &id, const size_t size)
const Tempest::Texture2d * tex
static const size_t MAX_MORPH_LAYERS
void notifyTlas(const Material &m, RtScene::Category cat) const
void addInstance(const Tempest::Matrix4x4 &pos, const Tempest::AccelerationStructure &blas, const Material &mat, const StaticMesh &mesh, size_t firstIndex, size_t iboLength, Category cat)
bool isUpdateRequired() const
std::pair< uint32_t, uint32_t > meshSlice() const
const Bounds & bounds() const
const Material & material() const
void startMMAnim(std::string_view anim, float intensity, uint64_t timeUntil)
const StaticMesh * mesh() const
void setWind(zenkit::AnimationType m, float intensity)
void setObjMatrix(const Tempest::Matrix4x4 &mt)
Tempest::Matrix4x4 position() const
bool updateRtScene(RtScene &out)
auto instanceSsbo() const -> const Tempest::StorageBuffer &
void drawGBuffer(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
void visibilityVsm(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
void dbgClusters(Tempest::Painter &p, Tempest::Vec2 wsz)
Item get(const StaticMesh &mesh, const Material &mat, size_t iboOffset, size_t iboLength, bool staticDraw)
void prepareGlobals(Tempest::Encoder< Tempest::CommandBuffer > &cmd, uint8_t fId)
void drawHiZ(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
void visibilityPass(Tempest::Encoder< Tempest::CommandBuffer > &cmd, int pass)
VisualObjects(const SceneGlobals &globals, const std::pair< Tempest::Vec3, Tempest::Vec3 > &bbox)
void drawWater(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
InstanceStorage::Id alloc(size_t size)
bool realloc(InstanceStorage::Id &id, size_t size)
void drawTranslucent(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
void drawVsm(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
void drawShadow(Tempest::Encoder< Tempest::CommandBuffer > &cmd, int layer)
const StaticMesh * staticMesh
const std::vector< Morph > * anim
void setPosition(const Tempest::Matrix4x4 &m)
MorphDesc morph[Resources::MAX_MORPH_LAYERS]
static RtScene::Category toRtCategory(DrawCommands::Type t)