Browse Source

Add the physics playground

Panagiotis Christopoulos Charitos 7 years ago
parent
commit
0b2523bb6a
39 changed files with 387 additions and 108 deletions
  1. 2 0
      .gitignore
  2. 1 0
      samples/CMakeLists.txt
  3. 3 7
      samples/common/Framework.cpp
  4. 4 0
      samples/physics_playground/CMakeLists.txt
  5. 77 0
      samples/physics_playground/Main.cpp
  6. 29 0
      samples/physics_playground/assets/Material-material.ankimtl
  7. 29 0
      samples/physics_playground/assets/Material_001-material.ankimtl
  8. 5 0
      samples/physics_playground/assets/Suzanne.ankicl
  9. BIN
      samples/physics_playground/assets/Suzanne.ankimesh
  10. 9 0
      samples/physics_playground/assets/SuzanneMaterial-material.ankimdl
  11. 5 0
      samples/physics_playground/assets/floor.ankicl
  12. BIN
      samples/physics_playground/assets/floor.ankimesh
  13. 9 0
      samples/physics_playground/assets/floorMaterial-material.ankimdl
  14. BIN
      samples/physics_playground/assets/physics_playground.blend
  15. 5 0
      samples/physics_playground/assets/walls.ankicl
  16. BIN
      samples/physics_playground/assets/walls.ankimesh
  17. 9 0
      samples/physics_playground/assets/wallsMaterial_001-material.ankimdl
  18. 1 0
      src/anki/Scene.h
  19. 3 6
      src/anki/physics/PhysicsBody.cpp
  20. 1 2
      src/anki/physics/PhysicsBody.h
  21. 1 0
      src/anki/physics/PhysicsCollisionShape.cpp
  22. 1 0
      src/anki/scene/Forward.h
  23. 0 30
      src/anki/scene/Misc.h
  24. 15 14
      src/anki/scene/ModelNode.cpp
  25. 1 1
      src/anki/scene/ModelNode.h
  26. 10 8
      src/anki/scene/ParticleEmitterNode.cpp
  27. 2 3
      src/anki/scene/ParticleEmitterNode.h
  28. 48 0
      src/anki/scene/PhysicsDebugNode.cpp
  29. 27 0
      src/anki/scene/PhysicsDebugNode.h
  30. 1 1
      src/anki/scene/SceneGraph.cpp
  31. 13 0
      src/anki/scene/SceneGraph.h
  32. 1 1
      src/anki/scene/StaticCollisionNode.cpp
  33. 2 2
      src/anki/scene/StaticGeometryNode.cpp
  34. 2 2
      src/anki/scene/Visibility.cpp
  35. 8 5
      src/anki/scene/components/RenderComponent.cpp
  36. 37 19
      src/anki/scene/components/RenderComponent.h
  37. 13 0
      src/anki/scene/components/SpatialComponent.h
  38. 12 6
      tools/scene/Exporter.cpp
  39. 1 1
      tools/scene/ExporterMaterial.cpp

+ 2 - 0
.gitignore

@@ -11,5 +11,7 @@
 !*.md
 !*.md
 !*.txt
 !*.txt
 !*.glslp
 !*.glslp
+!*.anki*
+!*.blend
 !CMakeLists.txt
 !CMakeLists.txt
 build*/*
 build*/*

+ 1 - 0
samples/CMakeLists.txt

@@ -1,3 +1,4 @@
 add_definitions(-UANKI_BUILD)
 add_definitions(-UANKI_BUILD)
 add_subdirectory(simple_scene)
 add_subdirectory(simple_scene)
 add_subdirectory(sponza)
 add_subdirectory(sponza)
+add_subdirectory(physics_playground)

+ 3 - 7
samples/common/Framework.cpp

@@ -89,10 +89,6 @@ Error SampleApp::userMainLoop(Bool& quit)
 	{
 	{
 		// renderer.getDbg().flipFlags(DbgFlag::SPATIAL_COMPONENT);
 		// renderer.getDbg().flipFlags(DbgFlag::SPATIAL_COMPONENT);
 	}
 	}
-	if(in.getKey(KeyCode::F6) == 1)
-	{
-		renderer.getDbg().switchDepthTestEnabled();
-	}
 
 
 	if(in.getKey(KeyCode::UP))
 	if(in.getKey(KeyCode::UP))
 	{
 	{
@@ -124,14 +120,14 @@ Error SampleApp::userMainLoop(Bool& quit)
 		mover->moveLocalX(MOVE_DISTANCE);
 		mover->moveLocalX(MOVE_DISTANCE);
 	}
 	}
 
 
-	if(in.getKey(KeyCode::Z))
+	if(in.getKey(KeyCode::C))
 	{
 	{
-		mover->moveLocalY(MOVE_DISTANCE);
+		mover->moveLocalY(-MOVE_DISTANCE);
 	}
 	}
 
 
 	if(in.getKey(KeyCode::SPACE))
 	if(in.getKey(KeyCode::SPACE))
 	{
 	{
-		mover->moveLocalY(-MOVE_DISTANCE);
+		mover->moveLocalY(MOVE_DISTANCE);
 	}
 	}
 
 
 	if(in.getKey(KeyCode::W))
 	if(in.getKey(KeyCode::W))

+ 4 - 0
samples/physics_playground/CMakeLists.txt

@@ -0,0 +1,4 @@
+add_executable(physics_playground Main.cpp ../common/Framework.cpp)
+target_link_libraries(physics_playground anki)
+
+installExecutable(physics_playground)

