Panagiotis Christopoulos Charitos 13 лет назад
Родитель
Сommit
cac8dfb98c

+ 4 - 0
include/anki/resource/Mesh.h

@@ -143,6 +143,10 @@ protected:
 /// A mesh that behaves as a mesh and as a collection of separate meshes
 class BucketMesh: public Mesh
 {
+public:
+	/// The absolute limit of submeshes
+	static const U MAX_SUB_MESHES = 64;
+
 	/// Default constructor. Do nothing
 	BucketMesh()
 	{}

+ 1 - 3
include/anki/resource/MeshLoader.h

@@ -141,10 +141,8 @@ public:
 	}
 
 	/// This will adjust the indices bias
-	void appendIndices(const Vector<U16>& indices)
+	void appendIndices(const Vector<U16>& indices, U16 bias)
 	{
-		U16 bias = vertCoords.size();
-
 		for(U16 index : indices)
 		{
 			vertIndices.push_back(bias + index);

+ 49 - 9
include/anki/resource/Model.h

@@ -20,15 +20,14 @@ class ModelPatchBase
 public:
 	/// VAOs container
 	typedef Vector<Vao> VaosContainer;
-	/// Map to get the VAO given a PassLod key
-	typedef PassLevelHashMap<Vao*> PassLevelToVaoMap;
 
 	virtual ~ModelPatchBase()
 	{}
 
+	virtual const Material& getMaterial() const = 0;
+
 	virtual const MeshBase& getMeshBase(const PassLevelKey& key) const = 0;
 	virtual U32 getMeshesCount() const = 0;
-	virtual const Material& getMaterial() const = 0;
 
 	const Obb& getBoundingShape() const
 	{
@@ -36,10 +35,27 @@ public:
 		return getMeshBase(key).getBoundingShape();
 	}
 
+	const Obb& getBoundingShapeSub(U32 subMeshId) const
+	{
+		PassLevelKey key(0, 0);
+		return getMeshBase(key).getBoundingShapeSub(subMeshId);
+	}
+
+	U32 getSubMeshesCount() const
+	{
+		PassLevelKey key(0, 0);
+		return getMeshBase(key).getSubMeshesCount();
+	}
+
 	/// Given a pass lod key retrieve variables useful for rendering
 	void getRenderingData(const PassLevelKey& key, const Vao*& vao,
 		const ShaderProgram*& prog, U32& indicesCount) const;
 
+	/// Get information for multiDraw rendering
+	void getRenderingDataSub(const PassLevelKey& key, U64 subMeshesMask,
+		const Vao*& vao, const ShaderProgram*& prog,
+		U32* indicesCountArray, U32* indicesOffsetArray, U32& primcount) const;
+
 protected:
 	/// Array [lod][pass]
 	VaosContainer vaos;
@@ -59,14 +75,31 @@ private:
 
 /// Its a chunk of a model. Its very important class and it binds the material
 /// with the mesh
+template<typename MeshResourcePointerType>
 class ModelPatch: public ModelPatchBase
 {
 public:
 	/// Map to get the VAO given a PassLod key
 	typedef PassLevelHashMap<Vao> PassLevelToVaoMap;
 
-	ModelPatch(const char* meshFNames[], U32 meshesCount, const char* mtlFName);
-	~ModelPatch();
+	ModelPatch(const char* meshFNames[], U32 meshesCount,
+		const char* mtlFName)
+	{
+		// Load
+		ANKI_ASSERT(meshesCount > 0);
+		meshes.resize(meshesCount);
+		for(U32 i = 0; i < meshesCount; i++)
+		{
+			meshes[i].load(meshFNames[i]);
+		}
+		mtl.load(mtlFName);
+
+		/// Create VAOs
+		create();
+	}
+
+	~ModelPatch()
+	{}
 
 	/// @name Accessors
 	/// @{
@@ -91,7 +124,7 @@ public:
 	/// @}
 
 private:
-	Vector<MeshResourcePointer> meshes; ///< The geometries
+	Vector<MeshResourcePointerType> meshes; ///< The geometries
 	MaterialResourcePointer mtl; ///< Material
 };
 
@@ -103,9 +136,12 @@ private:
 /// <model>
 /// 	<modelPatches>
 /// 		<modelPatch>
-/// 			<mesh>path/to/mesh.mesh</mesh>
+/// 			[<mesh>path/to/mesh.mesh</mesh>
 ///				[<mesh1>path/to/mesh_lod_1.mesh</mesh1>]
-///				[<mesh2>path/to/mesh_lod_2.mesh</mesh2>]
+///				[<mesh2>path/to/mesh_lod_2.mesh</mesh2>]] |
+/// 			[<bucketMesh>path/to/mesh.bmesh</bucketMesh>
+///				[<bucketMesh1>path/to/mesh_lod_1.bmesh</bucketMesh1>]
+///				[<bucketMesh2>path/to/mesh_lod_2.bmesh</bucketMesh2>]]
 /// 			<material>path/to/material.mtl</material>
 /// 		</modelPatch>
 /// 		...
@@ -121,7 +157,11 @@ private:
 class Model
 {
 public:
-	typedef PtrVector<ModelPatch> ModelPatchesContainer;
+	typedef Vector<ModelPatchBase*> ModelPatchesContainer;
+
+	Model()
+	{}
+	~Model();
 
 	/// @name Accessors
 	/// @{

+ 1 - 0
include/anki/resource/Resource.h

@@ -18,6 +18,7 @@ ANKI_RESOURCE_TYPEDEFS(TextureResource, TextureResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(ShaderProgramResource, ShaderProgramResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(Material, MaterialResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(Mesh, MeshResourcePointer)
+ANKI_RESOURCE_TYPEDEFS(BucketMesh, BucketMeshResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(Skeleton, SkeletonResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(SkelAnim, SkelAnimResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(LightRsrc, LightRsrcResourcePointer)

+ 2 - 2
include/anki/scene/ModelNode.h

@@ -18,7 +18,7 @@ class ModelPatchNode: public SceneNode, public Movable, public Renderable,
 public:
 	/// @name Constructors/Destructor
 	/// @{
-	ModelPatchNode(const ModelPatch* modelPatch_,
+	ModelPatchNode(const ModelPatchBase* modelPatch_,
 		const char* name, Scene* scene, // Scene
 		U32 movableFlags, Movable* movParent); // Movable
 	/// @}
@@ -89,7 +89,7 @@ public:
 
 private:
 	Obb obb; ///< In world space
-	const ModelPatch* modelPatch; ///< The resource
+	const ModelPatchBase* modelPatch; ///< The resource
 };
 
 /// The model scene node

+ 4 - 18
include/anki/scene/Renderable.h

@@ -9,6 +9,7 @@
 namespace anki {
 
 class ModelPatchBase;
+class SceneNode;
 
 /// @addtogroup Scene
 /// @{
@@ -185,31 +186,16 @@ public:
 	{
 		return ubo;
 	}
-
-	U32 getSubMeshesCount() const
-	{
-		return subMeshVisible.size();
-	}
 	/// @}
 
-	/// Set all sub meshes to not visible
-	void setAllSubMeshesNotVisible()
+	U32 getSetsCount() const
 	{
-		memset(&subMeshVisible[0], 0, 
-			sizeof(subMeshVisible.size()) * sizeof(Bool8));
+		return 1;
 	}
 
-	/// Set the visibility of a single sub mesh
-	void setSubMeshVisible(U submeshId, Bool visible)
-	{
-		ANKI_ASSERT(submeshId < subMeshVisible.size());
-		subMeshVisible[submeshId] = visible;
-	}
+	void setVisibleSetsMask(const SceneNode* frustumable, U64 mask);
 
 protected:
-	/// Holds the visible submeshes in case of bucket meshes
-	SceneVector<Bool8> subMeshVisible;
-
 	/// The derived class needs to call that
 	void init(PropertyMap& pmap);
 

+ 3 - 3
include/anki/scene/SkinNode.h

@@ -83,7 +83,7 @@ public:
 
 	/// @name Constructors/Destructor
 	/// @{
-	SkinModelPatch(const ModelPatch* mpatch_, 
+	SkinModelPatch(const ModelPatchBase* mpatch_,
 		const SceneAllocator<U8>& alloc);
 	~SkinModelPatch();
 	/// @}
@@ -124,7 +124,7 @@ public:
 	/// @}
 
 private:
-	const ModelPatch* mpatch;
+	const ModelPatchBase* mpatch;
 	SceneVector<SkinMesh*> skinMeshes;
 	SceneVector<Vao> xfbVaos; ///< Used as a source VAO in XFB
 };
@@ -136,7 +136,7 @@ class SkinPatchNode: public SceneNode, public Movable, public Renderable,
 public:
 	/// @name Constructors/Destructor
 	/// @{
-	SkinPatchNode(const ModelPatch* modelPatch_,
+	SkinPatchNode(const ModelPatchBase* modelPatch_,
 		const char* name, Scene* scene, // Scene
 		uint movableFlags, Movable* movParent, // Movable
 		CollisionShape* spatialCs); // Spatial

+ 1 - 0
include/anki/scene/Spatial.h

@@ -1,6 +1,7 @@
 #ifndef ANKI_SCENE_SPATIAL_H
 #define ANKI_SCENE_SPATIAL_H
 
+#include "anki/scene/Common.h"
 #include "anki/collision/Collision.h"
 #include "anki/util/Flags.h"
 #include "anki/core/Timestamp.h"

+ 7 - 3
include/anki/scene/StaticGeometryNode.h

@@ -2,18 +2,19 @@
 #define ANKI_SCENE_STATIC_GEOMETRY_NODE_H
 
 #include "anki/scene/Common.h"
+#include "anki/scene/SceneNode.h"
 #include "anki/scene/Spatial.h"
 #include "anki/scene/Renderable.h"
 
 namespace anki {
 
-/// XXX
+/// Part of the static geometry
 class StaticGeometryPatchNode: public SceneNode, public Spatial
 {
 public:
 	/// @name Constructors/Destructor
 	/// @{
-	StaticGeometryPatchNode(
+	StaticGeometryPatchNode(const Obb& obb,
 		const char* name, Scene* scene); // Scene
 	/// @}
 
@@ -26,6 +27,9 @@ public:
 		return this;
 	}
 	/// @}
+
+public:
+	Obb obb;
 };
 
 /// XXX
@@ -34,7 +38,7 @@ class StaticGeometryNode: public SceneNode, public Spatial, public Renderable
 public:
 
 private:
-	SceneVector<StaticGeometryPatch*> patches;
+	SceneVector<StaticGeometryPatchNode*> patches;
 };
 
 } // end namespace anki

+ 1 - 2
include/anki/scene/Visibility.h

@@ -2,6 +2,7 @@
 #define ANKI_SCENE_VISIBILITY_TEST_RESULTS_H
 
 #include "anki/scene/Common.h"
+#include "anki/collision/Forward.h"
 
 namespace anki {
 
@@ -40,8 +41,6 @@ struct VisibilityTestResults
 	{}
 };
 
-/// XXX
-
 /// @}
 
 } // end namespace anki

+ 0 - 4
src/gl/BufferObject.cpp

@@ -39,10 +39,6 @@ void BufferObject::create(GLenum target_, U32 sizeInBytes_,
 {
 	ANKI_ASSERT(!isCreated());
 
-	ANKI_ASSERT(usage_ == GL_STREAM_DRAW
-		|| usage_ == GL_STATIC_DRAW
-		|| usage_ == GL_DYNAMIC_DRAW);
-
 	ANKI_ASSERT(sizeInBytes_ > 0 && "Unacceptable sizeInBytes");
 
 	usage = usage_;

+ 15 - 3
src/resource/Mesh.cpp

@@ -54,6 +54,10 @@ U32 Mesh::calcVertexSize() const
 //==============================================================================
 void Mesh::createVbos(const MeshLoader& loader)
 {
+	ANKI_ASSERT(vertsCount == loader.getPositions().size()
+		&& vertsCount == loader.getNormals().size()
+		&& vertsCount == loader.getTangents().size());
+
 	// Calculate VBO size
 	U32 vertexsize = calcVertexSize();
 	U32 vbosize = vertexsize * vertsCount;
@@ -205,7 +209,7 @@ void BucketMesh::load(const char* filename)
 		XmlDocument doc;
 		doc.loadFile(filename);
 
-		XmlElement rootEl = doc.getChildElement("multiMesh");
+		XmlElement rootEl = doc.getChildElement("bucketMesh");
 		XmlElement meshesEl = rootEl.getChildElement("meshes");
 		XmlElement meshEl = meshesEl.getChildElement("mesh");
 
@@ -225,6 +229,12 @@ void BucketMesh::load(const char* filename)
 			MeshLoader subLoader;
 			if(i != 0)
 			{
+				// Sanity check
+				if(i > MAX_SUB_MESHES)
+				{
+					throw ANKI_EXCEPTION("Max number of submeshes exceeded");
+				}
+
 				// Load
 				subLoader.load(subMeshFilename.c_str());
 				loader = &subLoader;
@@ -257,6 +267,8 @@ void BucketMesh::load(const char* filename)
 				{
 					fullLoader.appendWeights(subLoader.getWeights());
 				}
+
+				fullLoader.appendIndices(loader->getIndices(), vertsCount);
 			}
 			else
 			{
@@ -283,9 +295,9 @@ void BucketMesh::load(const char* filename)
 			indicesCount += loader->getIndices().size();
 
 			// Move to next
-			meshesEl = meshesEl.getNextSiblingElement("mesh");
+			meshEl = meshEl.getNextSiblingElement("mesh");
 			++i;
-		} while(meshesEl);
+		} while(meshEl);
 
 		// Create the bucket mesh
 		createVbos(fullLoader);

+ 102 - 37
src/resource/Model.cpp

@@ -106,6 +106,51 @@ void ModelPatchBase::getRenderingData(const PassLevelKey& key, const Vao*& vao,
 	prog = &getMaterial().findShaderProgram(mtlKey);
 }
 
+//==============================================================================
+void ModelPatchBase::getRenderingDataSub(const PassLevelKey& key,
+	U64 subMeshesMask, const Vao*& vao, const ShaderProgram*& prog,
+	U32* indicesCountArray, U32* indicesOffsetArray, U32& primcount) const
+{
+	const U meshLods = getMeshesCount();
+	ANKI_ASSERT(meshLods > 0);
+	const U mtlLods = getMaterial().getLevelsOfDetail();
+	ANKI_ASSERT(mtlLods > 0);
+
+	// VAO
+	U lodsCount = std::max(meshLods, mtlLods);
+
+	U index = key.pass + std::min((U)key.level, lodsCount - 1) * lodsCount;
+
+	ANKI_ASSERT(index < vaos.size());
+	vao = &vaos[index];
+
+	// Prog
+	PassLevelKey mtlKey;
+	mtlKey.pass = key.pass;
+	mtlKey.level = std::min(key.level, (U8)(mtlLods - 1));
+
+	prog = &getMaterial().findShaderProgram(mtlKey);
+
+	// Mesh and indices
+	PassLevelKey meshKey;
+	meshKey.pass = key.pass;
+	meshKey.level = std::min(key.level, (U8)(meshLods - 1));
+
+	const MeshBase& meshBase = getMeshBase(meshKey);
+
+	U subMeshesCount = meshBase.getSubMeshesCount();
+	primcount = 0;
+	for(U i = 0; i < subMeshesCount; i++)
+	{
+		if(subMeshesMask & (1 << i))
+		{
+			indicesCountArray[primcount] =
+				meshBase.getIndicesCountSub(i, indicesOffsetArray[primcount]);
+			++primcount;
+		}
+	}
+}
+
 //==============================================================================
 void ModelPatchBase::create()
 {
@@ -147,34 +192,18 @@ void ModelPatchBase::create()
 }
 
 //==============================================================================
-// ModelPatch                                                                  =
+// Model                                                                       =
 //==============================================================================
 
 //==============================================================================
-ModelPatch::ModelPatch(const char *meshFNames[], U32 meshesCount,
-	const char* mtlFName)
+Model::~Model()
 {
-	// Load
-	ANKI_ASSERT(meshesCount > 0);
-	meshes.resize(meshesCount);
-	for(U32 i = 0; i < meshesCount; i++)
+	for(ModelPatchBase* patch : modelPatches)
 	{
-		meshes[i].load(meshFNames[i]);
+		delete patch;
 	}
-	mtl.load(mtlFName);
-
-	/// Create VAOs
-	create();
 }
 
-//==============================================================================
-ModelPatch::~ModelPatch()
-{}
-
-//==============================================================================
-// Model                                                                       =
-//==============================================================================
-
 //==============================================================================
 void Model::load(const char* filename)
 {
@@ -194,33 +223,69 @@ void Model::load(const char* filename)
 			modelPatchesEl.getChildElement("modelPatch");
 		do
 		{
-			XmlElement meshEl = modelPatchEl.getChildElement("mesh");
-			XmlElement meshEl1 = modelPatchEl.getChildElementOptional("mesh1");
-			XmlElement meshEl2 = modelPatchEl.getChildElementOptional("mesh2");
+			XmlElement materialEl =
+			modelPatchEl.getChildElement("material");
+
 			Array<const char*, 3> meshesFnames;
 			U meshesCount = 1;
+			ModelPatchBase* patch;
 
-			meshesFnames[0] = meshEl.getText();
-
-			if(meshEl1)
+			// Try mesh
+			XmlElement meshEl = modelPatchEl.getChildElementOptional("mesh");
+			if(meshEl)
 			{
-				++meshesCount;
-				meshesFnames[1] = meshEl1.getText();
+				XmlElement meshEl1 =
+					modelPatchEl.getChildElementOptional("mesh1");
+				XmlElement meshEl2 =
+					modelPatchEl.getChildElementOptional("mesh2");
+
+				meshesFnames[0] = meshEl.getText();
+
+				if(meshEl1)
+				{
+					++meshesCount;
+					meshesFnames[1] = meshEl1.getText();
+				}
+
+				if(meshEl2)
+				{
+					++meshesCount;
+					meshesFnames[2] = meshEl2.getText();
+				}
+
+				patch = new ModelPatch<MeshResourcePointer>(
+					&meshesFnames[0], meshesCount, materialEl.getText());
 			}
-
-			if(meshEl2)
+			else
 			{
-				++meshesCount;
-				meshesFnames[2] = meshEl2.getText();
+				XmlElement bmeshEl =
+					modelPatchEl.getChildElement("bucketMesh");
+				XmlElement bmeshEl1 =
+					modelPatchEl.getChildElementOptional("bucketMesh1");
+				XmlElement bmeshEl2 =
+					modelPatchEl.getChildElementOptional("bucketMesh2");
+
+				meshesFnames[0] = bmeshEl.getText();
+
+				if(bmeshEl1)
+				{
+					++meshesCount;
+					meshesFnames[1] = bmeshEl1.getText();
+				}
+
+				if(bmeshEl2)
+				{
+					++meshesCount;
+					meshesFnames[2] = bmeshEl2.getText();
+				}
+
+				patch = new ModelPatch<BucketMeshResourcePointer>(
+					&meshesFnames[0], meshesCount, materialEl.getText());
 			}
 
-			XmlElement materialEl =
-				modelPatchEl.getChildElement("material");
-
-			ModelPatch* patch = new ModelPatch(
-				&meshesFnames[0], meshesCount, materialEl.getText());
 			modelPatches.push_back(patch);
 
+			// Move to next
 			modelPatchEl = modelPatchEl.getNextSiblingElement("modelPatch");
 		} while(modelPatchEl);
 

+ 1 - 1
src/resource/Skin.cpp

@@ -69,7 +69,7 @@ void Skin::load(const char* filename)
 		}
 
 		// All meshes should have vert weights
-		for(const ModelPatch* patch : model->getModelPatches())
+		for(const ModelPatchBase* patch : model->getModelPatches())
 		{
 			for(U i = 0; i < patch->getMeshesCount(); i++)
 			{

+ 2 - 2
src/scene/ModelNode.cpp

@@ -9,7 +9,7 @@ namespace anki {
 //==============================================================================
 
 //==============================================================================
-ModelPatchNode::ModelPatchNode(const ModelPatch* modelPatch_,
+ModelPatchNode::ModelPatchNode(const ModelPatchBase *modelPatch_,
 	const char* name, Scene* scene,
 	U32 movableFlags, Movable* movParent)
 	:	SceneNode(name, scene),
@@ -37,7 +37,7 @@ ModelNode::ModelNode(const char* modelFname,
 	patches.reserve(model->getModelPatches().size());
 
 	U i = 0;
-	for(const ModelPatch* patch : model->getModelPatches())
+	for(const ModelPatchBase* patch : model->getModelPatches())
 	{
 		std::string name_ = name + std::to_string(i);
 

+ 1 - 1
src/scene/Renderable.cpp

@@ -78,7 +78,7 @@ RenderableVariable::~RenderableVariable()
 
 //==============================================================================
 Renderable::Renderable(const SceneAllocator<U8>& alloc)
-	: vars(alloc), subMeshVisible(alloc)
+	: vars(alloc)
 {}
 
 //==============================================================================

+ 3 - 3
src/scene/SkinNode.cpp

@@ -57,7 +57,7 @@ SkinModelPatch::~SkinModelPatch()
 }
 
 //==============================================================================
-SkinModelPatch::SkinModelPatch(const ModelPatch* mpatch_, 
+SkinModelPatch::SkinModelPatch(const ModelPatchBase* mpatch_,
 	const SceneAllocator<U8>& alloc)
 	:	mpatch(mpatch_),
 		skinMeshes(alloc),
@@ -124,7 +124,7 @@ SkinModelPatch::SkinModelPatch(const ModelPatch* mpatch_,
 //==============================================================================
 
 //==============================================================================
-SkinPatchNode::SkinPatchNode(const ModelPatch* modelPatch_,
+SkinPatchNode::SkinPatchNode(const ModelPatchBase* modelPatch_,
 	const char* name, Scene* scene,
 	uint movableFlags, Movable* movParent,
 	CollisionShape* spatialCs)
@@ -156,7 +156,7 @@ SkinNode::SkinNode(const char* skinFname,
 	skin.load(skinFname);
 
 	uint i = 0;
-	for(const ModelPatch* patch : skin->getModel().getModelPatches())
+	for(const ModelPatchBase* patch : skin->getModel().getModelPatches())
 	{
 		std::string name = skin.getResourceName()
 			+ std::to_string(i);

+ 16 - 0
src/scene/StaticGeometryNode.cpp

@@ -0,0 +1,16 @@
+#include "anki/scene/StaticGeometryNode.h"
+#include "anki/scene/Scene.h"
+
+namespace anki {
+
+//==============================================================================
+// StaticGeometryPatchNode                                                     =
+//==============================================================================
+
+//==============================================================================
+StaticGeometryPatchNode::StaticGeometryPatchNode(const Obb& obb_,
+	const char* name, Scene* scene)
+	: SceneNode(name, scene), Spatial(&obb), obb(obb_)
+{}
+
+} // end namespace anki

+ 2 - 2
testapp/Main.cpp

@@ -243,7 +243,7 @@ void init()
 
 #if 1
 	ModelNode* sponzaModel = new ModelNode(
-		"data/maps/sponza/sponza.mdl",
+		"data/maps/sponza/sponza_new.mdl",
 		"sponza", &scene, Movable::MF_NONE, nullptr);
 
 	(void)sponzaModel;
@@ -453,7 +453,7 @@ void mainLoop()
 
 		// Sleep
 		//
-#if 0
+#if 1
 		timer.stop();
 		if(timer.getElapsedTime() < AppSingleton::get().getTimerTick())
 		{