OpenGothic
Open source reimplementation of Gothic I and II
Loading...
Searching...
No Matches
visualobjects.cpp
Go to the documentation of this file.
1#include "visualobjects.h"
2
3#include <Tempest/Log>
4#include <cassert>
5
7#include "gothic.h"
8
9using namespace Tempest;
10
22
23
25 void setPosition(const Tempest::Matrix4x4& m) {
26 for(int i=0; i<4; ++i)
27 for(int r=0; r<3; ++r)
28 pos[i][r] = m.at(i,r);
29 }
30 float pos[4][3] = {};
31 float fatness = 0;
32 uint32_t animPtr = 0;
33 uint32_t padd0 = {};
34 uint32_t padd1 = {};
35 };
36
38 uint32_t indexOffset = 0;
39 uint32_t sample0 = 0;
40 uint32_t sample1 = 0;
41 uint16_t alpha = 0;
42 uint16_t intensity = 0;
43 };
44
48
49
50void VisualObjects::Item::setObjMatrix(const Tempest::Matrix4x4& pos) {
51 if(owner!=nullptr) {
52 auto& obj = owner->objects[id];
53 if(obj.pos!=pos)
54 owner->updateRtAs(id);
55 obj.pos = pos;
56 owner->updateInstance(id);
57 }
58 }
59
61 if(owner!=nullptr) {
62 owner->setAsGhost(id, g);
63 }
64 }
65
67 if(owner!=nullptr) {
68 if(owner->objects[id].fatness == f)
69 return;
70 owner->objects[id].fatness = f;
71 owner->updateInstance(id);
72 }
73 }
74
75void VisualObjects::Item::setWind(zenkit::AnimationType m, float intensity) {
76 if(owner==nullptr)
77 return;
78
79 if(intensity!=0 && m==zenkit::AnimationType::NONE)
80 m = zenkit::AnimationType::WIND_ALT;
81
82 if(intensity==0)
83 m = zenkit::AnimationType::NONE;
84
85 auto& obj = owner->objects[id];
86
87 const auto prev = obj.wind;
88 obj.wind = m;
89 obj.windIntensity = intensity;
90
91 if(prev==m)
92 return;
93
94 if(prev!=zenkit::AnimationType::NONE)
95 owner->objectsWind.erase(id);
96 if(m!=zenkit::AnimationType::NONE)
97 owner->objectsWind.insert(id);
98 }
99
100void VisualObjects::Item::startMMAnim(std::string_view anim, float intensity, uint64_t timeUntil) {
101 if(owner!=nullptr)
102 owner->startMMAnim(id, anim, intensity, timeUntil);
103 }
104
106 if(owner==nullptr) {
107 static Material m;
108 return m;
109 }
110 auto& bx = *owner->objects[id].bucketId;
111 return bx.mat;
112 }
113
115 static Bounds dummy;
116 if(owner==nullptr)
117 return dummy;
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;
123 return dummy;
124 }
125
127 if(owner!=nullptr)
128 return owner->objects[id].pos;
129 return Matrix4x4();
130 }
131
133 if(owner==nullptr)
134 return nullptr;
135 auto& bx = *owner->objects[id].bucketId;
136 return bx.staticMesh;
137 }
138
139std::pair<uint32_t, uint32_t> VisualObjects::Item::meshSlice() const {
140 if(owner==nullptr)
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);
144 }
145
146
147VisualObjects::VisualObjects(const SceneGlobals& scene, const std::pair<Vec3, Vec3>& bbox)
148 : scene(scene), drawCmd(*this, bucketsMem, clustersMem, scene) {
149 objectsMorph.reserve(1024);
150 }
151
154
155void VisualObjects::updateInstance(size_t id, Matrix4x4* pos) {
156 auto& obj = objects[id];
157 if(obj.type==DrawCommands::Landscape)
158 return;
159
160 InstanceDesc d;
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));
165
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;
170 clustersMem.markClusters(cId);
171 }
172 }
173
174void VisualObjects::updateRtAs(size_t id) {
175 auto& obj = objects[id];
176 auto& mat = obj.bucketId->mat;
177
178 bool useBlas = toRtCategory(obj.type)!=RtScene::None;
179 if(mat.alpha==Material::Ghost)
180 useBlas = false;
181 if(mat.alpha!=Material::Solid && mat.alpha!=Material::AlphaTest && mat.alpha!=Material::Transparent)
182 useBlas = false;
183
184 if(!useBlas)
185 return;
186
187 auto& mesh = *obj.bucketId->staticMesh;
188 if(auto b = mesh.blas(obj.iboOff, obj.iboLen)) {
189 (void)b;
190 notifyTlas(mat, toRtCategory(obj.type));
191 }
192 }
193
195 size_t iboOff, size_t iboLen,
196 bool staticDraw) {
197 // return Item();
198 // 64x64 meshlets
199 assert(iboOff%PackedMesh::MaxInd==0);
200 assert(iboLen%PackedMesh::MaxInd==0);
201
202 if(mat.tex==nullptr) {
203 Log::e("no texture?!");
204 return VisualObjects::Item();
205 }
206 auto type = (staticDraw ? DrawCommands::Static : DrawCommands::Movable);
207 const size_t id = implAlloc();
208
209 Object& obj = objects[id];
210
211 if(mesh.morph.anim!=nullptr) {
212 type = DrawCommands::Morph;
213 }
214
215 obj.type = type;
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());
220 obj.clusterId = clusterId(*obj.bucketId, iboOff/PackedMesh::MaxInd, iboLen/PackedMesh::MaxInd, obj.bucketId.toInt(), obj.cmdId);
221 obj.alpha = mat.alpha;
222 obj.timeShift = -scene.tickCount;
223
224 if(obj.isEmpty())
225 return Item(); // null command
226
227 obj.objInstance = instanceMem.alloc(sizeof(InstanceDesc));
228 clustersMem[obj.clusterId].instanceId = obj.objInstance.offsetId<InstanceDesc>();
229
230 if(type==DrawCommands::Morph) {
231 obj.objMorphAnim = instanceMem.alloc(sizeof(MorphDesc)*Resources::MAX_MORPH_LAYERS);
232 obj.animPtr = obj.objMorphAnim.offsetId<MorphDesc>();
233 const MorphData d = {};
234 obj.objMorphAnim.set(&d, 0, sizeof(d));
235 }
236
237 updateInstance(id);
238 updateRtAs(id);
239 return Item(*this, id);
240 }
241
243 size_t iboOff, size_t iboLen,
244 const InstanceStorage::Id& anim) {
245 // return Item();
246 // 64x64 meshlets
247 assert(iboOff%PackedMesh::MaxInd==0);
248 assert(iboLen%PackedMesh::MaxInd==0);
249
250 if(mat.tex==nullptr) {
251 Log::e("no texture?!");
252 return VisualObjects::Item();
253 }
254
255 const size_t id = implAlloc();
256
257 Object& obj = objects[id];
258
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());
264 obj.clusterId = clusterId(*obj.bucketId, iboOff/PackedMesh::MaxInd, iboLen/PackedMesh::MaxInd, obj.bucketId.toInt(), obj.cmdId);
265 obj.alpha = mat.alpha;
266 obj.timeShift = -scene.tickCount;
267
268 if(obj.isEmpty())
269 return Item(); // null command
270 obj.animPtr = anim.offsetId<Matrix4x4>();
271 obj.objInstance = instanceMem.alloc(sizeof(InstanceDesc));
272 clustersMem[obj.clusterId].instanceId = obj.objInstance.offsetId<InstanceDesc>();
273
274 updateInstance(id);
275 updateRtAs(id);
276 return Item(*this, id);
277 }
278
280 size_t iboOff, size_t iboLen, const PackedMesh::Cluster* cluster,
281 DrawCommands::Type type) {
282 // return Item();
283 // 64x64 meshlets
284 assert(iboOff%PackedMesh::MaxInd==0);
285 assert(iboLen%PackedMesh::MaxInd==0);
286
287 const size_t id = implAlloc();
288
289 Object& obj = objects[id];
290
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());
296 obj.clusterId = clusterId(cluster, iboOff/PackedMesh::MaxInd, iboLen/PackedMesh::MaxInd, obj.bucketId.toInt(), obj.cmdId);
297 obj.alpha = mat.alpha;
298 obj.timeShift = -scene.tickCount;
299
300 if(obj.isEmpty())
301 return Item(); // null command
302 updateRtAs(id);
303 return Item(*this, id);
304 }
305
306size_t VisualObjects::implAlloc() {
307 if(!objectsFree.empty()) {
308 auto id = *objectsFree.begin();
309 objectsFree.erase(objectsFree.begin());
310 return id;
311 }
312
313 objects.resize(objects.size()+1);
314 return objects.size()-1;
315 }
316
317void VisualObjects::free(size_t id) {
318 Object& obj = objects[id];
319
320 const uint32_t meshletCount = (obj.iboLen/PackedMesh::MaxInd);
321 const uint32_t numCluster = (obj.type==DrawCommands::Landscape ? meshletCount : 1);
322
323 drawCmd.addClusters(obj.cmdId, -meshletCount);
324 clustersMem.free(obj.clusterId, numCluster);
325
326 if(obj.wind==zenkit::AnimationType::NONE)
327 objectsWind.erase(id);
328 if(obj.type==DrawCommands::Morph)
329 objectsMorph.erase(id);
330
331 obj = Object();
332 while(objects.size()>0) {
333 if(!objects.back().isEmpty())
334 break;
335 objects.pop_back();
336 objectsFree.erase(objects.size());
337 }
338 if(id<objects.size())
339 objectsFree.insert(id);
340 }
341
343 return instanceMem.alloc(size);
344 }
345
347 return instanceMem.realloc(id, size);
348 }
349
351 return drawCmd.resetRendering();
352 }
353
354const Tempest::StorageBuffer& VisualObjects::instanceSsbo() const {
355 return instanceMem.ssbo();
356 }
357
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))
360 return uint32_t(-1);
361
362 const auto ret = clustersMem.alloc(cx, firstMeshlet, meshletCount, bucketId, commandId);
363 drawCmd.addClusters(commandId, uint32_t(meshletCount));
364 return uint32_t(ret);
365 }
366
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))
369 return uint32_t(-1);
370
371 const auto ret = clustersMem.alloc(bucket, firstMeshlet, meshletCount, bucketId, commandId);
372 drawCmd.addClusters(commandId, uint32_t(meshletCount));
373 return uint32_t(ret);
374 }
375
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)
380 return;
381
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) {
386 id = i;
387 break;
388 }
389
390 if(id==size_t(-1))
391 return;
392
393 objectsMorph.insert(i);
394
395 auto& m = anim[id];
396 if(timeUntil==uint64_t(-1) && m.duration>0)
397 timeUntil = scene.tickCount + m.duration;
398
399 // extend time of anim
400 for(auto& i:obj.morphAnim) {
401 if(i.id!=id || i.timeUntil<scene.tickCount)
402 continue;
403 i.timeUntil = timeUntil;
404 i.intensity = intensity;
405 return;
406 }
407
408 // find same layer
409 for(auto& i:obj.morphAnim) {
410 if(i.timeUntil<scene.tickCount)
411 continue;
412 if(anim[i.id].layer!=m.layer)
413 continue;
414 i.id = id;
415 i.timeUntil = timeUntil;
416 i.intensity = intensity;
417 return;
418 }
419
420 size_t nId = 0;
421 for(size_t i=0; i<Resources::MAX_MORPH_LAYERS; ++i) {
422 if(obj.morphAnim[nId].timeStart<=obj.morphAnim[i].timeStart)
423 continue;
424 nId = i;
425 }
426
427 auto& ani = obj.morphAnim[nId];
428 ani.id = id;
429 ani.timeStart = scene.tickCount;
430 ani.timeUntil = timeUntil;
431 ani.intensity = intensity;
432 }
433
434void VisualObjects::setAsGhost(size_t id, bool g) {
435 auto& obj= objects[id];
436 if(obj.isGhost==g)
437 return;
438
439 auto& bx = *obj.bucketId;
440 auto& cx = drawCmd[obj.cmdId];
441 auto mat = bx.mat;
442
443 const uint32_t meshletCount = (obj.iboLen/PackedMesh::MaxInd);
444 drawCmd.addClusters(obj.cmdId, -meshletCount);
445
446 mat.alpha = g ? Material::Ghost : obj.alpha;
447 obj.isGhost = g;
448
449 if(bx.staticMesh!=nullptr)
450 obj.bucketId = bucketsMem.alloc(mat, *bx.staticMesh); else
451 obj.bucketId = bucketsMem.alloc(mat, *bx.animMesh);
452
453 obj.cmdId = drawCmd.commandId(mat, cx.type, obj.bucketId.toInt());
454 drawCmd.addClusters(obj.cmdId, +meshletCount);
455
456 const uint32_t numCluster = (obj.type==DrawCommands::Landscape ? meshletCount : 1);
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();
460 clustersMem.markClusters(obj.clusterId + i);
461 }
462 }
463
464void VisualObjects::prepareGlobals(Encoder<CommandBuffer>& enc, uint8_t fId) {
465 instanceMem.commit(enc, fId);
466 clustersMem.commit(enc, fId);
467 drawCmd.commit(enc);
468 bucketsMem.commit(enc, fId);
469 }
470
472 preFrameUpdateWind();
473 preFrameUpdateMorph();
474 }
475
476void VisualObjects::preFrameUpdateWind() {
477 if(!scene.zWindEnabled)
478 return;
479
480 const uint64_t period = scene.windPeriod;
481 float ax = float(scene.tickCount%period)/float(period);
482 ax = ax*2.f-1.f;
483
484 for(auto id:objectsWind) {
485 auto& i = objects[id];
486 float m = 0;
487
488 switch(i.wind) {
489 case zenkit::AnimationType::WIND:
490 // tree. note: mods tent to bump Intensity to insane values
491 if(i.windIntensity>0.f)
492 m = 0.03f; else
493 m = 0;
494 break;
495 case zenkit::AnimationType::WIND_ALT:
496 // grass
497 if(i.windIntensity>0.f && i.windIntensity<=1.0)
498 m = i.windIntensity * 0.1f; else
499 m = 0;
500 break;
501 case zenkit::AnimationType::NONE:
502 default:
503 // error
504 m = 0.f;
505 break;
506 }
507
508 auto pos = i.pos;
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);
511
512 pos[1][0] += scene.windDir.x*a;
513 pos[1][2] += scene.windDir.y*a;
514
515 updateInstance(id, &pos);
516 }
517 }
518
519void VisualObjects::preFrameUpdateMorph() {
520 for(auto it=objectsMorph.begin(); it!=objectsMorph.end(); ) {
521 auto& obj = objects[*it];
522
523 bool reschedule = false;
524 MorphData data = {};
525 for(size_t i=0; i<Resources::MAX_MORPH_LAYERS; ++i) {
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);
530
531 float alpha = float(time%anim.tickPerFrame)/float(anim.tickPerFrame);
532 float intensity = ani.intensity;
533
534 if(scene.tickCount>ani.timeUntil) {
535 data.morph[i].intensity = 0;
536 continue;
537 }
538
539 if(anim.numFrames>1)
540 reschedule = true;
541
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));
548 }
549
550 obj.objMorphAnim.set(&data, 0, sizeof(data));
551 if(!reschedule)
552 it = objectsMorph.erase(it); else
553 it++;
554 }
555 }
556
557void VisualObjects::visibilityPass(Tempest::Encoder<Tempest::CommandBuffer> &cmd, int pass) {
558 drawCmd.visibilityPass(cmd, pass);
559 }
560
561void VisualObjects::visibilityVsm(Tempest::Encoder<Tempest::CommandBuffer>& cmd) {
562 drawCmd.visibilityVsm(cmd);
563 }
564
565void VisualObjects::drawTranslucent(Tempest::Encoder<Tempest::CommandBuffer>& cmd) {
566 // return;
572 }
573
574void VisualObjects::drawWater(Tempest::Encoder<Tempest::CommandBuffer>& cmd) {
575 // return;
577 }
578
579void VisualObjects::drawGBuffer(Tempest::Encoder<CommandBuffer>& cmd) {
580 // return;
583 }
584
585void VisualObjects::drawShadow(Tempest::Encoder<Tempest::CommandBuffer>& cmd, int layer) {
586 // return;
588 drawCmd.drawCommon(cmd, view, Material::Solid);
589 drawCmd.drawCommon(cmd, view, Material::AlphaTest);
590 }
591
592void VisualObjects::drawVsm(Tempest::Encoder<Tempest::CommandBuffer>& cmd) {
593 drawCmd.drawVsm(cmd);
594 }
595
596void VisualObjects::drawHiZ(Tempest::Encoder<Tempest::CommandBuffer>& cmd) {
597 drawCmd.drawHiZ(cmd);
598 }
599
600void VisualObjects::notifyTlas(const Material& m, RtScene::Category cat) {
601 scene.rtScene.notifyTlas(m,cat);
602 }
603
605 instanceMem.join();
606 }
607
609 if(!out.isUpdateRequired())
610 return false;
611 for(auto& obj:objects) {
612 if(obj.isEmpty())
613 continue;
614 auto& bucket = *obj.bucketId;
615 auto* mesh = bucket.staticMesh;
616 auto& mat = bucket.mat;
617 if(mesh==nullptr)
618 continue;
619 if(auto blas = mesh->blas(obj.iboOff, obj.iboLen)) {
620 out.addInstance(obj.pos, *blas, mat, *mesh, obj.iboOff, obj.iboLen, toRtCategory(obj.type));
621 }
622 }
623 out.buildTlas();
624 return true;
625 }
626
627void VisualObjects::dbgClusters(Tempest::Painter& p, Vec2 wsz) {
628 auto cam = Gothic::inst().camera();
629 if(cam==nullptr)
630 return;
631 /*
632 for(auto& c:clusters) {
633 dbgDraw(p, wsz, *cam, c);
634 }
635 */
636
637 /*
638 if(auto pl = Gothic::inst().player()) {
639 Cluster cx;
640 cx.pos = pl->position();
641 cx.r = 100;
642 dbgDraw(p, wsz, *cam, cx);
643 }
644 */
645 }
646
647void VisualObjects::dbgDraw(Tempest::Painter& p, Vec2 wsz, const Camera& cam, const DrawClusters::Cluster& cx) {
648 auto c = cx.pos;
649 auto project = cam.projective();
650
651 cam.view().project(c);
652 //const vec3 c = (scene.view * vec4(sphere.xyz, 1)).xyz;
653 const float R = cx.r;
654 const float znear = cam.zNear();
655 if(c.z - R < znear)
656 ;//return;
657
658 // depthMin = znear / (c.z + r);
659 // float z = c.z + R;
660 // depthMin = scene.project[3][2]/z + scene.project[2][2];
661
662 float P00 = project[0][0];
663 float P11 = project[1][1];
664
665 Vec3 cr = c * R;
666 float czr2 = c.z * c.z - R * R;
667
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);
671
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);
675
676 Vec4 aabb;
677 aabb = Vec4(minx * P00, miny * P11, maxx * P00, maxy * P11);
678 aabb = aabb*0.5 + Vec4(0.5);
679
680 aabb.x = aabb.x * wsz.x;
681 aabb.z = aabb.z * wsz.x;
682
683 aabb.y = aabb.y * wsz.y;
684 aabb.w = aabb.w * wsz.y;
685
686 if(aabb.x>=aabb.z)
687 Log::d("");
688 if(aabb.y>=aabb.w)
689 Log::d("");
690
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));
693 }
694
695void VisualObjects::dbgDrawBBox(Tempest::Painter& p, Tempest::Vec2 wsz, const Camera& cam, const DrawClusters::Cluster& c) {
696 /*
697 auto& b = buckets[c.bucketId];
698 auto project = cam.viewProj();
699
700 Vec4 aabb = Vec4(1, 1, -1, -1);
701 float depthMin = 1;
702 for(uint32_t i=0; i<8; ++i) {
703 float x = b[i&0x1 ? 1 : 0].x;
704 float y = b[i&0x2 ? 1 : 0].y;
705 float z = b[i&0x4 ? 1 : 0].z;
706
707 const Vec3 pos = Vec3(x, y, z);
708 Vec4 trPos = Vec4(pos,1.0);
709 trPos = Vec4(obj.mat*trPos, 1.0);
710 trPos = scene.viewProject*trPos;
711 if(trPos.w<znear || false) {
712 depthMin = 0;
713 aabb = vec4(0,0,1,1);
714 return true;
715 }
716
717 vec3 bp = trPos.xyz/trPos.w;
718
719 aabb.xy = min(aabb.xy, bp.xy);
720 aabb.zw = max(aabb.zw, bp.xy);
721 depthMin = min(depthMin, bp.z);
722 }
723 aabb = aabb*0.5 + Vec4(0.5);
724
725 aabb.x = aabb.x * wsz.x;
726 aabb.z = aabb.z * wsz.x;
727
728 aabb.y = aabb.y * wsz.y;
729 aabb.w = aabb.w * wsz.y;
730
731 if(aabb.x>=aabb.z)
732 Log::d("");
733 if(aabb.y>=aabb.w)
734 Log::d("");
735
736 p.setBrush(Color(0,0,1,0.1f));
737 p.drawRect(int(aabb.x), int(aabb.y), int(aabb.z-aabb.x), int(aabb.w-aabb.y));
738 */
739 }
740
Tempest::Vec3 bbox[2]
Definition bounds.h:22
Tempest::Matrix4x4 view() const
Definition camera.cpp:915
Tempest::Matrix4x4 projective() const
Definition camera.cpp:259
float zNear() const
Definition camera.cpp:97
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 resetRendering()
void visibilityPass(Tempest::Encoder< Tempest::CommandBuffer > &cmd, int pass)
Camera * camera()
Definition gothic.cpp:319
static Gothic & inst()
Definition gothic.cpp:249
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)
@ AdditiveLight
Definition material.h:25
@ Multiply2
Definition material.h:23
@ Multiply
Definition material.h:22
@ Transparent
Definition material.h:24
@ AlphaTest
Definition material.h:19
const Tempest::Texture2d * tex
Definition material.h:28
AlphaFunc alpha
Definition material.h:30
static const size_t MAX_MORPH_LAYERS
Definition resources.h:53
void notifyTlas(const Material &m, RtScene::Category cat) const
Definition rtscene.cpp:12
void addInstance(const Tempest::Matrix4x4 &pos, const Tempest::AccelerationStructure &blas, const Material &mat, const StaticMesh &mesh, size_t firstIndex, size_t iboLength, Category cat)
@ Static
Definition rtscene.h:20
@ None
Definition rtscene.h:18
@ Movable
Definition rtscene.h:21
@ Landscape
Definition rtscene.h:19
bool isUpdateRequired() const
Definition rtscene.cpp:20
void buildTlas()
Definition rtscene.cpp:106
uint64_t windPeriod
RtScene rtScene
uint64_t tickCount
Tempest::Vec2 windDir
MorphAnim morph
Definition staticmesh.h:53
std::pair< uint32_t, uint32_t > meshSlice() const
const Bounds & bounds() const
const Material & material() const
void setAsGhost(bool g)
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
void setFatness(float f)
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
Definition drawbuckets.h:16
const std::vector< Morph > * anim
Definition staticmesh.h:43
void setPosition(const Tempest::Matrix4x4 &m)
MorphDesc morph[Resources::MAX_MORPH_LAYERS]
static RtScene::Category toRtCategory(DrawCommands::Type t)