+ 77 - 0
samples/physics_playground/Main.cpp

@@ -0,0 +1,77 @@
+// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <cstdio>
+#include "../common/Framework.h"
+
+using namespace anki;
+
+class MyApp : public SampleApp
+{
+public:
+	Error sampleExtraInit() override
+	{
+		ScriptResourcePtr script;
+		ANKI_CHECK(getResourceManager().loadResource("assets/scene.lua", script));
+		ANKI_CHECK(getScriptManager().evalString(script->getSource()));
+		return Error::NONE;
+	}
+
+	Error userMainLoop(Bool& quit) override;
+};
+
+Error MyApp::userMainLoop(Bool& quit)
+{
+	ANKI_CHECK(SampleApp::userMainLoop(quit));
+
+	if(getInput().getMouseButton(MouseButton::LEFT) == 1)
+	{
+		ANKI_LOGI("Firing a monkey");
+
+		static U instance = 0;
+
+		Transform camTrf = getSceneGraph().getActiveCameraNode().getComponent<MoveComponent>().getWorldTransform();
+
+		ModelNode* monkey;
+		ANKI_CHECK(getSceneGraph().newSceneNode<ModelNode>(
+			StringAuto(getAllocator()).sprintf("monkey%u", instance++).toCString(),
+			monkey,
+			"assets/SuzanneMaterial-material.ankimdl"));
+		// monkey->getComponent<MoveComponent>().setLocalTransform(camTrf);
+
+		BodyNode* body;
+		ANKI_CHECK(getSceneGraph().newSceneNode<BodyNode>(
+			StringAuto(getAllocator()).sprintf("bmonkey%u", instance++).toCString(), body, "assets/Suzanne.ankicl"));
+		body->getComponent<BodyComponent>().setTransform(camTrf);
+
+		body->addChild(monkey);
+	}
+
+	return Error::NONE;
+}
+
+int main(int argc, char* argv[])
+{
+	Error err = Error::NONE;
+
+	MyApp* app = new MyApp;
+	err = app->init(argc, argv, argv[0]);
+	if(!err)
+	{
+		err = app->mainLoop();
+	}
+
+	if(err)
+	{
+		ANKI_LOGE("Error reported. Bye!");
+	}
+	else
+	{
+		delete app;
+		ANKI_LOGI("Bye!!");
+	}
+
+	return 0;
+}

+ 29 - 0
samples/physics_playground/assets/Material-material.ankimtl

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!-- This file is auto generated by ExporterMaterial.cpp -->
+<material shaderProgram="shaders/GBufferGeneric.glslp">
+	
+	<mutators>
+		<mutator name="DIFFUSE_TEX" value="0"/>
+		<mutator name="SPECULAR_TEX" value="0"/>
+		<mutator name="ROUGHNESS_TEX" value="0"/>
+		<mutator name="METAL_TEX" value="0"/>
+		<mutator name="NORMAL_TEX" value="0"/>
+		<mutator name="PARALLAX" value="0"/>
+		<mutator name="EMISSIVE_TEX" value="0"/>
+	</mutators>
+	
+	<inputs>
+		<input shaderInput="mvp" builtin="MODEL_VIEW_PROJECTION_MATRIX"/>
+		<input shaderInput="rotationMat" builtin="ROTATION_MATRIX"/>
+		
+	
+		<input shaderInput="diffColor" value="0.548460 0.640000 0.063144"/>
+		<input shaderInput="specColor" value="0.500000 0.500000 0.500000"/>
+		<input shaderInput="roughness" value="0.097847" />
+		<input shaderInput="metallic" value="0.000000"/>
+		
+		<input shaderInput="emission" value="0.000000 0.000000 0.000000"/>
+		<input shaderInput="subsurface" value="0.000000"/>
+		
+	</inputs>
+</material>

+ 29 - 0
samples/physics_playground/assets/Material_001-material.ankimtl

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!-- This file is auto generated by ExporterMaterial.cpp -->
+<material shaderProgram="shaders/GBufferGeneric.glslp">
+	
+	<mutators>
+		<mutator name="DIFFUSE_TEX" value="0"/>
+		<mutator name="SPECULAR_TEX" value="0"/>
+		<mutator name="ROUGHNESS_TEX" value="0"/>
+		<mutator name="METAL_TEX" value="0"/>
+		<mutator name="NORMAL_TEX" value="0"/>
+		<mutator name="PARALLAX" value="0"/>
+		<mutator name="EMISSIVE_TEX" value="0"/>
+	</mutators>
+	
+	<inputs>
+		<input shaderInput="mvp" builtin="MODEL_VIEW_PROJECTION_MATRIX"/>
+		<input shaderInput="rotationMat" builtin="ROTATION_MATRIX"/>
+		
+	
+		<input shaderInput="diffColor" value="0.012172 0.367335 0.640000"/>
+		<input shaderInput="specColor" value="0.500000 0.500000 0.500000"/>
+		<input shaderInput="roughness" value="0.097847" />
+		<input shaderInput="metallic" value="0.000000"/>
+		
+		<input shaderInput="emission" value="0.000000 0.000000 0.000000"/>
+		<input shaderInput="subsurface" value="0.000000"/>
+		
+	</inputs>
+</material>

+ 5 - 0
samples/physics_playground/assets/Suzanne.ankicl

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<collisionShape>
+	<type>staticMesh</type>
+	<value>assets/Suzanne.ankimesh</value>
+</collisionShape>

