Browse Source

Work on particles exporting

Panagiotis Christopoulos Charitos 10 years ago
parent
commit
797dbdc6c2
6 changed files with 206 additions and 46 deletions
  1. 16 12
      src/physics/PhysicsWorld.cpp
  2. 27 31
      src/scene/ParticleEmitter.cpp
  3. 123 0
      src/script/Scene.cpp
  4. 16 0
      src/script/Scene.xml
  5. 3 3
      testapp/Main.cpp
  6. 21 0
      tools/scene/Exporter.cpp

+ 16 - 12
src/physics/PhysicsWorld.cpp

@@ -78,6 +78,9 @@ Error PhysicsWorld::create(AllocAlignedCallback allocCb, void* allocCbData)
 	m_sceneCollision = NewtonCreateSceneCollision(m_world, 0);
 	Mat4 trf = Mat4::getIdentity();
 	m_sceneBody = NewtonCreateDynamicBody(m_world, m_sceneCollision, &trf[0]);
+	NewtonBodySetMaterialGroupID(
+		m_sceneBody, NewtonMaterialGetDefaultGroupID(m_world));
+
 	NewtonDestroyCollision(m_sceneCollision); // destroy old scene
 	m_sceneCollision = NewtonBodyGetCollision(m_sceneBody);
 
@@ -86,9 +89,9 @@ Error PhysicsWorld::create(AllocAlignedCallback allocCb, void* allocCbData)
 		destroyCallback);
 
 	// Set callbacks
-	I defaultMaterialID = NewtonMaterialGetDefaultGroupID(m_world);
 	NewtonMaterialSetCollisionCallback(
-		m_world, defaultMaterialID, defaultMaterialID, nullptr,
+		m_world, NewtonMaterialGetDefaultGroupID(m_world),
+		NewtonMaterialGetDefaultGroupID(m_world), nullptr,
 		onAabbOverlapCallback, onContactCallback);
 
 	return err;
