// // Created by Victor Holt on 3/18/2017. // Reference: (rbnpontes) http://discourse.urho3d.io/t/a-mesh-generator/2361 // #pragma once #include gs_nsstart #define CM_MAX_FACES_PER_GEOM_SM 500 #define CM_MAX_FACES_PER_GEOM_LG 25000 enum class MeshUVType { UV_XY = 0, UV_XZ, UV_YZ, UV_ZY }; struct GAMESENCHA_API MeshVertex { Vector3 vertex_; Vector3 normal_; Vector2 uv_; Vector2 uv2_; Vector4 tangent_; Color color_; MeshUVType uvType_; }; struct GAMESENCHA_API MeshFace { unsigned vertIndexStart_; MeshVertex* v0_; MeshVertex* v1_; MeshVertex* v2_; }; struct GAMESENCHA_API MeshGeomData { /// Geometry index in the mesh. uint32_t geomIndex_; /// Check if this geometry data is dirty. bool isDirty_ = false; /// Faces for the mesh. PODVector faces_; /// Vertex data of the mesh. PODVector meshVertexList_; /// Vertex data of the mesh. PODVector vertexData_; /// Index data of the mesh. PODVector indexData_; /// Large index data. PODVector largeIndexData_; /// Geometry of the mesh. SharedPtr geometry_; /// Vertex buffer of the mesh. SharedPtr vertexBuffer_; /// Index buffer of the mesh. SharedPtr indexBuffer_; MeshGeomData(uint32_t geomIndex) { geomIndex_ = geomIndex; geometry_ = nullptr; vertexBuffer_ = nullptr; indexBuffer_ = nullptr; } ~MeshGeomData() { // Delete the faces. for (auto face : faces_) { delete face; } faces_.Clear(); for (auto vert : meshVertexList_) { delete vert; } meshVertexList_.Clear(); vertexData_.Clear(); indexData_.Clear(); } }; class GAMESENCHA_API CustomMesh : public Object { URHO3D_OBJECT(CustomMesh, Object); public: //! Constructor. //! \param context //! \param isDynamic CustomMesh(Context* context, bool isDynamic); //! Destructor. virtual ~CustomMesh(); //! Adds a face to the mesh. //! \param v0 //! \param v1 //! \param v2 //! \param uvType MeshFace* AddFace(const Vector3& v0, const Vector3& v1, const Vector3& v2, const MeshUVType& uvType = MeshUVType::UV_XZ); //! Adds an index. //! \param index void AddIndex(uint16_t index); //! Adds an index. //! \param index void AddLargeIndex(uint32_t index); //! Commits changes to the mesh. //! \param updateNormals //! \param updateTangents void Commit(bool updateNormals = false, bool updateTangents = false, bool updateMesh = true); //! Calculates the mesh normals. //! \param check void CalculateNormals(bool check = true); //! Calculates the mesh tangents. //! \param check void CalculateTangents(bool check = true); //! Updates the texture coordinates. void UpdateTexCoords(); //! Updates the bounding box for the mesh. void UpdateBoundingBox(); //! Clears all vertex data of the mesh. void Clear(); //! Saves the mesh to a file. //! \param path void Save(const String& path); //! Save the lightmap for this mesh. //! \param path void SaveLightmapTexture(const String& path); //! Returns the mesh geometry. //! \return Geometry* GetGeometry(uint32_t index); //! Returns the mesh model. //! \return Model* GetModel(); //! Returns a face at the given index. //! \param geomIndex //! \param faceIndex //! \return MeshFace* GetFace(uint32_t geomIndex, uint32_t faceIndex); //! Pushes a new geometry object onto the mesh. void PushGeometry(); //! Sets the scale of the mesh. //! \param scale inline void SetScale(float scale) { scale_ = scale; } //! Returns the scale of the mesh. //! \return inline float GetScale() const { return scale_; } //! Flag to use large indices. //! \param useLargeIndices inline void SetUseLargeIndices(bool useLargeIndices) { maxFaceCount_ = useLargeIndices ? CM_MAX_FACES_PER_GEOM_LG : CM_MAX_FACES_PER_GEOM_SM; useLargeIndices_ = useLargeIndices; } //! Sets the max face count. //! \param maxFaceCount inline void SetMaxFaceCount(uint32_t maxFaceCount) { maxFaceCount_ = maxFaceCount; } //! Rotates a mesh face. //! \param face //! \param rot void RotateFace(MeshFace* face, const Quaternion& rot); //! Rotates a mesh face. //! \param geomIndex //! \param faceIndex //! \param rot void RotateFaceByIndex(uint32_t geomIndex, unsigned faceIndex, const Quaternion& rot); //! Rotates the mesh by the given rotation. //! \param rot void Rotate(const Quaternion& rot); //! Returns the bounding box. //! \return inline const BoundingBox& GetBoundingBox() const { return boundingBox_; } //! Returns the number of faces. //! \return inline unsigned GetNumFaces() const { return faceCount_; } //! Returns the number of vertices. //! \return inline unsigned GetNumVerts() const { return vertexCount_; } //! Returns the number of indices. //! \return inline unsigned GetNumIndices() const { return indexCount_; } //! Adds a variable. //! \param name //! \param value inline void AddVar(const String& name, const Variant& value) { vars_.Populate(name, value); } //! Returns a variable. //! \param name //! \param dest inline void GetVar(const String& name, Variant& dest) { auto var = vars_.Find(name); if (var != vars_.End()) { dest = var->second_; } } //! Use the uv2 coords. //! \param useUV2 inline void SetUseUV2(bool useUV2) { useUV2_ = useUV2; } protected: //! Adds a vertex. //! \param v //! \param uvType MeshVertex* AddVertex(const Vector3& v, const MeshUVType& uvType = MeshUVType::UV_XZ); //! Builds the mesh. //! \param geomData //! \param updateNormals //! \param updateTangents //! \param updateMesh void CreateMesh(MeshGeomData* geomData, bool updateNormals, bool updateTangents, bool updateMesh = true); //! Generates the vertex data. void GenerateVertexData(MeshGeomData* geomData); //! Updates the vertex data. void UpdateVertexData(MeshGeomData* geomData); //! Creates a new face. //! \param v0 //! \param v1 //! \param v2 //! \return MeshFace* CreateFace(MeshVertex* v0, MeshVertex* v1, MeshVertex* v2); //! Updates the mesh. //! \param geomData //! \param updateNormals //! \param updateTangents //! \param updateMesh void UpdateMesh(MeshGeomData* geomData, bool updateNormals, bool updateTangents, bool updateMesh = true); //! Calculates the mesh normals. //! \param check void CalculateNormals(MeshGeomData* geomData, bool check); //! Calculates the mesh tangents. //! \param check void CalculateTangents(MeshGeomData* geomData, bool check); protected: /// Number of faces created. uint32_t faceCount_ = 0; /// Relative face count when create geometry data. uint32_t relFaceCount_ = 0; /// Number of vertices created. uint32_t vertexCount_ = 0; /// Number of indices created. uint32_t indexCount_ = 0; /// Current geometry index. uint32_t currentGeomIndex_ = 0; /// Max face count for the mesh. uint32_t maxFaceCount_; /// The scale of the mesh. float scale_; /// Flag for if this is a dynamic mesh. bool isDynamic_; /// Flag to calculate the normals. bool calcNormals_; /// Flag to calculate the tangents. bool calcTangents_; /// Flag to use large indices. bool useLargeIndices_; /// Flag to manually add indices. bool manualAddIndex_; /// Flag to use uv2 coords. bool useUV2_ = false; /// Model of the mesh. SharedPtr model_; /// Geometry data. PODVector geomData_; /// Reference to the bounding box. BoundingBox boundingBox_; /// Mutex for the mesh. Mutex meshLock_; /// Mutex for calculations. Mutex calcMeshLock_; /// Variables associated with the mesh. HashMap vars_; /// Transform for the mesh. Matrix3x4 transform_; }; gs_nsend