BIN
samples/physics_playground/assets/Suzanne.ankimesh


+ 9 - 0
samples/physics_playground/assets/SuzanneMaterial-material.ankimdl

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<model>
+	<modelPatches>
+		<modelPatch>
+			<mesh>assets/Suzanne.ankimesh</mesh>
+			<material>assets/Material-material.ankimtl</material>
+		</modelPatch>
+	</modelPatches>
+</model>

+ 5 - 0
samples/physics_playground/assets/floor.ankicl

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<collisionShape>
+	<type>staticMesh</type>
+	<value>assets/floor.ankimesh</value>
+</collisionShape>

BIN
samples/physics_playground/assets/floor.ankimesh


+ 9 - 0
samples/physics_playground/assets/floorMaterial-material.ankimdl

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<model>
+	<modelPatches>
+		<modelPatch>
+			<mesh>assets/floor.ankimesh</mesh>
+			<material>assets/Material-material.ankimtl</material>
+		</modelPatch>
+	</modelPatches>
+</model>

BIN
samples/physics_playground/assets/physics_playground.blend


+ 5 - 0
samples/physics_playground/assets/walls.ankicl

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<collisionShape>
+	<type>staticMesh</type>
+	<value>assets/walls.ankimesh</value>
+</collisionShape>

BIN
samples/physics_playground/assets/walls.ankimesh


+ 9 - 0
samples/physics_playground/assets/wallsMaterial_001-material.ankimdl

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<model>
+	<modelPatches>
+		<modelPatch>
+			<mesh>assets/walls.ankimesh</mesh>
+			<material>assets/Material_001-material.ankimtl</material>
+		</modelPatch>
+	</modelPatches>
+</model>

+ 1 - 0
src/anki/Scene.h

@@ -20,6 +20,7 @@
 #include <anki/scene/OccluderNode.h>
 #include <anki/scene/OccluderNode.h>
 #include <anki/scene/DecalNode.h>
 #include <anki/scene/DecalNode.h>
 #include <anki/scene/Octree.h>
 #include <anki/scene/Octree.h>
+#include <anki/scene/PhysicsDebugNode.h>
 
 
 #include <anki/scene/components/MoveComponent.h>
 #include <anki/scene/components/MoveComponent.h>
 #include <anki/scene/components/RenderComponent.h>
 #include <anki/scene/components/RenderComponent.h>

+ 3 - 6
src/anki/physics/PhysicsBody.cpp