@@ -180,24 +183,25 @@ void PhysicsWorld::onContactCallback(
 	const NewtonBody* body0 = NewtonJointGetBody0(contactJoint);
 	const NewtonBody* body1 = NewtonJointGetBody1(contactJoint);
 
+	F32 friction0 = 0.01;
+	F32 elasticity0 = 0.001;
+	F32 friction1 = friction0;
+	F32 elasticity1 = elasticity0;
+
 	void* userData = NewtonBodyGetUserData(body0);
-	if(!userData)
+	if(userData)
 	{
-		return;
+		friction0 = static_cast<PhysicsBody*>(userData)->getFriction();
+		elasticity0 = static_cast<PhysicsBody*>(userData)->getElasticity();
 	}
 
-	F32 friction0 = static_cast<PhysicsBody*>(userData)->getFriction();
-	F32 elasticity0 = static_cast<PhysicsBody*>(userData)->getElasticity();
-
 	userData = NewtonBodyGetUserData(body1);
-	if(!userData)
+	if(userData)
 	{
-		return;
+		friction1 = static_cast<PhysicsBody*>(userData)->getFriction();
+		elasticity1 = static_cast<PhysicsBody*>(userData)->getElasticity();
 	}
 
-	F32 friction1 = static_cast<PhysicsBody*>(userData)->getFriction();
-	F32 elasticity1 = static_cast<PhysicsBody*>(userData)->getElasticity();
-
 	F32 friction = friction0 + friction1;
 	F32 elasticity = elasticity0 + elasticity1;
 

+ 27 - 31
src/scene/ParticleEmitter.cpp

@@ -24,7 +24,7 @@ const PtrSize VERT_SIZE = COMPONENTS * sizeof(F32);
 //==============================================================================
 static F32 getRandom(F32 initial, F32 deviation)
 {
-	return (deviation == 0.0) 
+	return (deviation == 0.0)
 		? initial
 		: initial + randFloat(deviation) * 2.0 - deviation;
 }
@@ -295,23 +295,19 @@ Error ParticleEmitter::create(
 
 	// Move component
 	comp = getSceneAllocator().newInstance<MoveComponent>(this);
-
-	addComponent(comp);
-	comp->setAutomaticCleanup(true);
+	addComponent(comp, true);
 
 	// Spatial component
 	comp = getSceneAllocator().newInstance<SpatialComponent>(this, &m_obb);
-	addComponent(comp);
-	comp->setAutomaticCleanup(true);
+	addComponent(comp, true);
 
 	// Render component
-	ParticleEmitterRenderComponent* rcomp = 
+	ParticleEmitterRenderComponent* rcomp =
 		getSceneAllocator().newInstance<ParticleEmitterRenderComponent>(this);
 
 	ANKI_CHECK(rcomp->create());
-
-	addComponent(comp);
-	comp->setAutomaticCleanup(true);
+	comp = rcomp;
+	addComponent(comp, true);
 
 	// Other
 	m_obb.setCenter(Vec4(0.0));
@@ -337,11 +333,11 @@ Error ParticleEmitter::create(
 
 	// Create the vertex buffer and object
 	PtrSize buffSize = m_maxNumOfParticles * VERT_SIZE * 3;
-	ANKI_CHECK(m_vertBuff.create(&getSceneGraph().getGrManager(), 
-		GL_ARRAY_BUFFER, nullptr, buffSize, 
+	ANKI_CHECK(m_vertBuff.create(&getSceneGraph().getGrManager(),
+		GL_ARRAY_BUFFER, nullptr, buffSize,
 		GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT));
 
-	m_vertBuffMapping = 
+	m_vertBuffMapping =
 		static_cast<U8*>(m_vertBuff.getPersistentMappingAddress());
 
 	return ErrorCode::NONE;
@@ -365,27 +361,27 @@ Error ParticleEmitter::buildRendering(RenderingBuildData& data)
 	PipelineHandle ppline;
 	err = m_particleEmitterResource->getMaterial().getProgramPipeline(
 		key, ppline);
-	
+
 	if(!err)
 	{
 		ppline.bind(data.m_jobs);
 
-		PtrSize offset = 
+		PtrSize offset =
 			(getGlobalTimestamp() % 3) * (m_vertBuff.getSize() / 3);
 
 		// Position
-		m_vertBuff.bindVertexBuffer(data.m_jobs, 
+		m_vertBuff.bindVertexBuffer(data.m_jobs,
 			3, GL_FLOAT, false, VERT_SIZE, offset + 0, 0);
 
 		// Scale
-		m_vertBuff.bindVertexBuffer(data.m_jobs, 
+		m_vertBuff.bindVertexBuffer(data.m_jobs,
 			1, GL_FLOAT, false, VERT_SIZE, offset + sizeof(F32) * 3, 6);
 
 		// Alpha
-		m_vertBuff.bindVertexBuffer(data.m_jobs, 
+		m_vertBuff.bindVertexBuffer(data.m_jobs,
 			1, GL_FLOAT, false, VERT_SIZE, offset + sizeof(F32) * 4, 7);
 
-		data.m_jobs.drawArrays(GL_POINTS, 
+		data.m_jobs.drawArrays(GL_POINTS,
 			m_aliveParticlesCount,
 			data.m_subMeshIndicesCount);
 	}
@@ -436,12 +432,12 @@ void ParticleEmitter::createParticlesSimpleSimulation()
 
 	for(U i = 0; i < m_maxNumOfParticles; i++)
 	{
-		ParticleSimple* part = 
+		ParticleSimple* part =
 			getSceneAllocator().newInstance<ParticleSimple>();
 
-		part->m_size = 
+		part->m_size =
 			getRandom(m_particle.m_size, m_particle.m_sizeDeviation);
-		part->m_alpha = 
+		part->m_alpha =
 			getRandom(m_particle.m_alpha, m_particle.m_alphaDeviation);
 
 		m_particles[i] = part;
@@ -459,7 +455,7 @@ Error ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime)
 	Vec4 aabbmax(MIN_F32, MIN_F32, MIN_F32, 0.0);
 	m_aliveParticlesCount = 0;
 
-	F32* verts = (F32*)(m_vertBuffMapping 
+	F32* verts = (F32*)(m_vertBuffMapping
 		+ (getGlobalTimestamp() % 3) * (m_vertBuff.getSize() / 3));
 	F32* verts_base = verts;
 	(void)verts_base;
@@ -482,7 +478,7 @@ Error ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime)
 			// It's alive
 
 			// Do checks
-			ANKI_ASSERT(((PtrSize)verts + VERT_SIZE 
+			ANKI_ASSERT(((PtrSize)verts + VERT_SIZE
 				- (PtrSize)m_vertBuffMapping) <= m_vertBuff.getSize());
 
 			// This will calculate a new world transformation
@@ -533,7 +529,7 @@ Error ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime)
 	{
 		m_obb = Obb(Vec4(0.0), Mat3x4::getIdentity(), Vec4(0.001));
 	}
-	
+
 	getComponent<SpatialComponent>().markForUpdate();
 
 	//
@@ -592,14 +588,14 @@ Error ParticleEmitter::doInstancingCalcs()
 	if(err)	return err;
 
 	err = SceneNode::visitChildren([&](SceneNode& sn) -> Error
-	{	
+	{
 		if(sn.tryGetComponent<InstanceComponent>())
 		{
 			MoveComponent& move = sn.getComponent<MoveComponent>();
 
 			instanceMoves[instanceMovesCount++] = &move;
 
-			instancesTimestamp = 
+			instancesTimestamp =
 				std::max(instancesTimestamp, move.getTimestamp());
 		}
 
@@ -655,7 +651,7 @@ Error ParticleEmitter::doInstancingCalcs()
 			err = m_transforms.resize(getSceneAllocator(), instanceMovesCount);
 		}
 
-		if(!err && (transformsNeedUpdate 
+		if(!err && (transformsNeedUpdate
 			|| m_transformsTimestamp < instancesTimestamp))
 		{
 			m_transformsTimestamp = instancesTimestamp;
@@ -678,9 +674,9 @@ Error ParticleEmitter::doInstancingCalcs()
 				Error err2 = ErrorCode::NONE;
 
 				// Skip the first
-				if(&sp != meSpatial)	
+				if(&sp != meSpatial)
 				{
-					ObbSpatialComponent* msp = 
+					ObbSpatialComponent* msp =
 						staticCastPtr<ObbSpatialComponent*>(&sp);
 
 					if(msp)
@@ -715,7 +711,7 @@ void ParticleEmitter::getRenderWorldTransform(U index, Transform& trf)
 
 	if(index == 0)
 	{
-		// Don't transform the particle positions. They are already in world 
+		// Don't transform the particle positions. They are already in world
 		// space
 		trf = Transform::getIdentity();
 	}

+ 123 - 0
src/script/Scene.cpp

@@ -1716,6 +1716,74 @@ static inline void wrapSector(lua_State* l)
 	lua_settop(l, 0);
 }
 
+//==============================================================================
+// ParticleEmitter                                                             =
+//==============================================================================
+
+//==============================================================================
+static const char* classnameParticleEmitter = "ParticleEmitter";
+
+template<>
+I64 LuaBinder::getWrappedTypeSignature<ParticleEmitter>()
+{
+	return -1716560948193631017;
+}
+
+template<>
+const char* LuaBinder::getWrappedTypeName<ParticleEmitter>()
+{
+	return classnameParticleEmitter;
+}
+
+//==============================================================================
+/// Pre-wrap method ParticleEmitter::getSceneNodeBase.
+static inline int pwrapParticleEmittergetSceneNodeBase(lua_State* l)
+{
+	UserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	
+	LuaBinder::checkArgsCount(l, 1);
+	
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, classnameParticleEmitter, -1716560948193631017, ud)) return -1;
+	ParticleEmitter* self = static_cast<ParticleEmitter*>(ud->m_data);
+	ANKI_ASSERT(self != nullptr);
+	
+	// Call the method
+	SceneNode& ret = *self;
+	
+	// Push return value
+	voidp = lua_newuserdata(l, sizeof(UserData));
+	ud = static_cast<UserData*>(voidp);
+	luaL_setmetatable(l, "SceneNode");
+	ud->m_data = static_cast<void*>(&ret);
+	ud->m_gc = false;
+	ud->m_sig = -2220074417980276571;
+	
+	return 1;
+}
+
+//==============================================================================
+/// Wrap method ParticleEmitter::getSceneNodeBase.
+static int wrapParticleEmittergetSceneNodeBase(lua_State* l)
+{
+	int res = pwrapParticleEmittergetSceneNodeBase(l);
+	if(res >= 0) return res;
+	lua_error(l);
+	return 0;
+}
+
+//==============================================================================
+/// Wrap class ParticleEmitter.
+static inline void wrapParticleEmitter(lua_State* l)
+{
+	LuaBinder::createClass(l, classnameParticleEmitter);
+	LuaBinder::pushLuaCFuncMethod(l, "getSceneNodeBase", wrapParticleEmittergetSceneNodeBase);
+	lua_settop(l, 0);
+}
+
 //==============================================================================
 // SceneGraph                                                                  =
 //==============================================================================
@@ -2097,6 +2165,59 @@ static int wrapSceneGraphnewSector(lua_State* l)
 	return 0;
 }
 
+//==============================================================================
+/// Pre-wrap method SceneGraph::newParticleEmitter.
+static inline int pwrapSceneGraphnewParticleEmitter(lua_State* l)
+{
+	UserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	
+	LuaBinder::checkArgsCount(l, 3);
+	
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, classnameSceneGraph, -7754439619132389154, ud)) return -1;
+	SceneGraph* self = static_cast<SceneGraph*>(ud->m_data);
+	ANKI_ASSERT(self != nullptr);
+	
+	// Pop arguments
+	const char* arg0;
+	if(LuaBinder::checkString(l, 2, arg0)) return -1;
+	
+	const char* arg1;
+	if(LuaBinder::checkString(l, 3, arg1)) return -1;
+	
+	// Call the method
+	ParticleEmitter* ret = newSceneNode<ParticleEmitter>(self, arg0, arg1);
+	
+	// Push return value
+	if(ANKI_UNLIKELY(ret == nullptr))
+	{
+		lua_pushstring(l, "Glue code returned nullptr");
+		return -1;
+	}
+	
+	voidp = lua_newuserdata(l, sizeof(UserData));
+	ud = static_cast<UserData*>(voidp);
+	luaL_setmetatable(l, "ParticleEmitter");
+	ud->m_data = static_cast<void*>(ret);
+	ud->m_gc = false;
+	ud->m_sig = -1716560948193631017;
+	
+	return 1;
+}
+
+//==============================================================================
+/// Wrap method SceneGraph::newParticleEmitter.
+static int wrapSceneGraphnewParticleEmitter(lua_State* l)
+{
+	int res = pwrapSceneGraphnewParticleEmitter(l);
+	if(res >= 0) return res;
+	lua_error(l);
+	return 0;
+}
+
 //==============================================================================
 /// Wrap class SceneGraph.
 static inline void wrapSceneGraph(lua_State* l)
@@ -2109,6 +2230,7 @@ static inline void wrapSceneGraph(lua_State* l)
 	LuaBinder::pushLuaCFuncMethod(l, "newStaticCollisionNode", wrapSceneGraphnewStaticCollisionNode);
 	LuaBinder::pushLuaCFuncMethod(l, "newPortal", wrapSceneGraphnewPortal);
 	LuaBinder::pushLuaCFuncMethod(l, "newSector", wrapSceneGraphnewSector);
+	LuaBinder::pushLuaCFuncMethod(l, "newParticleEmitter", wrapSceneGraphnewParticleEmitter);
 	lua_settop(l, 0);
 }
 
@@ -2168,6 +2290,7 @@ void wrapModuleScene(lua_State* l)
 	wrapStaticCollisionNode(l);
 	wrapPortal(l);
 	wrapSector(l);
+	wrapParticleEmitter(l);
 	wrapSceneGraph(l);
 	LuaBinder::pushLuaCFunc(l, "getSceneGraph", wrapgetSceneGraph);
 }

+ 16 - 0
src/script/Scene.xml

@@ -228,6 +228,14 @@ static SceneGraph* getSceneGraph(lua_State* l)
 				</method>
 			</methods>
 		</class>
+		<class name="ParticleEmitter">
+			<methods>
+				<method name="getSceneNodeBase">
+					<overrideCall>SceneNode&amp; ret = *self;</overrideCall>
+					<return>SceneNode&amp;</return>
+				</method>
+			</methods>
+		</class>
 		<class name="SceneGraph">
 			<methods>
 				<method name="newModelNode">
@@ -283,6 +291,14 @@ static SceneGraph* getSceneGraph(lua_State* l)
 					</args>
 					<return>Sector*</return>
 				</method>
+				<method name="newParticleEmitter">
+					<overrideCall><![CDATA[ParticleEmitter* ret = newSceneNode<ParticleEmitter>(self, arg0, arg1);]]></overrideCall>
+					<args>
+						<arg>const CString&amp;</arg>
+						<arg>const CString&amp;</arg>
+					</args>
+					<return>ParticleEmitter*</return>
+				</method>
 			</methods>
 		</class>
 	</classes>

+ 3 - 3
testapp/Main.cpp

@@ -260,7 +260,7 @@ Error init()
 	{
 		ScriptResourcePointer script;
 
-		err = script.load("maps/adis/scene.lua", &resources);
+		err = script.load("maps/techdemo/scene.lua", &resources);
 		if(err) return err;
 
 		err = app->getScriptManager().evalString(script->getSource());
@@ -384,14 +384,14 @@ Error mainLoopExtra(App& app, void*, Bool& quit)
 				Transform(pos, Mat3x4::getIdentity(), 1.0));
 		}*/
 
-		scene.newSceneNode<ModelNode>(CString(), horse,
+		scene.newSceneNode<ModelNode>("aaaaaaa", horse,
 			"models/crate0/crate0.ankimdl");
 
 		horse->getComponent<MoveComponent>().enableBits(
 			MoveComponent::Flag::IGNORE_LOCAL_TRANSFORM);
 
 		BodyNode* bnode;
-		scene.newSceneNode<BodyNode>(CString(), bnode,
+		scene.newSceneNode<BodyNode>("bbbbbbb", bnode,
 			"models/crate0/crate0.ankicl");
 
 		bnode->addChild(horse);

+ 21 - 0
tools/scene/Exporter.cpp

@@ -948,6 +948,7 @@ void Exporter::visitNode(const aiNode* ainode)
 		unsigned mtlIndex =  m_scene->mMeshes[meshIndex]->mMaterialIndex;
 
 		// Check properties
+		bool special = false;
 		for(const auto& prop : m_scene->mMeshes[meshIndex]->mProperties)
 		{
 			if(prop.first == "particles_file")
@@ -956,9 +957,15 @@ void Exporter::visitNode(const aiNode* ainode)
 				p.m_filename = prop.second;
 				p.m_transform = ainode->mTransformation;
 				m_particleEmitters.push_back(p);
+				special = true;
 			}
 		}
 
+		if(special)
+		{
+			continue;
+		}
+
 		// Check if it's a collsion mesh
 		std::string name = m_scene->mMeshes[meshIndex]->mName.C_Str();
 		if(name.find("ak_collision") == 0)
@@ -1127,6 +1134,20 @@ void Exporter::exportAll()
 		++i;
 	}
 
+	//
+	// Export particle emitters
+	//
+	i = 0;
+	for(const ParticleEmitter& p : m_particleEmitters)
+	{
+		std::string name = "particles" + std::to_string(i);
+		file << "\nnode = scene:newParticleEmitter(\"" << name << "\", \""
+			<< p.m_filename << "\")\n";
+
+		writeNodeTransform("node", p.m_transform);
+		++i;
+	}
+
 	//
 	// Export nodes and models.
 	//