diff --git a/Content/Documentation/ScriptingAPI-Documentation.md b/Content/Documentation/ScriptingAPI-Documentation.md index e0efe32fb..093995207 100644 --- a/Content/Documentation/ScriptingAPI-Documentation.md +++ b/Content/Documentation/ScriptingAPI-Documentation.md @@ -508,9 +508,12 @@ The scene holds components. Entity handles can be used to retrieve associated co - [outer]GetCamera() : Camera result -- returns the global camera - [outer]LoadModel(string fileName, opt Matrix transform) : int rootEntity -- Load Model from file. returns a root entity that everything in this model is attached to - [outer]LoadModel(Scene scene, string fileName, opt Matrix transform) : int rootEntity -- Load Model from file into specified scene. returns a root entity that everything in this model is attached to -- [outer]Pick(Ray ray, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) : int entity, Vector position,normal, float distance -- Perform ray-picking in the scene. pickType is a bitmask specifying object types to check against. layerMask is a bitmask specifying which layers to check against. Scene parameter is optional and will use the global scene if not specified. -- [outer]SceneIntersectSphere(Sphere sphere, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) : int entity, Vector position,normal, float distance -- Perform ray-picking in the scene. pickType is a bitmask specifying object types to check against. layerMask is a bitmask specifying which layers to check against. Scene parameter is optional and will use the global scene if not specified. -- [outer]SceneIntersectCapsule(Capsule capsule, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) : int entity, Vector position,normal, float distance -- Perform ray-picking in the scene. pickType is a bitmask specifying object types to check against. layerMask is a bitmask specifying which layers to check against. Scene parameter is optional and will use the global scene if not specified. +- [outer]PICK_OPAQUE : uint +- [outer]PICK_TRANSPARENT : uint +- [outer]PICK_WATER : uint +- [outer]Pick(Ray ray, opt uint pickType = ~0, opt uint layerMask = ~0, opt Scene scene = GetScene(), uint lod = 0) : int entity, Vector position,normal, float distance -- Perform ray-picking in the scene. pickType is a bitmask specifying object types to check against. layerMask is a bitmask specifying which layers to check against. Scene parameter is optional and will use the global scene if not specified. +- [outer]SceneIntersectSphere(Sphere sphere, opt uint pickType = ~0, opt uint layerMask = ~0, opt Scene scene = GetScene(), opt uint lod = 0) : int entity, Vector position,normal, float distance -- Perform ray-picking in the scene. pickType is a bitmask specifying object types to check against. layerMask is a bitmask specifying which layers to check against. Scene parameter is optional and will use the global scene if not specified. +- [outer]SceneIntersectCapsule(Capsule capsule, opt uint pickType = ~0, opt uint layerMask = ~0, opt Scene scene = GetScene(), opt uint lod = 0) : int entity, Vector position,normal, float distance -- Perform ray-picking in the scene. pickType is a bitmask specifying object types to check against. layerMask is a bitmask specifying which layers to check against. Scene parameter is optional and will use the global scene if not specified. - Update() -- updates the scene and every entity and component inside the scene - Clear() -- deletes every entity and component inside the scene - Merge(Scene other) -- moves contents from an other scene into this one. The other scene will be empty after this operation (contents are moved, not copied) diff --git a/Editor/ComponentsWindow.cpp b/Editor/ComponentsWindow.cpp index c01bc7522..6730c8322 100644 --- a/Editor/ComponentsWindow.cpp +++ b/Editor/ComponentsWindow.cpp @@ -77,6 +77,15 @@ void ComponentsWindow::Create(EditorComponent* _editor) return; Scene& scene = editor->GetCurrentScene(); Entity entity = editor->translator.selected.back().entity; + if (args.userdata == 17) + { + // explanation: for softbody, we want to create it for the MeshComponent, if it's also selected together with the object: + ObjectComponent* object = scene.objects.GetComponent(entity); + if (object != nullptr) + { + entity = object->meshID; + } + } if (entity == INVALID_ENTITY) { assert(0); @@ -195,7 +204,6 @@ void ComponentsWindow::Create(EditorComponent* _editor) break; case 3: scene.lights.Create(entity); - scene.aabb_lights.Create(entity); break; case 4: scene.materials.Create(entity); @@ -225,7 +233,6 @@ void ComponentsWindow::Create(EditorComponent* _editor) break; case 8: scene.probes.Create(entity); - scene.aabb_probes.Create(entity); break; case 9: if (!scene.materials.Contains(entity)) @@ -241,7 +248,6 @@ void ComponentsWindow::Create(EditorComponent* _editor) if (!scene.materials.Contains(entity)) scene.materials.Create(entity); scene.decals.Create(entity); - scene.aabb_decals.Create(entity); break; case 12: scene.weathers.Create(entity); @@ -272,7 +278,6 @@ void ComponentsWindow::Create(EditorComponent* _editor) break; case 21: scene.objects.Create(entity); - scene.aabb_objects.Create(entity); break; default: break; diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index 225cb3b10..78176617c 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -1578,7 +1578,7 @@ void EditorComponent::Render() const const ObjectComponent* object = scene.objects.GetComponent(hovered.entity); if (object != nullptr) { - const AABB& aabb = *scene.aabb_objects.GetComponent(hovered.entity); + const AABB& aabb = scene.aabb_objects[scene.objects.GetIndex(hovered.entity)]; XMFLOAT4X4 hoverBox; XMStoreFloat4x4(&hoverBox, aabb.getAsBoxMatrix()); @@ -1588,7 +1588,7 @@ void EditorComponent::Render() const const LightComponent* light = scene.lights.GetComponent(hovered.entity); if (light != nullptr) { - const AABB& aabb = *scene.aabb_lights.GetComponent(hovered.entity); + const AABB& aabb = scene.aabb_lights[scene.lights.GetIndex(hovered.entity)]; XMFLOAT4X4 hoverBox; XMStoreFloat4x4(&hoverBox, aabb.getAsBoxMatrix()); @@ -1604,7 +1604,7 @@ void EditorComponent::Render() const const EnvironmentProbeComponent* probe = scene.probes.GetComponent(hovered.entity); if (probe != nullptr) { - const AABB& aabb = *scene.aabb_probes.GetComponent(hovered.entity); + const AABB& aabb = scene.aabb_probes[scene.probes.GetIndex(hovered.entity)]; XMFLOAT4X4 hoverBox; XMStoreFloat4x4(&hoverBox, aabb.getAsBoxMatrix()); @@ -1647,21 +1647,21 @@ void EditorComponent::Render() const const ObjectComponent* object = scene.objects.GetComponent(picked.entity); if (object != nullptr) { - const AABB& aabb = *scene.aabb_objects.GetComponent(picked.entity); + const AABB& aabb = scene.aabb_objects[scene.objects.GetIndex(picked.entity)]; selectedAABB = AABB::Merge(selectedAABB, aabb); } const LightComponent* light = scene.lights.GetComponent(picked.entity); if (light != nullptr) { - const AABB& aabb = *scene.aabb_lights.GetComponent(picked.entity); + const AABB& aabb = scene.aabb_lights[scene.lights.GetIndex(picked.entity)]; selectedAABB = AABB::Merge(selectedAABB, aabb); } const DecalComponent* decal = scene.decals.GetComponent(picked.entity); if (decal != nullptr) { - const AABB& aabb = *scene.aabb_decals.GetComponent(picked.entity); + const AABB& aabb = scene.aabb_decals[scene.decals.GetIndex(picked.entity)]; selectedAABB = AABB::Merge(selectedAABB, aabb); // also display decal OBB: @@ -1673,7 +1673,7 @@ void EditorComponent::Render() const const EnvironmentProbeComponent* probe = scene.probes.GetComponent(picked.entity); if (probe != nullptr) { - const AABB& aabb = *scene.aabb_probes.GetComponent(picked.entity); + const AABB& aabb = scene.aabb_probes[scene.probes.GetIndex(picked.entity)]; selectedAABB = AABB::Merge(selectedAABB, aabb); } diff --git a/Editor/EnvProbeWindow.cpp b/Editor/EnvProbeWindow.cpp index c0da4e32d..46512ac5c 100644 --- a/Editor/EnvProbeWindow.cpp +++ b/Editor/EnvProbeWindow.cpp @@ -19,7 +19,6 @@ void EnvProbeWindow::Create(EditorComponent* _editor) editor->RecordEntity(archive, entity); editor->GetCurrentScene().probes.Remove(entity); - editor->GetCurrentScene().aabb_probes.Remove(entity); editor->RecordEntity(archive, entity); diff --git a/Editor/LightWindow.cpp b/Editor/LightWindow.cpp index 62301184a..d53ccbd82 100644 --- a/Editor/LightWindow.cpp +++ b/Editor/LightWindow.cpp @@ -23,7 +23,6 @@ void LightWindow::Create(EditorComponent* _editor) editor->RecordEntity(archive, entity); editor->GetCurrentScene().lights.Remove(entity); - editor->GetCurrentScene().aabb_lights.Remove(entity); editor->RecordEntity(archive, entity); diff --git a/Editor/ObjectWindow.cpp b/Editor/ObjectWindow.cpp index 56bc2e174..9bca62744 100644 --- a/Editor/ObjectWindow.cpp +++ b/Editor/ObjectWindow.cpp @@ -271,7 +271,6 @@ void ObjectWindow::Create(EditorComponent* _editor) editor->RecordEntity(archive, entity); editor->GetCurrentScene().objects.Remove(entity); - editor->GetCurrentScene().aabb_objects.Remove(entity); editor->RecordEntity(archive, entity); diff --git a/Editor/TerrainWindow.cpp b/Editor/TerrainWindow.cpp index 56d07f140..6affd7217 100644 --- a/Editor/TerrainWindow.cpp +++ b/Editor/TerrainWindow.cpp @@ -694,11 +694,8 @@ void TerrainWindow::Create(EditorComponent* _editor) wi::primitive::AABB aabb; for (auto& chunk : terrain->chunks) { - const wi::primitive::AABB* object_aabb = terrain->scene->aabb_objects.GetComponent(chunk.second.entity); - if (object_aabb != nullptr) - { - aabb = wi::primitive::AABB::Merge(aabb, *object_aabb); - } + const wi::primitive::AABB& object_aabb = terrain->scene->aabb_objects[terrain->scene->objects.GetIndex(chunk.second.entity)]; + aabb = wi::primitive::AABB::Merge(aabb, object_aabb); } wi::vector data; diff --git a/Example_ImGui_Docking/Example_ImGui_Docking.cpp b/Example_ImGui_Docking/Example_ImGui_Docking.cpp index 1e5303886..e65e3ed7d 100644 --- a/Example_ImGui_Docking/Example_ImGui_Docking.cpp +++ b/Example_ImGui_Docking/Example_ImGui_Docking.cpp @@ -770,7 +770,7 @@ void Example_ImGuiRenderer::Update(float dt) if (!boundSizing) { //PE: This only diplay the bounding box. - const wi::primitive::AABB& aabb = *scene.aabb_objects.GetComponent(highlight_entity); + const wi::primitive::AABB& aabb = scene.aabb_objects[scene.objects.GetIndex(highlight_entity)]; XMFLOAT4X4 hoverBox; XMStoreFloat4x4(&hoverBox, aabb.getAsBoxMatrix()); wi::renderer::DrawBox(hoverBox, XMFLOAT4(1.0f, 0.9f, 0.5f, 0.4f)); diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 7f89aa279..c4115a39a 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -2781,8 +2781,8 @@ void UpdateVisibility(Visibility& vis) if (vis.flags & Visibility::ALLOW_LIGHTS) { // Cull lights: - vis.visibleLights.resize(vis.scene->aabb_lights.GetCount()); - wi::jobsystem::Dispatch(ctx, (uint32_t)vis.scene->aabb_lights.GetCount(), groupSize, [&](wi::jobsystem::JobArgs args) { + vis.visibleLights.resize(vis.scene->aabb_lights.size()); + wi::jobsystem::Dispatch(ctx, (uint32_t)vis.scene->aabb_lights.size(), groupSize, [&](wi::jobsystem::JobArgs args) { // Setup stream compaction: uint32_t& group_count = *(uint32_t*)args.sharedmemory; @@ -2834,8 +2834,8 @@ void UpdateVisibility(Visibility& vis) if (vis.flags & Visibility::ALLOW_OBJECTS) { // Cull objects: - vis.visibleObjects.resize(vis.scene->aabb_objects.GetCount()); - wi::jobsystem::Dispatch(ctx, (uint32_t)vis.scene->aabb_objects.GetCount(), groupSize, [&](wi::jobsystem::JobArgs args) { + vis.visibleObjects.resize(vis.scene->aabb_objects.size()); + wi::jobsystem::Dispatch(ctx, (uint32_t)vis.scene->aabb_objects.size(), groupSize, [&](wi::jobsystem::JobArgs args) { // Setup stream compaction: uint32_t& group_count = *(uint32_t*)args.sharedmemory; @@ -2907,8 +2907,8 @@ void UpdateVisibility(Visibility& vis) if (vis.flags & Visibility::ALLOW_DECALS) { - vis.visibleDecals.resize(vis.scene->aabb_decals.GetCount()); - wi::jobsystem::Dispatch(ctx, (uint32_t)vis.scene->aabb_decals.GetCount(), groupSize, [&](wi::jobsystem::JobArgs args) { + vis.visibleDecals.resize(vis.scene->aabb_decals.size()); + wi::jobsystem::Dispatch(ctx, (uint32_t)vis.scene->aabb_decals.size(), groupSize, [&](wi::jobsystem::JobArgs args) { // Setup stream compaction: uint32_t& group_count = *(uint32_t*)args.sharedmemory; @@ -2943,7 +2943,7 @@ void UpdateVisibility(Visibility& vis) { wi::jobsystem::Execute(ctx, [&](wi::jobsystem::JobArgs args) { // Cull probes: - for (size_t i = 0; i < vis.scene->aabb_probes.GetCount(); ++i) + for (size_t i = 0; i < vis.scene->aabb_probes.size(); ++i) { const AABB& aabb = vis.scene->aabb_probes[i]; @@ -4875,7 +4875,7 @@ void DrawShadowmaps( { renderQueue.init(); bool transparentShadowsRequested = false; - for (size_t i = 0; i < vis.scene->aabb_objects.GetCount(); ++i) + for (size_t i = 0; i < vis.scene->aabb_objects.size(); ++i) { const AABB& aabb = vis.scene->aabb_objects[i]; if ((aabb.layerMask & vis.layerMask) && shcams[cascade].frustum.CheckBoxFast(aabb)) @@ -4927,7 +4927,7 @@ void DrawShadowmaps( renderQueue.init(); bool transparentShadowsRequested = false; - for (size_t i = 0; i < vis.scene->aabb_objects.GetCount(); ++i) + for (size_t i = 0; i < vis.scene->aabb_objects.size(); ++i) { const AABB& aabb = vis.scene->aabb_objects[i]; if ((aabb.layerMask & vis.layerMask) && shcam.frustum.CheckBoxFast(aabb)) @@ -4985,7 +4985,7 @@ void DrawShadowmaps( renderQueue.init(); bool transparentShadowsRequested = false; - for (size_t i = 0; i < vis.scene->aabb_objects.GetCount(); ++i) + for (size_t i = 0; i < vis.scene->aabb_objects.size(); ++i) { const AABB& aabb = vis.scene->aabb_objects[i]; if ((aabb.layerMask & vis.layerMask) && boundingsphere.intersects(aabb)) @@ -5375,7 +5375,7 @@ void DrawDebugWorld( MiscCB sb; - for (size_t i = 0; i < scene.aabb_objects.GetCount(); ++i) + for (size_t i = 0; i < scene.aabb_objects.size(); ++i) { const AABB& aabb = scene.aabb_objects[i]; @@ -5387,7 +5387,7 @@ void DrawDebugWorld( device->DrawIndexed(24, 0, 0, cmd); } - for (size_t i = 0; i < scene.aabb_lights.GetCount(); ++i) + for (size_t i = 0; i < scene.aabb_lights.size(); ++i) { const AABB& aabb = scene.aabb_lights[i]; @@ -5399,7 +5399,7 @@ void DrawDebugWorld( device->DrawIndexed(24, 0, 0, cmd); } - for (size_t i = 0; i < scene.aabb_decals.GetCount(); ++i) + for (size_t i = 0; i < scene.aabb_decals.size(); ++i) { const AABB& aabb = scene.aabb_decals[i]; @@ -5411,7 +5411,7 @@ void DrawDebugWorld( device->DrawIndexed(24, 0, 0, cmd); } - for (size_t i = 0; i < scene.aabb_probes.GetCount(); ++i) + for (size_t i = 0; i < scene.aabb_probes.size(); ++i) { const AABB& aabb = scene.aabb_probes[i]; @@ -6749,7 +6749,7 @@ void RefreshEnvProbes(const Visibility& vis, CommandList cmd) static thread_local RenderQueue renderQueue; renderQueue.init(); - for (size_t i = 0; i < vis.scene->aabb_objects.GetCount(); ++i) + for (size_t i = 0; i < vis.scene->aabb_objects.size(); ++i) { const AABB& aabb = vis.scene->aabb_objects[i]; if ((aabb.layerMask & vis.layerMask) && (aabb.layerMask & probe_aabb.layerMask) && culler.intersects(aabb)) @@ -7096,7 +7096,7 @@ void VoxelRadiance(const Visibility& vis, CommandList cmd) static thread_local RenderQueue renderQueue; renderQueue.init(); - for (size_t i = 0; i < vis.scene->aabb_objects.GetCount(); ++i) + for (size_t i = 0; i < vis.scene->aabb_objects.size(); ++i) { const AABB& aabb = vis.scene->aabb_objects[i]; if (bbox.intersects(aabb)) diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index 20dd82b14..0d1529c3d 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -734,8 +734,6 @@ namespace wi::scene transforms.Create(entity); - aabb_objects.Create(entity); - objects.Create(entity); return entity; @@ -772,8 +770,6 @@ namespace wi::scene transform.Translate(position); transform.UpdateTransform(); - aabb_lights.Create(entity).createFromHalfWidth(position, XMFLOAT3(range, range, range)); - LightComponent& light = lights.Create(entity); light.intensity = intensity; light.range = range; @@ -818,8 +814,6 @@ namespace wi::scene transform.Translate(position); transform.UpdateTransform(); - aabb_probes.Create(entity); - probes.Create(entity); return entity; @@ -838,8 +832,6 @@ namespace wi::scene transforms.Create(entity); - aabb_decals.Create(entity); - decals.Create(entity); MaterialComponent& material = materials.Create(entity); @@ -944,8 +936,6 @@ namespace wi::scene transforms.Create(entity); - aabb_objects.Create(entity); - ObjectComponent& object = objects.Create(entity); MeshComponent& mesh = meshes.Create(entity); @@ -1090,8 +1080,6 @@ namespace wi::scene transforms.Create(entity); - aabb_objects.Create(entity); - ObjectComponent& object = objects.Create(entity); MeshComponent& mesh = meshes.Create(entity); @@ -2994,7 +2982,7 @@ namespace wi::scene } void Scene::RunObjectUpdateSystem(wi::jobsystem::context& ctx) { - assert(objects.GetCount() == aabb_objects.GetCount()); + aabb_objects.resize(objects.GetCount()); meshletAllocator.store(0u); @@ -3293,7 +3281,7 @@ namespace wi::scene } void Scene::RunDecalUpdateSystem(wi::jobsystem::context& ctx) { - assert(decals.GetCount() == aabb_decals.GetCount()); + aabb_decals.resize(decals.GetCount()); for (size_t i = 0; i < decals.GetCount(); ++i) { @@ -3339,7 +3327,7 @@ namespace wi::scene } void Scene::RunProbeUpdateSystem(wi::jobsystem::context& ctx) { - assert(probes.GetCount() == aabb_probes.GetCount()); + aabb_probes.resize(probes.GetCount()); if (!envmapArray.IsValid()) // even when zero probes, this will be created, since sometimes only the sky will be rendered into it { @@ -3573,7 +3561,7 @@ namespace wi::scene } void Scene::RunLightUpdateSystem(wi::jobsystem::context& ctx) { - assert(lights.GetCount() == aabb_lights.GetCount()); + aabb_lights.resize(lights.GetCount()); wi::jobsystem::Dispatch(ctx, (uint32_t)lights.GetCount(), small_subtask_groupsize, [&](wi::jobsystem::JobArgs args) { @@ -4026,125 +4014,172 @@ namespace wi::scene return INVALID_ENTITY; } - PickResult Pick(const Ray& ray, uint32_t renderTypeMask, uint32_t layerMask, const Scene& scene) + PickResult Pick(const Ray& ray, uint32_t renderTypeMask, uint32_t layerMask, const Scene& scene, uint32_t lod) { PickResult result; if (scene.objects.GetCount() > 0) { - const XMVECTOR rayOrigin = XMLoadFloat3(&ray.origin); - const XMVECTOR rayDirection = XMVector3Normalize(XMLoadFloat3(&ray.direction)); - - for (size_t i = 0; i < scene.aabb_objects.GetCount(); ++i) + // Set up parallel closest hit selection: + wi::jobsystem::context ctx; + struct JobDataForFunction { - const AABB& aabb = scene.aabb_objects[i]; - if (!ray.intersects(aabb)) - { - continue; - } + PickResult* groupResults; + XMVECTOR rayOrigin; + XMVECTOR rayDirection; + float TMin; + float TMax; + } jobDataFunction; + const uint32_t threadCount = wi::jobsystem::GetThreadCount(); + jobDataFunction.groupResults = (PickResult*)alloca(sizeof(PickResult) * threadCount); + for (uint32_t t = 0; t < threadCount; ++t) + { + jobDataFunction.groupResults[t] = result; + } + jobDataFunction.rayOrigin = XMLoadFloat3(&ray.origin); + jobDataFunction.rayDirection = XMVector3Normalize(XMLoadFloat3(&ray.direction)); + jobDataFunction.TMin = ray.TMin; + jobDataFunction.TMax = ray.TMax; - const ObjectComponent& object = scene.objects[i]; + for (size_t objectIndex = 0; objectIndex < scene.aabb_objects.size(); ++objectIndex) + { + const AABB& aabb = scene.aabb_objects[objectIndex]; + if (!ray.intersects(aabb) || (layerMask & aabb.layerMask) == 0) + continue; + + const ObjectComponent& object = scene.objects[objectIndex]; if (object.meshID == INVALID_ENTITY) - { continue; - } if (!(renderTypeMask & object.GetRenderTypes())) - { continue; - } - Entity entity = scene.aabb_objects.GetEntity(i); - const LayerComponent* layer = scene.layers.GetComponent(entity); - if (layer != nullptr && !(layer->GetLayerMask() & layerMask)) - { + const MeshComponent* mesh = scene.meshes.GetComponent(object.meshID); + if (mesh == nullptr) continue; - } - const MeshComponent& mesh = *scene.meshes.GetComponent(object.meshID); - const SoftBodyPhysicsComponent* softbody = scene.softbodies.GetComponent(object.meshID); - const bool softbody_active = softbody != nullptr && !softbody->vertex_positions_simulation.empty(); + struct JobDataForInstance + { + JobDataForFunction* func; + Entity entity; + const MeshComponent* mesh; + const SoftBodyPhysicsComponent* softbody; + const ArmatureComponent* armature; + XMMATRIX objectMat; + XMVECTOR rayOrigin_local; + XMVECTOR rayDirection_local; + }; - const XMMATRIX objectMat = XMLoadFloat4x4(&object.worldMatrix); - const XMMATRIX objectMat_Inverse = XMMatrixInverse(nullptr, objectMat); + // This will be stack deallocated at function exit: + JobDataForInstance& jobData = *(JobDataForInstance*)alloca(sizeof(JobDataForInstance)); + jobData.func = &jobDataFunction; - const XMVECTOR rayOrigin_local = XMVector3Transform(rayOrigin, objectMat_Inverse); - const XMVECTOR rayDirection_local = XMVector3Normalize(XMVector3TransformNormal(rayDirection, objectMat_Inverse)); + jobData.mesh = mesh; - const ArmatureComponent* armature = mesh.IsSkinned() ? scene.armatures.GetComponent(mesh.armatureID) : nullptr; + jobData.entity = scene.objects.GetEntity(objectIndex); + + jobData.softbody = scene.softbodies.GetComponent(object.meshID); + + jobData.objectMat = XMLoadFloat4x4(&object.worldMatrix); + const XMMATRIX objectMat_Inverse = XMMatrixInverse(nullptr, jobData.objectMat); + + jobData.rayOrigin_local = XMVector3Transform(jobData.func->rayOrigin, objectMat_Inverse); + jobData.rayDirection_local = XMVector3Normalize(XMVector3TransformNormal(jobData.func->rayDirection, objectMat_Inverse)); + + jobData.armature = jobData.mesh->IsSkinned() ? scene.armatures.GetComponent(jobData.mesh->armatureID) : nullptr; uint32_t first_subset = 0; uint32_t last_subset = 0; - mesh.GetLODSubsetRange(0, first_subset, last_subset); + jobData.mesh->GetLODSubsetRange(lod, first_subset, last_subset); for (uint32_t subsetIndex = first_subset; subsetIndex < last_subset; ++subsetIndex) { - const MeshComponent::MeshSubset& subset = mesh.subsets[subsetIndex]; - for (size_t i = 0; i < subset.indexCount; i += 3) - { - const uint32_t i0 = mesh.indices[subset.indexOffset + i + 0]; - const uint32_t i1 = mesh.indices[subset.indexOffset + i + 1]; - const uint32_t i2 = mesh.indices[subset.indexOffset + i + 2]; + const MeshComponent::MeshSubset& subset = jobData.mesh->subsets[subsetIndex]; + if (subset.indexCount == 0) + continue; + const uint32_t indexOffset = subset.indexOffset; + + // Parallel closest hit selection: + const uint32_t jobCount = subset.indexCount / 3; + const uint32_t groupSize = wi::jobsystem::DispatchGroupCount(jobCount, threadCount); + wi::jobsystem::Dispatch(ctx, jobCount, groupSize, [&jobData, subsetIndex, indexOffset](wi::jobsystem::JobArgs args) { + + PickResult& groupResult = jobData.func->groupResults[args.groupID]; + + const uint32_t i0 = jobData.mesh->indices[indexOffset + args.jobIndex * 3 + 0]; + const uint32_t i1 = jobData.mesh->indices[indexOffset + args.jobIndex * 3 + 1]; + const uint32_t i2 = jobData.mesh->indices[indexOffset + args.jobIndex * 3 + 2]; XMVECTOR p0; XMVECTOR p1; XMVECTOR p2; + const bool softbody_active = jobData.softbody != nullptr && !jobData.softbody->vertex_positions_simulation.empty(); if (softbody_active) { - p0 = softbody->vertex_positions_simulation[i0].LoadPOS(); - p1 = softbody->vertex_positions_simulation[i1].LoadPOS(); - p2 = softbody->vertex_positions_simulation[i2].LoadPOS(); + p0 = jobData.softbody->vertex_positions_simulation[i0].LoadPOS(); + p1 = jobData.softbody->vertex_positions_simulation[i1].LoadPOS(); + p2 = jobData.softbody->vertex_positions_simulation[i2].LoadPOS(); } else { - if (armature == nullptr) + if (jobData.armature == nullptr || jobData.armature->boneData.empty()) { - if (mesh.vertex_positions_morphed.empty()) - { - p0 = XMLoadFloat3(&mesh.vertex_positions[i0]); - p1 = XMLoadFloat3(&mesh.vertex_positions[i1]); - p2 = XMLoadFloat3(&mesh.vertex_positions[i2]); + if (jobData.mesh->vertex_positions_morphed.empty()) + { + p0 = XMLoadFloat3(&jobData.mesh->vertex_positions[i0]); + p1 = XMLoadFloat3(&jobData.mesh->vertex_positions[i1]); + p2 = XMLoadFloat3(&jobData.mesh->vertex_positions[i2]); } else { - p0 = mesh.vertex_positions_morphed[i0].LoadPOS(); - p1 = mesh.vertex_positions_morphed[i1].LoadPOS(); - p2 = mesh.vertex_positions_morphed[i2].LoadPOS(); + p0 = jobData.mesh->vertex_positions_morphed[i0].LoadPOS(); + p1 = jobData.mesh->vertex_positions_morphed[i1].LoadPOS(); + p2 = jobData.mesh->vertex_positions_morphed[i2].LoadPOS(); } } else { - p0 = SkinVertex(mesh, *armature, i0); - p1 = SkinVertex(mesh, *armature, i1); - p2 = SkinVertex(mesh, *armature, i2); + p0 = SkinVertex(*jobData.mesh, *jobData.armature, i0); + p1 = SkinVertex(*jobData.mesh, *jobData.armature, i1); + p2 = SkinVertex(*jobData.mesh, *jobData.armature, i2); } } float distance; XMFLOAT2 bary; - if (wi::math::RayTriangleIntersects(rayOrigin_local, rayDirection_local, p0, p1, p2, distance, bary, ray.TMin, ray.TMax)) + if (wi::math::RayTriangleIntersects(jobData.rayOrigin_local, jobData.rayDirection_local, p0, p1, p2, distance, bary, jobData.func->TMin, jobData.func->TMax)) { - const XMVECTOR pos = XMVector3Transform(XMVectorAdd(rayOrigin_local, rayDirection_local*distance), objectMat); - distance = wi::math::Distance(pos, rayOrigin); + const XMVECTOR pos = XMVector3Transform(XMVectorAdd(jobData.rayOrigin_local, jobData.rayDirection_local * distance), jobData.objectMat); + distance = wi::math::Distance(pos, jobData.func->rayOrigin); - if (distance < result.distance) + if (distance < groupResult.distance) { - const XMVECTOR nor = XMVector3Normalize(XMVector3TransformNormal(XMVector3Cross(XMVectorSubtract(p2, p1), XMVectorSubtract(p1, p0)), objectMat)); + const XMVECTOR nor = XMVector3Normalize(XMVector3TransformNormal(XMVector3Cross(XMVectorSubtract(p2, p1), XMVectorSubtract(p1, p0)), jobData.objectMat)); - result.entity = entity; - XMStoreFloat3(&result.position, pos); - XMStoreFloat3(&result.normal, nor); - result.distance = distance; - result.subsetIndex = (int)subsetIndex; - result.vertexID0 = (int)i0; - result.vertexID1 = (int)i1; - result.vertexID2 = (int)i2; - result.bary = bary; + groupResult.entity = jobData.entity; + XMStoreFloat3(&groupResult.position, pos); + XMStoreFloat3(&groupResult.normal, nor); + groupResult.distance = distance; + groupResult.subsetIndex = (int)subsetIndex; + groupResult.vertexID0 = (int)i0; + groupResult.vertexID1 = (int)i1; + groupResult.vertexID2 = (int)i2; + groupResult.bary = bary; } } - } + }); } } + + // Merge thread results: + wi::jobsystem::Wait(ctx); + for (uint32_t t = 0; t < threadCount; ++t) + { + if (jobDataFunction.groupResults[t].distance < result.distance) + { + result = jobDataFunction.groupResults[t]; + } + } } // Construct a matrix that will orient to position (P) according to surface normal (N): @@ -4159,99 +4194,131 @@ namespace wi::scene return result; } - SceneIntersectSphereResult SceneIntersectSphere(const Sphere& sphere, uint32_t renderTypeMask, uint32_t layerMask, const Scene& scene) + SceneIntersectSphereResult SceneIntersectSphere(const Sphere& sphere, uint32_t renderTypeMask, uint32_t layerMask, const Scene& scene, uint32_t lod) { SceneIntersectSphereResult result; - XMVECTOR Center = XMLoadFloat3(&sphere.center); - XMVECTOR Radius = XMVectorReplicate(sphere.radius); - XMVECTOR RadiusSq = XMVectorMultiply(Radius, Radius); if (scene.objects.GetCount() > 0) { - - for (size_t i = 0; i < scene.aabb_objects.GetCount(); ++i) + // Set up parallel closest hit selection: + wi::jobsystem::context ctx; + struct JobDataForFunction { - const AABB& aabb = scene.aabb_objects[i]; - if (!sphere.intersects(aabb)) - { - continue; - } + SceneIntersectSphereResult* groupResults; + Sphere sphere; + XMVECTOR Center; + XMVECTOR Radius; + XMVECTOR RadiusSq; + } jobDataFunction; + const uint32_t threadCount = wi::jobsystem::GetThreadCount(); + jobDataFunction.groupResults = (SceneIntersectSphereResult*)alloca(sizeof(SceneIntersectSphereResult) * threadCount); + for (uint32_t t = 0; t < threadCount; ++t) + { + jobDataFunction.groupResults[t] = result; + } + jobDataFunction.sphere = sphere; + jobDataFunction.Center = XMLoadFloat3(&sphere.center); + jobDataFunction.Radius = XMVectorReplicate(sphere.radius); + jobDataFunction.RadiusSq = XMVectorMultiply(jobDataFunction.Radius, jobDataFunction.Radius); - const ObjectComponent& object = scene.objects[i]; + for (size_t objectIndex = 0; objectIndex < scene.aabb_objects.size(); ++objectIndex) + { + const AABB& aabb = scene.aabb_objects[objectIndex]; + if (!sphere.intersects(aabb) || (layerMask & aabb.layerMask) == 0) + continue; + + const ObjectComponent& object = scene.objects[objectIndex]; if (object.meshID == INVALID_ENTITY) - { continue; - } if (!(renderTypeMask & object.GetRenderTypes())) - { continue; - } - Entity entity = scene.aabb_objects.GetEntity(i); - const LayerComponent* layer = scene.layers.GetComponent(entity); - if (layer != nullptr && !(layer->GetLayerMask() & layerMask)) - { + const MeshComponent* mesh = scene.meshes.GetComponent(object.meshID); + if (mesh == nullptr) continue; - } - const MeshComponent& mesh = *scene.meshes.GetComponent(object.meshID); - const SoftBodyPhysicsComponent* softbody = scene.softbodies.GetComponent(object.meshID); - const bool softbody_active = softbody != nullptr && !softbody->vertex_positions_simulation.empty(); + struct JobDataForInstance + { + JobDataForFunction* func; + Entity entity; + const MeshComponent* mesh; + const SoftBodyPhysicsComponent* softbody; + const ArmatureComponent* armature; + XMMATRIX objectMat; + }; - const XMMATRIX objectMat = XMLoadFloat4x4(&object.worldMatrix); + // This will be stack deallocated at function exit: + JobDataForInstance& jobData = *(JobDataForInstance*)alloca(sizeof(JobDataForInstance)); + jobData.func = &jobDataFunction; - const ArmatureComponent* armature = mesh.IsSkinned() ? scene.armatures.GetComponent(mesh.armatureID) : nullptr; + jobData.mesh = mesh; + + jobData.entity = scene.objects.GetEntity(objectIndex); + + jobData.softbody = scene.softbodies.GetComponent(object.meshID); + + jobData.objectMat = XMLoadFloat4x4(&object.worldMatrix); + + jobData.armature = jobData.mesh->IsSkinned() ? scene.armatures.GetComponent(jobData.mesh->armatureID) : nullptr; uint32_t first_subset = 0; uint32_t last_subset = 0; - mesh.GetLODSubsetRange(0, first_subset, last_subset); + jobData.mesh->GetLODSubsetRange(lod, first_subset, last_subset); for (uint32_t subsetIndex = first_subset; subsetIndex < last_subset; ++subsetIndex) { - const MeshComponent::MeshSubset& subset = mesh.subsets[subsetIndex]; - for (size_t i = 0; i < subset.indexCount; i += 3) - { - const uint32_t i0 = mesh.indices[subset.indexOffset + i + 0]; - const uint32_t i1 = mesh.indices[subset.indexOffset + i + 1]; - const uint32_t i2 = mesh.indices[subset.indexOffset + i + 2]; + const MeshComponent::MeshSubset& subset = jobData.mesh->subsets[subsetIndex]; + if (subset.indexCount == 0) + continue; + const uint32_t indexOffset = subset.indexOffset; + + // Parallel closest hit selection: + const uint32_t jobCount = subset.indexCount / 3; + const uint32_t groupSize = wi::jobsystem::DispatchGroupCount(jobCount, threadCount); + wi::jobsystem::Dispatch(ctx, jobCount, groupSize, [&jobData, subsetIndex, indexOffset](wi::jobsystem::JobArgs args) { + + SceneIntersectSphereResult& groupResult = jobData.func->groupResults[args.groupID]; + + const uint32_t i0 = jobData.mesh->indices[indexOffset + args.jobIndex * 3 + 0]; + const uint32_t i1 = jobData.mesh->indices[indexOffset + args.jobIndex * 3 + 1]; + const uint32_t i2 = jobData.mesh->indices[indexOffset + args.jobIndex * 3 + 2]; XMVECTOR p0; XMVECTOR p1; XMVECTOR p2; + const bool softbody_active = jobData.softbody != nullptr && !jobData.softbody->vertex_positions_simulation.empty(); if (softbody_active) { - p0 = softbody->vertex_positions_simulation[i0].LoadPOS(); - p1 = softbody->vertex_positions_simulation[i1].LoadPOS(); - p2 = softbody->vertex_positions_simulation[i2].LoadPOS(); + p0 = jobData.softbody->vertex_positions_simulation[i0].LoadPOS(); + p1 = jobData.softbody->vertex_positions_simulation[i1].LoadPOS(); + p2 = jobData.softbody->vertex_positions_simulation[i2].LoadPOS(); } else { - if (armature == nullptr) + if (jobData.armature == nullptr || jobData.armature->boneData.empty()) { - p0 = XMLoadFloat3(&mesh.vertex_positions[i0]); - p1 = XMLoadFloat3(&mesh.vertex_positions[i1]); - p2 = XMLoadFloat3(&mesh.vertex_positions[i2]); + p0 = XMLoadFloat3(&jobData.mesh->vertex_positions[i0]); + p1 = XMLoadFloat3(&jobData.mesh->vertex_positions[i1]); + p2 = XMLoadFloat3(&jobData.mesh->vertex_positions[i2]); } else { - p0 = SkinVertex(mesh, *armature, i0); - p1 = SkinVertex(mesh, *armature, i1); - p2 = SkinVertex(mesh, *armature, i2); + p0 = SkinVertex(*jobData.mesh, *jobData.armature, i0); + p1 = SkinVertex(*jobData.mesh, *jobData.armature, i1); + p2 = SkinVertex(*jobData.mesh, *jobData.armature, i2); } } - p0 = XMVector3Transform(p0, objectMat); - p1 = XMVector3Transform(p1, objectMat); - p2 = XMVector3Transform(p2, objectMat); + p0 = XMVector3Transform(p0, jobData.objectMat); + p1 = XMVector3Transform(p1, jobData.objectMat); + p2 = XMVector3Transform(p2, jobData.objectMat); XMFLOAT3 min, max; XMStoreFloat3(&min, XMVectorMin(p0, XMVectorMin(p1, p2))); XMStoreFloat3(&max, XMVectorMax(p0, XMVectorMax(p1, p2))); AABB aabb_triangle(min, max); - if (sphere.intersects(aabb_triangle) == AABB::OUTSIDE) - { - continue; - } + if (jobData.func->sphere.intersects(aabb_triangle) == AABB::OUTSIDE) + return; // Compute the plane of the triangle (has to be normalized). XMVECTOR N = XMVector3Normalize(XMVector3Cross(XMVectorSubtract(p1, p0), XMVectorSubtract(p2, p0))); @@ -4260,20 +4327,18 @@ namespace wi::scene assert(!XMVector3Equal(N, XMVectorZero())); // Find the nearest feature on the triangle to the sphere. - XMVECTOR Dist = XMVector3Dot(XMVectorSubtract(Center, p0), N); + XMVECTOR Dist = XMVector3Dot(XMVectorSubtract(jobData.func->Center, p0), N); - if (!mesh.IsDoubleSided() && XMVectorGetX(Dist) > 0) - { - continue; // pass through back faces - } + if (!jobData.mesh->IsDoubleSided() && XMVectorGetX(Dist) > 0) + return; // pass through back faces // If the center of the sphere is farther from the plane of the triangle than // the radius of the sphere, then there cannot be an intersection. - XMVECTOR NoIntersection = XMVectorLess(Dist, XMVectorNegate(Radius)); - NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Dist, Radius)); + XMVECTOR NoIntersection = XMVectorLess(Dist, XMVectorNegate(jobData.func->Radius)); + NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Dist, jobData.func->Radius)); // Project the center of the sphere onto the plane of the triangle. - XMVECTOR Point0 = XMVectorNegativeMultiplySubtract(N, Dist, Center); + XMVECTOR Point0 = XMVectorNegativeMultiplySubtract(N, Dist, jobData.func->Center); // Is it inside all the edges? If so we intersect because the distance // to the plane is less than the radius. @@ -4300,25 +4365,25 @@ namespace wi::scene // Find the nearest point on each edge. // Edge 0,1 - XMVECTOR Point1 = DirectX::Internal::PointOnLineSegmentNearestPoint(p0, p1, Center); + XMVECTOR Point1 = DirectX::Internal::PointOnLineSegmentNearestPoint(p0, p1, jobData.func->Center); // If the distance to the center of the sphere to the point is less than // the radius of the sphere then it must intersect. - Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(Center, Point1)), RadiusSq)); + Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(jobData.func->Center, Point1)), jobData.func->RadiusSq)); // Edge 1,2 - XMVECTOR Point2 = DirectX::Internal::PointOnLineSegmentNearestPoint(p1, p2, Center); + XMVECTOR Point2 = DirectX::Internal::PointOnLineSegmentNearestPoint(p1, p2, jobData.func->Center); // If the distance to the center of the sphere to the point is less than // the radius of the sphere then it must intersect. - Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(Center, Point2)), RadiusSq)); + Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(jobData.func->Center, Point2)), jobData.func->RadiusSq)); // Edge 2,0 - XMVECTOR Point3 = DirectX::Internal::PointOnLineSegmentNearestPoint(p2, p0, Center); + XMVECTOR Point3 = DirectX::Internal::PointOnLineSegmentNearestPoint(p2, p0, jobData.func->Center); // If the distance to the center of the sphere to the point is less than // the radius of the sphere then it must intersect. - Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(Center, Point3)), RadiusSq)); + Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(jobData.func->Center, Point3)), jobData.func->RadiusSq)); bool intersects = XMVector4EqualInt(XMVectorAndCInt(Intersection, NoIntersection), XMVectorTrueInt()); @@ -4329,143 +4394,193 @@ namespace wi::scene { // If the sphere center's projection on the triangle plane is not within the triangle, // determine the closest point on triangle to the sphere center - float bestDist = XMVectorGetX(XMVector3LengthSq(Point1 - Center)); + float bestDist = XMVectorGetX(XMVector3LengthSq(Point1 - jobData.func->Center)); bestPoint = Point1; - float d = XMVectorGetX(XMVector3LengthSq(Point2 - Center)); + float d = XMVectorGetX(XMVector3LengthSq(Point2 - jobData.func->Center)); if (d < bestDist) { bestDist = d; bestPoint = Point2; } - d = XMVectorGetX(XMVector3LengthSq(Point3 - Center)); + d = XMVectorGetX(XMVector3LengthSq(Point3 - jobData.func->Center)); if (d < bestDist) { bestDist = d; bestPoint = Point3; } } - XMVECTOR intersectionVec = Center - bestPoint; + XMVECTOR intersectionVec = jobData.func->Center - bestPoint; XMVECTOR intersectionVecLen = XMVector3Length(intersectionVec); - result.entity = entity; - result.depth = sphere.radius - XMVectorGetX(intersectionVecLen); - XMStoreFloat3(&result.position, bestPoint); - XMStoreFloat3(&result.normal, intersectionVec / intersectionVecLen); - return result; + float depth = jobData.func->sphere.radius - XMVectorGetX(intersectionVecLen); + if (depth > groupResult.depth) + { + groupResult.entity = jobData.entity; + groupResult.depth = depth; + XMStoreFloat3(&groupResult.position, bestPoint); + XMStoreFloat3(&groupResult.normal, intersectionVec / intersectionVecLen); + } } - } + }); } } + + // Merge thread results: + wi::jobsystem::Wait(ctx); + for (uint32_t t = 0; t < threadCount; ++t) + { + if (jobDataFunction.groupResults[t].depth > result.depth) + { + result = jobDataFunction.groupResults[t]; + } + } } return result; } - SceneIntersectSphereResult SceneIntersectCapsule(const Capsule& capsule, uint32_t renderTypeMask, uint32_t layerMask, const Scene& scene) + SceneIntersectSphereResult SceneIntersectCapsule(const Capsule& capsule, uint32_t renderTypeMask, uint32_t layerMask, const Scene& scene, uint32_t lod) { SceneIntersectSphereResult result; - XMVECTOR Base = XMLoadFloat3(&capsule.base); - XMVECTOR Tip = XMLoadFloat3(&capsule.tip); - XMVECTOR Radius = XMVectorReplicate(capsule.radius); - XMVECTOR LineEndOffset = XMVector3Normalize(Tip - Base) * Radius; - XMVECTOR A = Base + LineEndOffset; - XMVECTOR B = Tip - LineEndOffset; - XMVECTOR RadiusSq = XMVectorMultiply(Radius, Radius); - AABB capsule_aabb = capsule.getAABB(); if (scene.objects.GetCount() > 0) { - - for (size_t i = 0; i < scene.aabb_objects.GetCount(); ++i) + // Set up parallel closest hit selection: + wi::jobsystem::context ctx; + struct JobDataForFunction { - const AABB& aabb = scene.aabb_objects[i]; - if (capsule_aabb.intersects(aabb) == AABB::INTERSECTION_TYPE::OUTSIDE) - { - continue; - } + SceneIntersectSphereResult* groupResults; + float radius; + XMVECTOR Base; + XMVECTOR Tip; + XMVECTOR Radius; + XMVECTOR LineEndOffset; + XMVECTOR A; + XMVECTOR B; + XMVECTOR RadiusSq; + AABB capsule_aabb; + } jobDataFunction; + const uint32_t threadCount = wi::jobsystem::GetThreadCount(); + jobDataFunction.groupResults = (SceneIntersectSphereResult*)alloca(sizeof(SceneIntersectSphereResult) * threadCount); + for (uint32_t t = 0; t < threadCount; ++t) + { + jobDataFunction.groupResults[t] = result; + } + jobDataFunction.radius = capsule.radius; + jobDataFunction.Base = XMLoadFloat3(&capsule.base); + jobDataFunction.Tip = XMLoadFloat3(&capsule.tip); + jobDataFunction.Radius = XMVectorReplicate(capsule.radius); + jobDataFunction.LineEndOffset = XMVector3Normalize(jobDataFunction.Tip - jobDataFunction.Base) * jobDataFunction.Radius; + jobDataFunction.A = jobDataFunction.Base + jobDataFunction.LineEndOffset; + jobDataFunction.B = jobDataFunction.Tip - jobDataFunction.LineEndOffset; + jobDataFunction.RadiusSq = XMVectorMultiply(jobDataFunction.Radius, jobDataFunction.Radius); + jobDataFunction.capsule_aabb = capsule.getAABB(); - const ObjectComponent& object = scene.objects[i]; + for (size_t objectIndex = 0; objectIndex < scene.aabb_objects.size(); ++objectIndex) + { + const AABB& aabb = scene.aabb_objects[objectIndex]; + if (jobDataFunction.capsule_aabb.intersects(aabb) == AABB::INTERSECTION_TYPE::OUTSIDE || (layerMask & aabb.layerMask) == 0) + continue; + + const ObjectComponent& object = scene.objects[objectIndex]; if (object.meshID == INVALID_ENTITY) - { continue; - } if (!(renderTypeMask & object.GetRenderTypes())) - { continue; - } - Entity entity = scene.aabb_objects.GetEntity(i); - const LayerComponent* layer = scene.layers.GetComponent(entity); - if (layer != nullptr && !(layer->GetLayerMask() & layerMask)) - { + const MeshComponent* mesh = scene.meshes.GetComponent(object.meshID); + if (mesh == nullptr) continue; - } - const MeshComponent& mesh = *scene.meshes.GetComponent(object.meshID); - const SoftBodyPhysicsComponent* softbody = scene.softbodies.GetComponent(object.meshID); - const bool softbody_active = softbody != nullptr && !softbody->vertex_positions_simulation.empty(); + struct JobDataForInstance + { + JobDataForFunction* func; + Entity entity; + const MeshComponent* mesh; + const SoftBodyPhysicsComponent* softbody; + const ArmatureComponent* armature; + XMMATRIX objectMat; + }; - const XMMATRIX objectMat = XMLoadFloat4x4(&object.worldMatrix); + // This will be stack deallocated at function exit: + JobDataForInstance& jobData = *(JobDataForInstance*)alloca(sizeof(JobDataForInstance)); + jobData.func = &jobDataFunction; - const ArmatureComponent* armature = mesh.IsSkinned() ? scene.armatures.GetComponent(mesh.armatureID) : nullptr; + jobData.mesh = mesh; + + jobData.entity = scene.objects.GetEntity(objectIndex); + + jobData.softbody = scene.softbodies.GetComponent(object.meshID); + + jobData.objectMat = XMLoadFloat4x4(&object.worldMatrix); + + jobData.armature = jobData.mesh->IsSkinned() ? scene.armatures.GetComponent(jobData.mesh->armatureID) : nullptr; uint32_t first_subset = 0; uint32_t last_subset = 0; - mesh.GetLODSubsetRange(0, first_subset, last_subset); + jobData.mesh->GetLODSubsetRange(lod, first_subset, last_subset); for (uint32_t subsetIndex = first_subset; subsetIndex < last_subset; ++subsetIndex) { - const MeshComponent::MeshSubset& subset = mesh.subsets[subsetIndex]; - for (size_t i = 0; i < subset.indexCount; i += 3) - { - const uint32_t i0 = mesh.indices[subset.indexOffset + i + 0]; - const uint32_t i1 = mesh.indices[subset.indexOffset + i + 1]; - const uint32_t i2 = mesh.indices[subset.indexOffset + i + 2]; + const MeshComponent::MeshSubset& subset = jobData.mesh->subsets[subsetIndex]; + if (subset.indexCount == 0) + continue; + const uint32_t indexOffset = subset.indexOffset; + + // Parallel closest hit selection: + const uint32_t jobCount = subset.indexCount / 3; + const uint32_t groupSize = wi::jobsystem::DispatchGroupCount(jobCount, threadCount); + wi::jobsystem::Dispatch(ctx, jobCount, groupSize, [&jobData, subsetIndex, indexOffset](wi::jobsystem::JobArgs args) { + + SceneIntersectSphereResult& groupResult = jobData.func->groupResults[args.groupID]; + + const uint32_t i0 = jobData.mesh->indices[indexOffset + args.jobIndex * 3 + 0]; + const uint32_t i1 = jobData.mesh->indices[indexOffset + args.jobIndex * 3 + 1]; + const uint32_t i2 = jobData.mesh->indices[indexOffset + args.jobIndex * 3 + 2]; XMVECTOR p0; XMVECTOR p1; XMVECTOR p2; + const bool softbody_active = jobData.softbody != nullptr && !jobData.softbody->vertex_positions_simulation.empty(); if (softbody_active) { - p0 = softbody->vertex_positions_simulation[i0].LoadPOS(); - p1 = softbody->vertex_positions_simulation[i1].LoadPOS(); - p2 = softbody->vertex_positions_simulation[i2].LoadPOS(); + p0 = jobData.softbody->vertex_positions_simulation[i0].LoadPOS(); + p1 = jobData.softbody->vertex_positions_simulation[i1].LoadPOS(); + p2 = jobData.softbody->vertex_positions_simulation[i2].LoadPOS(); } else { - if (armature == nullptr || armature->boneData.empty()) + if (jobData.armature == nullptr || jobData.armature->boneData.empty()) { - p0 = XMLoadFloat3(&mesh.vertex_positions[i0]); - p1 = XMLoadFloat3(&mesh.vertex_positions[i1]); - p2 = XMLoadFloat3(&mesh.vertex_positions[i2]); + p0 = XMLoadFloat3(&jobData.mesh->vertex_positions[i0]); + p1 = XMLoadFloat3(&jobData.mesh->vertex_positions[i1]); + p2 = XMLoadFloat3(&jobData.mesh->vertex_positions[i2]); } else { - p0 = SkinVertex(mesh, *armature, i0); - p1 = SkinVertex(mesh, *armature, i1); - p2 = SkinVertex(mesh, *armature, i2); + p0 = SkinVertex(*jobData.mesh, *jobData.armature, i0); + p1 = SkinVertex(*jobData.mesh, *jobData.armature, i1); + p2 = SkinVertex(*jobData.mesh, *jobData.armature, i2); } } - p0 = XMVector3Transform(p0, objectMat); - p1 = XMVector3Transform(p1, objectMat); - p2 = XMVector3Transform(p2, objectMat); + p0 = XMVector3Transform(p0, jobData.objectMat); + p1 = XMVector3Transform(p1, jobData.objectMat); + p2 = XMVector3Transform(p2, jobData.objectMat); XMFLOAT3 min, max; XMStoreFloat3(&min, XMVectorMin(p0, XMVectorMin(p1, p2))); XMStoreFloat3(&max, XMVectorMax(p0, XMVectorMax(p1, p2))); AABB aabb_triangle(min, max); - if (capsule_aabb.intersects(aabb_triangle) == AABB::OUTSIDE) - { - continue; - } + if (jobData.func->capsule_aabb.intersects(aabb_triangle) == AABB::OUTSIDE) + return; // Compute the plane of the triangle (has to be normalized). XMVECTOR N = XMVector3Normalize(XMVector3Cross(XMVectorSubtract(p1, p0), XMVectorSubtract(p2, p0))); XMVECTOR ReferencePoint; - XMVECTOR d = XMVector3Normalize(B - A); + XMVECTOR d = XMVector3Normalize(jobData.func->B - jobData.func->A); if (abs(XMVectorGetX(XMVector3Dot(N, d))) < FLT_EPSILON) { // Capsule line cannot be intersected with triangle plane (they are parallel) @@ -4475,8 +4590,8 @@ namespace wi::scene else { // Intersect capsule line with triangle plane: - XMVECTOR t = XMVector3Dot(N, (Base - p0) / XMVectorAbs(XMVector3Dot(N, d))); - XMVECTOR LinePlaneIntersection = Base + d * t; + XMVECTOR t = XMVector3Dot(N, (jobData.func->Base - p0) / XMVectorAbs(XMVector3Dot(N, d))); + XMVECTOR LinePlaneIntersection = jobData.func->Base + d * t; // Compute the cross products of the vector from the base of each edge to // the point with each edge vector. @@ -4533,7 +4648,7 @@ namespace wi::scene } // Place a sphere on closest point on line segment to intersection: - XMVECTOR Center = wi::math::ClosestPointOnLineSegment(A, B, ReferencePoint); + XMVECTOR Center = wi::math::ClosestPointOnLineSegment(jobData.func->A, jobData.func->B, ReferencePoint); // Assert that the triangle is not degenerate. assert(!XMVector3Equal(N, XMVectorZero())); @@ -4541,15 +4656,13 @@ namespace wi::scene // Find the nearest feature on the triangle to the sphere. XMVECTOR Dist = XMVector3Dot(XMVectorSubtract(Center, p0), N); - if (!mesh.IsDoubleSided() && XMVectorGetX(Dist) > 0) - { - continue; // pass through back faces - } + if (!jobData.mesh->IsDoubleSided() && XMVectorGetX(Dist) > 0) + return; // pass through back faces // If the center of the sphere is farther from the plane of the triangle than // the radius of the sphere, then there cannot be an intersection. - XMVECTOR NoIntersection = XMVectorLess(Dist, XMVectorNegate(Radius)); - NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Dist, Radius)); + XMVECTOR NoIntersection = XMVectorLess(Dist, XMVectorNegate(jobData.func->Radius)); + NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Dist, jobData.func->Radius)); // Project the center of the sphere onto the plane of the triangle. XMVECTOR Point0 = XMVectorNegativeMultiplySubtract(N, Dist, Center); @@ -4583,21 +4696,21 @@ namespace wi::scene // If the distance to the center of the sphere to the point is less than // the radius of the sphere then it must intersect. - Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(Center, Point1)), RadiusSq)); + Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(Center, Point1)), jobData.func->RadiusSq)); // Edge 1,2 XMVECTOR Point2 = wi::math::ClosestPointOnLineSegment(p1, p2, Center); // If the distance to the center of the sphere to the point is less than // the radius of the sphere then it must intersect. - Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(Center, Point2)), RadiusSq)); + Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(Center, Point2)), jobData.func->RadiusSq)); // Edge 2,0 XMVECTOR Point3 = wi::math::ClosestPointOnLineSegment(p2, p0, Center); // If the distance to the center of the sphere to the point is less than // the radius of the sphere then it must intersect. - Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(Center, Point3)), RadiusSq)); + Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(Center, Point3)), jobData.func->RadiusSq)); bool intersects = XMVector4EqualInt(XMVectorAndCInt(Intersection, NoIntersection), XMVectorTrueInt()); @@ -4627,16 +4740,29 @@ namespace wi::scene XMVECTOR intersectionVec = Center - bestPoint; XMVECTOR intersectionVecLen = XMVector3Length(intersectionVec); - result.entity = entity; - result.depth = capsule.radius - XMVectorGetX(intersectionVecLen); - XMStoreFloat3(&result.position, bestPoint); - XMStoreFloat3(&result.normal, intersectionVec / intersectionVecLen); - return result; + float depth = jobData.func->radius - XMVectorGetX(intersectionVecLen); + if (depth > groupResult.depth) + { + groupResult.entity = jobData.entity; + groupResult.depth = depth; + XMStoreFloat3(&groupResult.position, bestPoint); + XMStoreFloat3(&groupResult.normal, intersectionVec / intersectionVecLen); + } } - } + }); } } + + // Merge thread results: + wi::jobsystem::Wait(ctx); + for (uint32_t t = 0; t < threadCount; ++t) + { + if (jobDataFunction.groupResults[t].depth > result.depth) + { + result = jobDataFunction.groupResults[t]; + } + } } return result; diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index 2ab4878cb..0f66c8174 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -29,18 +29,14 @@ namespace wi::scene wi::ecs::ComponentManager& meshes = componentLibrary.Register("wi::scene::Scene::meshes", 1); // version = 1 wi::ecs::ComponentManager& impostors = componentLibrary.Register("wi::scene::Scene::impostors"); wi::ecs::ComponentManager& objects = componentLibrary.Register("wi::scene::Scene::objects"); - wi::ecs::ComponentManager& aabb_objects = componentLibrary.Register("wi::scene::Scene::aabb_objects"); wi::ecs::ComponentManager& rigidbodies = componentLibrary.Register("wi::scene::Scene::rigidbodies", 1); // version = 1 wi::ecs::ComponentManager& softbodies = componentLibrary.Register("wi::scene::Scene::softbodies"); wi::ecs::ComponentManager& armatures = componentLibrary.Register("wi::scene::Scene::armatures"); wi::ecs::ComponentManager& lights = componentLibrary.Register("wi::scene::Scene::lights"); - wi::ecs::ComponentManager& aabb_lights = componentLibrary.Register("wi::scene::Scene::aabb_lights"); wi::ecs::ComponentManager& cameras = componentLibrary.Register("wi::scene::Scene::cameras"); wi::ecs::ComponentManager& probes = componentLibrary.Register("wi::scene::Scene::probes"); - wi::ecs::ComponentManager& aabb_probes = componentLibrary.Register("wi::scene::Scene::aabb_probes"); wi::ecs::ComponentManager& forces = componentLibrary.Register("wi::scene::Scene::forces", 1); // version = 1 wi::ecs::ComponentManager& decals = componentLibrary.Register("wi::scene::Scene::decals"); - wi::ecs::ComponentManager& aabb_decals = componentLibrary.Register("wi::scene::Scene::aabb_decals"); wi::ecs::ComponentManager& animations = componentLibrary.Register("wi::scene::Scene::animations"); wi::ecs::ComponentManager& animation_datas = componentLibrary.Register("wi::scene::Scene::animation_datas"); wi::ecs::ComponentManager& emitters = componentLibrary.Register("wi::scene::Scene::emitters"); @@ -76,6 +72,12 @@ namespace wi::scene void SetAccelerationStructureUpdateRequested(bool value = true) { acceleration_structure_update_requested = value; } bool IsAccelerationStructureUpdateRequested() const { return acceleration_structure_update_requested; } + // AABB culling streams: + wi::vector aabb_objects; + wi::vector aabb_lights; + wi::vector aabb_probes; + wi::vector aabb_decals; + // Shader visible scene parameters: ShaderScene shaderscene; @@ -380,7 +382,7 @@ namespace wi::scene // renderTypeMask : filter based on render type // layerMask : filter based on layer // scene : the scene that will be traced against the ray - PickResult Pick(const wi::primitive::Ray& ray, uint32_t renderTypeMask = wi::enums::RENDERTYPE_OPAQUE, uint32_t layerMask = ~0, const Scene& scene = GetScene()); + PickResult Pick(const wi::primitive::Ray& ray, uint32_t renderTypeMask = wi::enums::RENDERTYPE_OPAQUE, uint32_t layerMask = ~0, const Scene& scene = GetScene(), uint32_t lod = 0); struct SceneIntersectSphereResult { @@ -389,8 +391,8 @@ namespace wi::scene XMFLOAT3 normal = XMFLOAT3(0, 0, 0); float depth = 0; }; - SceneIntersectSphereResult SceneIntersectSphere(const wi::primitive::Sphere& sphere, uint32_t renderTypeMask = wi::enums::RENDERTYPE_OPAQUE, uint32_t layerMask = ~0, const Scene& scene = GetScene()); - SceneIntersectSphereResult SceneIntersectCapsule(const wi::primitive::Capsule& capsule, uint32_t renderTypeMask = wi::enums::RENDERTYPE_OPAQUE, uint32_t layerMask = ~0, const Scene& scene = GetScene()); + SceneIntersectSphereResult SceneIntersectSphere(const wi::primitive::Sphere& sphere, uint32_t renderTypeMask = wi::enums::RENDERTYPE_OPAQUE, uint32_t layerMask = ~0, const Scene& scene = GetScene(), uint32_t lod = 0); + SceneIntersectSphereResult SceneIntersectCapsule(const wi::primitive::Capsule& capsule, uint32_t renderTypeMask = wi::enums::RENDERTYPE_OPAQUE, uint32_t layerMask = ~0, const Scene& scene = GetScene(), uint32_t lod = 0); } diff --git a/WickedEngine/wiScene_BindLua.cpp b/WickedEngine/wiScene_BindLua.cpp index c1d45b767..308ae92db 100644 --- a/WickedEngine/wiScene_BindLua.cpp +++ b/WickedEngine/wiScene_BindLua.cpp @@ -130,6 +130,7 @@ int Pick(lua_State* L) uint32_t renderTypeMask = wi::enums::RENDERTYPE_OPAQUE; uint32_t layerMask = 0xFFFFFFFF; Scene* scene = GetGlobalScene(); + uint32_t lod = 0; if (argc > 1) { renderTypeMask = (uint32_t)wi::lua::SGetInt(L, 2); @@ -144,15 +145,20 @@ int Pick(lua_State* L) if (custom_scene) { scene = custom_scene->scene; + + if (argc > 4) + { + lod = (uint32_t)wi::lua::SGetInt(L, 5); + } } else { - wi::lua::SError(L, "Pick(Ray ray, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) last argument is not of type Scene!"); + wi::lua::SError(L, "Pick(Ray ray, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene, opt uint lod) 4th argument is not of type Scene!"); } } } } - auto pick = wi::scene::Pick(ray->ray, renderTypeMask, layerMask, *scene); + auto pick = wi::scene::Pick(ray->ray, renderTypeMask, layerMask, *scene, lod); wi::lua::SSetLongLong(L, pick.entity); Luna::push(L, new Vector_BindLua(XMLoadFloat3(&pick.position))); Luna::push(L, new Vector_BindLua(XMLoadFloat3(&pick.normal))); @@ -160,11 +166,11 @@ int Pick(lua_State* L) return 4; } - wi::lua::SError(L, "Pick(Ray ray, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) first argument must be of Ray type!"); + wi::lua::SError(L, "Pick(Ray ray, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene, opt uint lod) first argument must be of Ray type!"); } else { - wi::lua::SError(L, "Pick(Ray ray, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) not enough arguments!"); + wi::lua::SError(L, "Pick(Ray ray, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene, opt uint lod) not enough arguments!"); } return 0; @@ -180,6 +186,7 @@ int SceneIntersectSphere(lua_State* L) uint32_t renderTypeMask = wi::enums::RENDERTYPE_OPAQUE; uint32_t layerMask = 0xFFFFFFFF; Scene* scene = GetGlobalScene(); + uint32_t lod = 0; if (argc > 1) { renderTypeMask = (uint32_t)wi::lua::SGetInt(L, 2); @@ -194,15 +201,20 @@ int SceneIntersectSphere(lua_State* L) if (custom_scene) { scene = custom_scene->scene; + + if (argc > 4) + { + lod = (uint32_t)wi::lua::SGetInt(L, 5); + } } else { - wi::lua::SError(L, "SceneIntersectSphere(Sphere sphere, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) last argument is not of type Scene!"); + wi::lua::SError(L, "SceneIntersectSphere(Sphere sphere, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene, opt uint lod) 4th argument is not of type Scene!"); } } } } - auto pick = wi::scene::SceneIntersectSphere(sphere->sphere, renderTypeMask, layerMask, *scene); + auto pick = wi::scene::SceneIntersectSphere(sphere->sphere, renderTypeMask, layerMask, *scene, lod); wi::lua::SSetLongLong(L, pick.entity); Luna::push(L, new Vector_BindLua(XMLoadFloat3(&pick.position))); Luna::push(L, new Vector_BindLua(XMLoadFloat3(&pick.normal))); @@ -210,11 +222,11 @@ int SceneIntersectSphere(lua_State* L) return 4; } - wi::lua::SError(L, "SceneIntersectSphere(Sphere sphere, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) first argument must be of Sphere type!"); + wi::lua::SError(L, "SceneIntersectSphere(Sphere sphere, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene, opt uint lod) first argument must be of Sphere type!"); } else { - wi::lua::SError(L, "SceneIntersectSphere(Sphere sphere, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) not enough arguments!"); + wi::lua::SError(L, "SceneIntersectSphere(Sphere sphere, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene, opt uint lod) not enough arguments!"); } return 0; @@ -230,6 +242,7 @@ int SceneIntersectCapsule(lua_State* L) uint32_t renderTypeMask = wi::enums::RENDERTYPE_OPAQUE; uint32_t layerMask = 0xFFFFFFFF; Scene* scene = GetGlobalScene(); + uint32_t lod = 0; if (argc > 1) { renderTypeMask = (uint32_t)wi::lua::SGetInt(L, 2); @@ -244,15 +257,20 @@ int SceneIntersectCapsule(lua_State* L) if (custom_scene) { scene = custom_scene->scene; + + if (argc > 4) + { + lod = (uint32_t)wi::lua::SGetInt(L, 5); + } } else { - wi::lua::SError(L, "SceneIntersectCapsule(Capsule capsule, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) last argument is not of type Scene!"); + wi::lua::SError(L, "SceneIntersectCapsule(Capsule capsule, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene, opt uint lod) 4th argument is not of type Scene!"); } } } } - auto pick = wi::scene::SceneIntersectCapsule(capsule->capsule, renderTypeMask, layerMask, *scene); + auto pick = wi::scene::SceneIntersectCapsule(capsule->capsule, renderTypeMask, layerMask, *scene, lod); wi::lua::SSetLongLong(L, pick.entity); Luna::push(L, new Vector_BindLua(XMLoadFloat3(&pick.position))); Luna::push(L, new Vector_BindLua(XMLoadFloat3(&pick.normal))); @@ -260,11 +278,11 @@ int SceneIntersectCapsule(lua_State* L) return 4; } - wi::lua::SError(L, "SceneIntersectCapsule(Capsule capsule, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) first argument must be of Capsule type!"); + wi::lua::SError(L, "SceneIntersectCapsule(Capsule capsule, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene, opt uint lod) first argument must be of Capsule type!"); } else { - wi::lua::SError(L, "SceneIntersectCapsule(Capsule capsule, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) not enough arguments!"); + wi::lua::SError(L, "SceneIntersectCapsule(Capsule capsule, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene, opt uint lod) not enough arguments!"); } return 0; @@ -610,8 +628,6 @@ int Scene_BindLua::Component_CreateLight(lua_State* L) { Entity entity = (Entity)wi::lua::SGetLongLong(L, 1); - scene->aabb_lights.Create(entity); - LightComponent& component = scene->lights.Create(entity); Luna::push(L, new LightComponent_BindLua(&component)); return 1; @@ -663,8 +679,6 @@ int Scene_BindLua::Component_CreateObject(lua_State* L) { Entity entity = (Entity)wi::lua::SGetLongLong(L, 1); - scene->aabb_objects.Create(entity); - ObjectComponent& component = scene->objects.Create(entity); Luna::push(L, new ObjectComponent_BindLua(&component)); return 1; diff --git a/WickedEngine/wiScene_Serializers.cpp b/WickedEngine/wiScene_Serializers.cpp index f80334899..7c6baf2a0 100644 --- a/WickedEngine/wiScene_Serializers.cpp +++ b/WickedEngine/wiScene_Serializers.cpp @@ -1658,7 +1658,7 @@ namespace wi::scene } else { - // Old serialization path with hard coded componentn types: + // Old serialization path with hard coded component types: names.Serialize(archive, seri); layers.Serialize(archive, seri); transforms.Serialize(archive, seri); @@ -1672,18 +1672,19 @@ namespace wi::scene meshes.Serialize(archive, seri); impostors.Serialize(archive, seri); objects.Serialize(archive, seri); - aabb_objects.Serialize(archive, seri); + ComponentManager aabbs_tmp; // no longer needed from serializer + aabbs_tmp.Serialize(archive, seri); rigidbodies.Serialize(archive, seri); softbodies.Serialize(archive, seri); armatures.Serialize(archive, seri); lights.Serialize(archive, seri); - aabb_lights.Serialize(archive, seri); + aabbs_tmp.Serialize(archive, seri); cameras.Serialize(archive, seri); probes.Serialize(archive, seri); - aabb_probes.Serialize(archive, seri); + aabbs_tmp.Serialize(archive, seri); forces.Serialize(archive, seri); decals.Serialize(archive, seri); - aabb_decals.Serialize(archive, seri); + aabbs_tmp.Serialize(archive, seri); animations.Serialize(archive, seri); emitters.Serialize(archive, seri); hairs.Serialize(archive, seri); @@ -2051,7 +2052,7 @@ namespace wi::scene archive >> component_exists; if (component_exists) { - auto& component = aabb_objects.Create(entity); + auto component = wi::primitive::AABB(); // no longer needed to be serialized component.Serialize(archive, seri); } } @@ -2096,7 +2097,7 @@ namespace wi::scene archive >> component_exists; if (component_exists) { - auto& component = aabb_lights.Create(entity); + auto component = wi::primitive::AABB(); // no longer needed to be serialized component.Serialize(archive, seri); } } @@ -2123,7 +2124,7 @@ namespace wi::scene archive >> component_exists; if (component_exists) { - auto& component = aabb_probes.Create(entity); + auto component = wi::primitive::AABB(); // no longer needed to be serialized component.Serialize(archive, seri); } } @@ -2150,7 +2151,7 @@ namespace wi::scene archive >> component_exists; if (component_exists) { - auto& component = aabb_decals.Create(entity); + auto component = wi::primitive::AABB(); // no longer needed to be serialized component.Serialize(archive, seri); } } @@ -2356,16 +2357,7 @@ namespace wi::scene } } { - auto component = aabb_objects.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } + archive << false; // aabb no longer needed to be serialized } { auto component = rigidbodies.GetComponent(entity); @@ -2416,16 +2408,7 @@ namespace wi::scene } } { - auto component = aabb_lights.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } + archive << false; // aabb no longer needed to be serialized } { auto component = cameras.GetComponent(entity); @@ -2452,16 +2435,7 @@ namespace wi::scene } } { - auto component = aabb_probes.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } + archive << false; // aabb no longer needed to be serialized } { auto component = forces.GetComponent(entity); @@ -2488,16 +2462,7 @@ namespace wi::scene } } { - auto component = aabb_decals.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } + archive << false; // aabb no longer needed to be serialized } { auto component = animations.GetComponent(entity); diff --git a/WickedEngine/wiTerrain.cpp b/WickedEngine/wiTerrain.cpp index 58831b637..c7b975107 100644 --- a/WickedEngine/wiTerrain.cpp +++ b/WickedEngine/wiTerrain.cpp @@ -1055,7 +1055,6 @@ namespace wi::terrain Entity object_entity = CreateEntity(); tmp_scene.names.Create(object_entity) = name; tmp_scene.objects.Create(object_entity) = object; - tmp_scene.aabb_objects.Create(object_entity); tmp_scene.transforms.Create(object_entity); wi::Archive archive; EntitySerializer seri; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 562dde2d6..a71a94637 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 38; + const int revision = 39; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);