@@ -30,19 +30,16 @@ public:
 PhysicsBody::PhysicsBody(PhysicsWorld* world, const PhysicsBodyInitInfo& init)
 PhysicsBody::PhysicsBody(PhysicsWorld* world, const PhysicsBodyInitInfo& init)
 	: PhysicsObject(PhysicsObjectType::BODY, world)
 	: PhysicsObject(PhysicsObjectType::BODY, world)
 {
 {
-	if(init.m_static)
-	{
-		ANKI_ASSERT(init.m_mass > 0.0f);
-	}
+	const Bool dynamic = init.m_mass > 0.0f;
 
 
 	// Create motion state
 	// Create motion state
 	m_motionState = getAllocator().newInstance<MotionState>();
 	m_motionState = getAllocator().newInstance<MotionState>();
 	m_motionState->m_body = this;
 	m_motionState->m_body = this;
 
 
 	// Compute inertia
 	// Compute inertia
-	btCollisionShape* shape = init.m_shape->getBtShape(!init.m_static);
+	btCollisionShape* shape = init.m_shape->getBtShape(dynamic);
 	btVector3 localInertia(0, 0, 0);
 	btVector3 localInertia(0, 0, 0);
-	if(!init.m_static)
+	if(dynamic)
 	{
 	{
 		shape->calculateLocalInertia(init.m_mass, localInertia);
 		shape->calculateLocalInertia(init.m_mass, localInertia);
 	}
 	}

+ 1 - 2
src/anki/physics/PhysicsBody.h

@@ -18,11 +18,10 @@ class PhysicsBodyInitInfo
 {
 {
 public:
 public:
 	PhysicsCollisionShapePtr m_shape;
 	PhysicsCollisionShapePtr m_shape;
-	F32 m_mass = 0.0;
+	F32 m_mass = 0.0f;
 	Transform m_startTrf = Transform::getIdentity();
 	Transform m_startTrf = Transform::getIdentity();
 	Bool m_kinematic = false;
 	Bool m_kinematic = false;
 	Bool m_gravity = true;
 	Bool m_gravity = true;
-	Bool m_static = false;
 };
 };
 
 
 /// Rigid body.
 /// Rigid body.

+ 1 - 0
src/anki/physics/PhysicsCollisionShape.cpp

@@ -54,6 +54,7 @@ PhysicsTriangleSoup::~PhysicsTriangleSoup()
 {
 {
 	getAllocator().deleteInstance(m_staticShape);
 	getAllocator().deleteInstance(m_staticShape);
 	getAllocator().deleteInstance(m_shape);
 	getAllocator().deleteInstance(m_shape);
+	m_shape = nullptr;
 	getAllocator().deleteInstance(m_mesh);
 	getAllocator().deleteInstance(m_mesh);
 }
 }
 
 

+ 1 - 0
src/anki/scene/Forward.h

@@ -14,6 +14,7 @@ class FrustumComponent;
 class InstanceComponent;
 class InstanceComponent;
 class MoveComponent;
 class MoveComponent;
 class RenderComponent;
 class RenderComponent;
+class MaterialRenderComponent;
 class SpatialComponent;
 class SpatialComponent;
 class DecalComponent;
 class DecalComponent;
 class PortalComponent;
 class PortalComponent;

+ 0 - 30
src/anki/scene/Misc.h

@@ -1,30 +0,0 @@
-// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <anki/scene/components/SpatialComponent.h>
-
-namespace anki
-{
-
-/// @addtogroup scene
-/// @{
-
-/// A class that holds spatial information and implements the SpatialComponent virtuals. You just need to update the
-/// OBB manually
-class ObbSpatialComponent : public SpatialComponent
-{
-public:
-	Obb m_obb;
-
-	ObbSpatialComponent(SceneNode* node)
-		: SpatialComponent(node, &m_obb)
-	{
-	}
-};
-/// @}
-
-} // end namespace anki

+ 15 - 14
src/anki/scene/ModelNode.cpp

@@ -7,7 +7,7 @@
 #include <anki/scene/SceneGraph.h>
 #include <anki/scene/SceneGraph.h>
 #include <anki/scene/components/BodyComponent.h>
 #include <anki/scene/components/BodyComponent.h>
 #include <anki/scene/components/SkinComponent.h>
 #include <anki/scene/components/SkinComponent.h>
-#include <anki/scene/Misc.h>
+#include <anki/scene/components/RenderComponent.h>
 #include <anki/resource/ModelResource.h>
 #include <anki/resource/ModelResource.h>
 #include <anki/resource/ResourceManager.h>
 #include <anki/resource/ResourceManager.h>
 #include <anki/resource/SkeletonResource.h>
 #include <anki/resource/SkeletonResource.h>
@@ -17,7 +17,7 @@ namespace anki
 {
 {
 
 
 /// Render component implementation.
 /// Render component implementation.
-class ModelPatchNode::MRenderComponent : public RenderComponent
+class ModelPatchNode::MRenderComponent : public MaterialRenderComponent
 {
 {
 public:
 public:
 	const ModelPatchNode& getNode() const
 	const ModelPatchNode& getNode() const
@@ -26,7 +26,7 @@ public:
 	}
 	}
 
 
 	MRenderComponent(ModelPatchNode* node)
 	MRenderComponent(ModelPatchNode* node)
-		: RenderComponent(node, node->m_modelPatch->getMaterial())
+		: MaterialRenderComponent(node, node->m_modelPatch->getMaterial())
 	{
 	{
 	}
 	}
 
 
@@ -111,11 +111,11 @@ void ModelPatchNode::drawCallback(RenderQueueDrawContext& ctx, ConstWeakArray<vo
 		trfs[i] = Mat4(self2.getParent()->getComponentAt<MoveComponent>(0).getWorldTransform());
 		trfs[i] = Mat4(self2.getParent()->getComponentAt<MoveComponent>(0).getWorldTransform());
 	}
 	}
 
 
-	self.getComponentAt<RenderComponent>(1).allocateAndSetupUniforms(
-		self.m_modelPatch->getMaterial()->getDescriptorSetIndex(),
-		ctx,
-		ConstWeakArray<Mat4>(&trfs[0], userData.getSize()),
-		*ctx.m_stagingGpuAllocator);
+	static_cast<const MaterialRenderComponent&>(self.getComponentAt<RenderComponent>(1))
+		.allocateAndSetupUniforms(self.m_modelPatch->getMaterial()->getDescriptorSetIndex(),
+			ctx,
+			ConstWeakArray<Mat4>(&trfs[0], userData.getSize()),
+			*ctx.m_stagingGpuAllocator);
 
 
 	// Draw
 	// Draw
 	cmdb->drawElements(PrimitiveTopology::TRIANGLES,
 	cmdb->drawElements(PrimitiveTopology::TRIANGLES,
@@ -150,11 +150,11 @@ public:
 	}
 	}
 };
 };
 
 
-class ModelNode::MRenderComponent : public RenderComponent
+class ModelNode::MRenderComponent : public MaterialRenderComponent
 {
 {
 public:
 public:
 	MRenderComponent(ModelNode* node)
 	MRenderComponent(ModelNode* node)
-		: RenderComponent(node, node->m_model->getModelPatches()[0]->getMaterial())
+		: MaterialRenderComponent(node, node->m_model->getModelPatches()[0]->getMaterial())
 	{
 	{
 	}
 	}
 
 
@@ -300,10 +300,11 @@ void ModelNode::drawCallback(RenderQueueDrawContext& ctx, ConstWeakArray<void*>
 			trfs[i] = Mat4(self2.getComponent<MoveComponent>().getWorldTransform());
 			trfs[i] = Mat4(self2.getComponent<MoveComponent>().getWorldTransform());
 		}
 		}
 
 
-		self.getComponent<RenderComponent>().allocateAndSetupUniforms(patch->getMaterial()->getDescriptorSetIndex(),
-			ctx,
-			ConstWeakArray<Mat4>(&trfs[0], userData.getSize()),
-			*ctx.m_stagingGpuAllocator);
+		static_cast<const MaterialRenderComponent&>(self.getComponent<RenderComponent>())
+			.allocateAndSetupUniforms(patch->getMaterial()->getDescriptorSetIndex(),
+				ctx,
+				ConstWeakArray<Mat4>(&trfs[0], userData.getSize()),
+				*ctx.m_stagingGpuAllocator);
 
 
 		// Bones storage
 		// Bones storage
 		if(self.m_model->getSkeleton())
 		if(self.m_model->getSkeleton())

+ 1 - 1
src/anki/scene/ModelNode.h

@@ -6,11 +6,11 @@
 #pragma once
 #pragma once
 
 
 #include <anki/scene/SceneNode.h>
 #include <anki/scene/SceneNode.h>
-#include <anki/scene/components/RenderComponent.h>
 #include <anki/scene/components/MoveComponent.h>
 #include <anki/scene/components/MoveComponent.h>
 #include <anki/scene/components/SpatialComponent.h>
 #include <anki/scene/components/SpatialComponent.h>
 #include <anki/resource/ModelResource.h>
 #include <anki/resource/ModelResource.h>
 #include <anki/collision/Obb.h>
 #include <anki/collision/Obb.h>
+#include <anki/renderer/RenderQueue.h>
 
 
 namespace anki
 namespace anki
 {
 {

+ 10 - 8
src/anki/scene/ParticleEmitterNode.cpp

@@ -5,7 +5,9 @@
 
 
 #include <anki/scene/ParticleEmitterNode.h>
 #include <anki/scene/ParticleEmitterNode.h>
 #include <anki/scene/SceneGraph.h>
 #include <anki/scene/SceneGraph.h>
-#include <anki/scene/Misc.h>
+#include <anki/scene/components/MoveComponent.h>
+#include <anki/scene/components/SpatialComponent.h>
+#include <anki/scene/components/RenderComponent.h>
 #include <anki/resource/ModelResource.h>
 #include <anki/resource/ModelResource.h>
 #include <anki/resource/ResourceManager.h>
 #include <anki/resource/ResourceManager.h>
 #include <anki/util/Functions.h>
 #include <anki/util/Functions.h>
@@ -162,7 +164,7 @@ void Particle::revive(const ParticleEmitterNode& pe,
 #endif
 #endif
 
 
 /// The derived render component for particle emitters.
 /// The derived render component for particle emitters.
-class ParticleEmitterRenderComponent : public RenderComponent
+class ParticleEmitterRenderComponent : public MaterialRenderComponent
 {
 {
 public:
 public:
 	const ParticleEmitterNode& getNode() const
 	const ParticleEmitterNode& getNode() const
@@ -171,7 +173,7 @@ public:
 	}
 	}
 
 
 	ParticleEmitterRenderComponent(ParticleEmitterNode* node)
 	ParticleEmitterRenderComponent(ParticleEmitterNode* node)
-		: RenderComponent(node, node->m_particleEmitterResource->getMaterial())
+		: MaterialRenderComponent(node, node->m_particleEmitterResource->getMaterial())
 	{
 	{
 	}
 	}
 
 
@@ -304,11 +306,11 @@ void ParticleEmitterNode::drawCallback(RenderQueueDrawContext& ctx, ConstWeakArr
 
 
 		// Uniforms
 		// Uniforms
 		Array<Mat4, 1> trf = {{Mat4::getIdentity()}};
 		Array<Mat4, 1> trf = {{Mat4::getIdentity()}};
-		self.getComponent<RenderComponent>().allocateAndSetupUniforms(
-			self.m_particleEmitterResource->getMaterial()->getDescriptorSetIndex(),
-			ctx,
-			trf,
-			*ctx.m_stagingGpuAllocator);
+		static_cast<const MaterialRenderComponent&>(self.getComponent<RenderComponent>())
+			.allocateAndSetupUniforms(self.m_particleEmitterResource->getMaterial()->getDescriptorSetIndex(),
+				ctx,
+				trf,
+				*ctx.m_stagingGpuAllocator);
 
 
 		// Draw
 		// Draw
 		cmdb->drawArrays(PrimitiveTopology::TRIANGLE_STRIP, 4, self.m_aliveParticlesCount, 0, 0);
 		cmdb->drawArrays(PrimitiveTopology::TRIANGLE_STRIP, 4, self.m_aliveParticlesCount, 0, 0);

+ 2 - 3
src/anki/scene/ParticleEmitterNode.h

@@ -6,10 +6,9 @@
 #pragma once
 #pragma once
 
 
 #include <anki/scene/SceneNode.h>
 #include <anki/scene/SceneNode.h>
-#include <anki/scene/components/MoveComponent.h>
-#include <anki/scene/components/SpatialComponent.h>
-#include <anki/scene/components/RenderComponent.h>
 #include <anki/resource/ParticleEmitterResource.h>
 #include <anki/resource/ParticleEmitterResource.h>
+#include <anki/renderer/RenderQueue.h>
+#include <anki/collision/Obb.h>
 
 
 namespace anki
 namespace anki
 {
 {

+ 48 - 0
src/anki/scene/PhysicsDebugNode.cpp

@@ -0,0 +1,48 @@
+// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <anki/scene/PhysicsDebugNode.h>
+#include <anki/resource/ResourceManager.h>
+#include <anki/scene/components/RenderComponent.h>
+#include <anki/scene/components/SpatialComponent.h>
+#include <anki/scene/SceneGraph.h>
+
+namespace anki
+{
+
+/// Render component implementation.
+class PhysicsDebugNode::MyRenderComponent : public RenderComponent
+{
+public:
+	ShaderProgramResourcePtr m_prog;
+
+	MyRenderComponent(SceneNode* node)
+		: RenderComponent(node)
+	{
+		m_castsShadow = false;
+		m_isForwardShading = false;
+	}
+
+	void setupRenderableQueueElement(RenderableQueueElement& el) const override
+	{
+		// TODO
+	}
+};
+
+Error PhysicsDebugNode::init()
+{
+	MyRenderComponent* rcomp = newComponent<MyRenderComponent>(this);
+	ANKI_CHECK(getResourceManager().loadResource("shaders/SceneDebug.glslp", rcomp->m_prog));
+
+	ObbSpatialComponent* scomp = newComponent<ObbSpatialComponent>(this);
+	Vec3 center = (getSceneGraph().getSceneMax() + getSceneGraph().getSceneMin()) / 2.0f;
+	scomp->m_obb.setCenter(center.xyz0());
+	scomp->m_obb.setExtend((getSceneGraph().getSceneMax() - center).xyz0());
+	scomp->m_obb.setRotation(Mat3x4::getIdentity());
+
+	return Error::NONE;
+}
+
+} // end namespace anki

+ 27 - 0
src/anki/scene/PhysicsDebugNode.h

@@ -0,0 +1,27 @@
+// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <anki/scene/SceneNode.h>
+
+namespace anki
+{
+
+/// An always visible node that debug draws primitives of the physics world.
+class PhysicsDebugNode : public SceneNode
+{
+public:
+	PhysicsDebugNode(SceneGraph* scene, CString name);
+
+	~PhysicsDebugNode();
+
+	ANKI_USE_RESULT Error init();
+
+private:
+	class MyRenderComponent;
+};
+
+} // end namespace anki

+ 1 - 1
src/anki/scene/SceneGraph.cpp

@@ -101,7 +101,7 @@ Error SceneGraph::init(AllocAlignedCallback allocCb,
 	m_maxReflectionProxyDistance = config.getNumber("scene.imageReflectionMaxDistance");
 	m_maxReflectionProxyDistance = config.getNumber("scene.imageReflectionMaxDistance");
 
 
 	m_octree = m_alloc.newInstance<Octree>(m_alloc);
 	m_octree = m_alloc.newInstance<Octree>(m_alloc);
-	m_octree->init(Vec3(-1000.0f), Vec3(1000.0f), 5); // TODO
+	m_octree->init(m_sceneMin, m_sceneMax, 5); // TODO
 
 
 	// Init the default main camera
 	// Init the default main camera
 	ANKI_CHECK(newSceneNode<PerspectiveCameraNode>("mainCamera", m_defaultMainCam));
 	ANKI_CHECK(newSceneNode<PerspectiveCameraNode>("mainCamera", m_defaultMainCam));

+ 13 - 0
src/anki/scene/SceneGraph.h

@@ -167,6 +167,16 @@ public:
 		return m_stats;
 		return m_stats;
 	}
 	}
 
 
+	const Vec3& getSceneMin() const
+	{
+		return m_sceneMin;
+	}
+
+	const Vec3& getSceneMax() const
+	{
+		return m_sceneMax;
+	}
+
 anki_internal:
 anki_internal:
 	ResourceManager& getResourceManager()
 	ResourceManager& getResourceManager()
 	{
 	{
@@ -262,6 +272,9 @@ private:
 
 
 	Octree* m_octree = nullptr;
 	Octree* m_octree = nullptr;
 
 
+	Vec3 m_sceneMin = {-1000.0f, -200.0f, -1000.0f};
+	Vec3 m_sceneMax = {1000.0f, 200.0f, 1000.0f};
+
 	Atomic<U32> m_objectsMarkedForDeletionCount;
 	Atomic<U32> m_objectsMarkedForDeletionCount;
 
 
 	F32 m_maxReflectionProxyDistance = 0.0;
 	F32 m_maxReflectionProxyDistance = 0.0;

+ 1 - 1
src/anki/scene/StaticCollisionNode.cpp

@@ -30,7 +30,7 @@ Error StaticCollisionNode::init(const CString& resourceFname, const Transform& t
 	// Create body
 	// Create body
 	PhysicsBodyInitInfo init;
 	PhysicsBodyInitInfo init;
 	init.m_shape = m_rsrc->getShape();
 	init.m_shape = m_rsrc->getShape();
-	init.m_static = true;
+	init.m_mass = 0.0f;
 	init.m_startTrf = transform;
 	init.m_startTrf = transform;
 
 
 	m_body = getSceneGraph().getPhysicsWorld().newInstance<PhysicsBody>(init);
 	m_body = getSceneGraph().getPhysicsWorld().newInstance<PhysicsBody>(init);

+ 2 - 2
src/anki/scene/StaticGeometryNode.cpp

@@ -12,13 +12,13 @@ namespace anki
 {
 {
 
 
 /// The implementation of static geometry node renderable component.
 /// The implementation of static geometry node renderable component.
-class StaticGeometryRenderComponent : public RenderComponent
+class StaticGeometryRenderComponent : public MaterialRenderComponent
 {
 {
 public:
 public:
 	StaticGeometryPatchNode* m_node;
 	StaticGeometryPatchNode* m_node;
 
 
 	StaticGeometryRenderComponent(StaticGeometryPatchNode* node)
 	StaticGeometryRenderComponent(StaticGeometryPatchNode* node)
-		: RenderComponent(node, node->m_modelPatch->getMaterial())
+		: MaterialRenderComponent(node, node->m_modelPatch->getMaterial())
 		, m_node(node)
 		, m_node(node)
 	{
 	{
 	}
 	}

+ 2 - 2
src/anki/scene/Visibility.cpp

@@ -350,7 +350,7 @@ void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
 			if(wantsRenderComponents || (wantsShadowCasters && rc->getCastsShadow()))
 			if(wantsRenderComponents || (wantsShadowCasters && rc->getCastsShadow()))
 			{
 			{
 				RenderableQueueElement* el;
 				RenderableQueueElement* el;
-				if(rc->getMaterial().isForwardShading())
+				if(rc->isForwardShading())
 				{
 				{
 					el = result.m_forwardShadingRenderables.newElement(alloc);
 					el = result.m_forwardShadingRenderables.newElement(alloc);
 				}
 				}
@@ -366,7 +366,7 @@ void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
 				el->m_distanceFromCamera = max(0.0f, sps[0].m_sp->getAabb().testPlane(nearPlane));
 				el->m_distanceFromCamera = max(0.0f, sps[0].m_sp->getAabb().testPlane(nearPlane));
 
 
 				if(wantsEarlyZ && el->m_distanceFromCamera < m_frcCtx->m_visCtx->m_earlyZDist
 				if(wantsEarlyZ && el->m_distanceFromCamera < m_frcCtx->m_visCtx->m_earlyZDist
-					&& !rc->getMaterial().isForwardShading())
+					&& !rc->isForwardShading())
 				{
 				{
 					RenderableQueueElement* el2 = result.m_earlyZRenderables.newElement(alloc);
 					RenderableQueueElement* el2 = result.m_earlyZRenderables.newElement(alloc);
 					*el2 = *el;
 					*el2 = *el;

+ 8 - 5
src/anki/scene/components/RenderComponent.cpp

@@ -12,8 +12,8 @@
 namespace anki
 namespace anki
 {
 {
 
 
-RenderComponent::RenderComponent(SceneNode* node, MaterialResourcePtr mtl)
-	: SceneComponent(SceneComponentType::RENDER, node)
+MaterialRenderComponent::MaterialRenderComponent(SceneNode* node, MaterialResourcePtr mtl)
+	: RenderComponent(node)
 	, m_mtl(mtl)
 	, m_mtl(mtl)
 {
 {
 	// Create the material variables
 	// Create the material variables
@@ -23,14 +23,17 @@ RenderComponent::RenderComponent(SceneNode* node, MaterialResourcePtr mtl)
 	{
 	{
 		m_vars[count++].m_mvar = &mv;
 		m_vars[count++].m_mvar = &mv;
 	}
 	}
+
+	m_isForwardShading = mtl->isForwardShading();
+	m_castsShadow = mtl->castsShadow();
 }
 }
 
 
-RenderComponent::~RenderComponent()
+MaterialRenderComponent::~MaterialRenderComponent()
 {
 {
 	m_vars.destroy(getAllocator());
 	m_vars.destroy(getAllocator());
 }
 }
 
 
-void RenderComponent::allocateAndSetupUniforms(
+void MaterialRenderComponent::allocateAndSetupUniforms(
 	U set, const RenderQueueDrawContext& ctx, ConstWeakArray<Mat4> transforms, StagingGpuMemoryManager& alloc) const
 	U set, const RenderQueueDrawContext& ctx, ConstWeakArray<Mat4> transforms, StagingGpuMemoryManager& alloc) const
 {
 {
 	ANKI_ASSERT(transforms.getSize() <= MAX_INSTANCES);
 	ANKI_ASSERT(transforms.getSize() <= MAX_INSTANCES);
@@ -62,7 +65,7 @@ void RenderComponent::allocateAndSetupUniforms(
 	// Iterate variables
 	// Iterate variables
 	for(auto it = m_vars.getBegin(); it != m_vars.getEnd(); ++it)
 	for(auto it = m_vars.getBegin(); it != m_vars.getEnd(); ++it)
 	{
 	{
-		const RenderComponentVariable& var = *it;
+		const MaterialRenderComponentVariable& var = *it;
 		const MaterialVariable& mvar = var.getMaterialVariable();
 		const MaterialVariable& mvar = var.getMaterialVariable();
 		const ShaderProgramResourceInputVariable& progvar = mvar.getShaderProgramResourceInputVariable();
 		const ShaderProgramResourceInputVariable& progvar = mvar.getShaderProgramResourceInputVariable();
 
 

+ 37 - 19
src/anki/scene/components/RenderComponent.h

@@ -17,14 +17,42 @@ namespace anki
 /// @addtogroup scene
 /// @addtogroup scene
 /// @{
 /// @{
 
 
+/// Render component interface. Implemented by renderable scene nodes
+class RenderComponent : public SceneComponent
+{
+public:
+	static const SceneComponentType CLASS_TYPE = SceneComponentType::RENDER;
+
+	RenderComponent(SceneNode* node)
+		: SceneComponent(CLASS_TYPE, node)
+	{
+	}
+
+	Bool getCastsShadow() const
+	{
+		return m_castsShadow;
+	}
+
+	Bool isForwardShading() const
+	{
+		return m_isForwardShading;
+	}
+
+	virtual void setupRenderableQueueElement(RenderableQueueElement& el) const = 0;
+
+protected:
+	Bool8 m_castsShadow = false;
+	Bool8 m_isForwardShading = false;
+};
+
 /// A wrapper on top of MaterialVariable
 /// A wrapper on top of MaterialVariable
-class RenderComponentVariable
+class MaterialRenderComponentVariable
 {
 {
-	friend class RenderComponent;
+	friend class MaterialRenderComponent;
 
 
 public:
 public:
-	RenderComponentVariable() = default;
-	~RenderComponentVariable() = default;
+	MaterialRenderComponentVariable() = default;
+	~MaterialRenderComponentVariable() = default;
 
 
 	template<typename T>
 	template<typename T>
 	const T& getValue() const
 	const T& getValue() const
@@ -41,17 +69,15 @@ private:
 	const MaterialVariable* m_mvar = nullptr;
 	const MaterialVariable* m_mvar = nullptr;
 };
 };
 
 
-/// RenderComponent interface. Implemented by renderable scene nodes
-class RenderComponent : public SceneComponent
+/// Material render component interface.
+class MaterialRenderComponent : public RenderComponent
 {
 {
 public:
 public:
-	static const SceneComponentType CLASS_TYPE = SceneComponentType::RENDER;
+	using Variables = DynamicArray<MaterialRenderComponentVariable>;
 
 
-	using Variables = DynamicArray<RenderComponentVariable>;
+	MaterialRenderComponent(SceneNode* node, MaterialResourcePtr mtl);
 
 
-	RenderComponent(SceneNode* node, MaterialResourcePtr mtl);
-
-	~RenderComponent();
+	~MaterialRenderComponent();
 
 
 	Variables::Iterator getVariablesBegin()
 	Variables::Iterator getVariablesBegin()
 	{
 	{
@@ -80,12 +106,6 @@ public:
 		return *m_mtl;
 		return *m_mtl;
 	}
 	}
 
 
-	Bool getCastsShadow() const
-	{
-		const MaterialResource& mtl = getMaterial();
-		return mtl.castsShadow();
-	}
-
 	/// Iterate variables using a lambda
 	/// Iterate variables using a lambda
 	template<typename Func>
 	template<typename Func>
 	ANKI_USE_RESULT Error iterateVariables(Func func)
 	ANKI_USE_RESULT Error iterateVariables(Func func)
@@ -105,8 +125,6 @@ public:
 		ConstWeakArray<Mat4> transforms,
 		ConstWeakArray<Mat4> transforms,
 		StagingGpuMemoryManager& alloc) const;
 		StagingGpuMemoryManager& alloc) const;
 
 
-	virtual void setupRenderableQueueElement(RenderableQueueElement& el) const = 0;
-
 private:
 private:
 	Variables m_vars;
 	Variables m_vars;
 	MaterialResourcePtr m_mtl;
 	MaterialResourcePtr m_mtl;

+ 13 - 0
src/anki/scene/components/SpatialComponent.h

@@ -104,6 +104,19 @@ private:
 
 
 	OctreePlaceable m_octreeInfo;
 	OctreePlaceable m_octreeInfo;
 };
 };
+
+/// A class that holds spatial information and implements the SpatialComponent virtuals. You just need to update the
+/// OBB manually
+class ObbSpatialComponent : public SpatialComponent
+{
+public:
+	Obb m_obb;
+
+	ObbSpatialComponent(SceneNode* node)
+		: SpatialComponent(node, &m_obb)
+	{
+	}
+};
 /// @}
 /// @}
 
 
 } // end namespace anki
 } // end namespace anki

+ 12 - 6
tools/scene/Exporter.cpp

@@ -1146,22 +1146,28 @@ void Exporter::exportAll()
 		// Write the collision node
 		// Write the collision node
 		if(!node.m_collisionMesh.empty())
 		if(!node.m_collisionMesh.empty())
 		{
 		{
-			bool found = false;
 			unsigned i = 0;
 			unsigned i = 0;
-			for(; i < m_scene->mNumMeshes; i++)
+			if(node.m_collisionMesh == "self")
 			{
 			{
-				if(m_scene->mMeshes[i]->mName.C_Str() == node.m_collisionMesh)
+				i = model.m_meshIndex;
+			}
+			else
+			{
+				for(; i < m_scene->mNumMeshes; i++)
 				{
 				{
-					found = true;
-					break;
+					if(m_scene->mMeshes[i]->mName.C_Str() == node.m_collisionMesh)
+					{
+						break;
+					}
 				}
 				}
 			}
 			}
 
 
+			const bool found = i < m_scene->mNumMeshes;
 			if(found)
 			if(found)
 			{
 			{
 				exportCollisionMesh(i);
 				exportCollisionMesh(i);
 
 
-				std::string fname = m_rpath + node.m_collisionMesh + ".ankicl";
+				std::string fname = m_rpath + getMeshName(getMeshAt(i)) + ".ankicl";
 				file << "node = scene:newStaticCollisionNode(\"" << nodeName << "_cl\", \"" << fname << "\", trf)\n";
 				file << "node = scene:newStaticCollisionNode(\"" << nodeName << "_cl\", \"" << fname << "\", trf)\n";
 			}
 			}
 			else
 			else

+ 1 - 1
tools/scene/ExporterMaterial.cpp

@@ -8,7 +8,7 @@
 
 
 const char* MATERIAL_TEMPLATE = R"(<?xml version="1.0" encoding="UTF-8" ?>
 const char* MATERIAL_TEMPLATE = R"(<?xml version="1.0" encoding="UTF-8" ?>
 <!-- This file is auto generated by ExporterMaterial.cpp -->
 <!-- This file is auto generated by ExporterMaterial.cpp -->
-<material shaderProgram="shaders/GBufferGeneric.ankiprog">
+<material shaderProgram="shaders/GBufferGeneric.glslp">
 	
 	
 	<mutators>
 	<mutators>
 		<mutator name="DIFFUSE_TEX" value="%diffTexMutator%"/>
 		<mutator name="DIFFUSE_TEX" value="%diffTexMutator%"/>