// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Core/Types/Guid.h" #include "Engine/Graphics/Enums.h" #include "Types.h" #include "Config.h" #include "SkeletonData.h" #include "BlendShape.h" #include "Engine/Animations/AnimationData.h" class WriteStream; /// /// Data container for the common model meshes data. Supports holding all types of data related to the models pipeline. /// class FLAXENGINE_API MeshData { public: /// /// The slot index in the model materials to use during rendering. /// int32 MaterialSlotIndex = 0; /// /// The model skeleton node index. Used during importing and by the animated models. /// int32 NodeIndex = 0; /// /// The name of the mesh. /// String Name; /// /// Mesh positions buffer /// Array Positions; /// /// Texture coordinates /// Array UVs; /// /// Normals vector /// Array Normals; /// /// Tangents vectors /// Array Tangents; /// /// Bitangents vectors signs (used for bitangent reconstruction). Can be +1 or -1. /// bitangent = cross(normal, tangent) * sign /// sign = dot(cross(bitangent, normal), tangent) /// Array BitangentSigns; /// /// Mesh index buffer /// Array Indices; /// /// Lightmap UVs /// Array LightmapUVs; /// /// Vertex colors /// Array Colors; /// /// Skinned mesh blend indices (max 4 per bone) /// Array BlendIndices; /// /// Skinned mesh index buffer (max 4 per bone) /// Array BlendWeights; /// /// Blend shapes used by this mesh /// Array BlendShapes; /// /// Global translation for this mesh to be at it's local origin. /// Vector3 OriginTranslation = Vector3::Zero; /// /// Orientation for this mesh at it's local origin. /// Quaternion OriginOrientation = Quaternion::Identity; /// /// Meshes scaling. /// Vector3 Scaling = Vector3::One; public: /// /// Determines whether this instance has any mesh data. /// FORCE_INLINE bool HasData() const { return Indices.HasItems(); } public: /// /// Clear arrays /// void Clear(); /// /// Ensure that buffers will have given space for data /// /// Amount of vertices. /// Amount of indices. /// Failed if clear data otherwise will try to preserve the buffers contents. /// True if use vertex colors buffer. /// True if use vertex blend indices and weights buffer. void EnsureCapacity(int32 vertices, int32 indices, bool preserveContents = false, bool withColors = true, bool withSkin = true); /// /// Swaps the vertex and index buffers contents (without a data copy) with the other mesh. /// /// The other mesh to swap data with. void SwapBuffers(MeshData& other); /// /// Clean data /// void Release(); public: /// /// Init from model vertices array /// /// Array of vertices /// Amount of vertices void InitFromModelVertices(ModelVertex19* vertices, uint32 verticesCount); /// /// Init from model vertices array /// /// Array of vertices /// Amount of vertices void InitFromModelVertices(ModelVertex18* vertices, uint32 verticesCount); /// /// Init from model vertices array /// /// Array of vertices /// Amount of vertices void InitFromModelVertices(ModelVertex15* vertices, uint32 verticesCount); /// /// Init from model vertices array /// /// Array of data for vertex buffer 0 /// Array of data for vertex buffer 1 /// Amount of vertices void InitFromModelVertices(VB0ElementType18* vb0, VB1ElementType18* vb1, uint32 verticesCount); /// /// Init from model vertices array /// /// Array of data for vertex buffer 0 /// Array of data for vertex buffer 1 /// Array of data for vertex buffer 2 /// Amount of vertices void InitFromModelVertices(VB0ElementType18* vb0, VB1ElementType18* vb1, VB2ElementType18* vb2, uint32 verticesCount); /// /// Init from model vertices array /// /// Array of data for vertex buffer 0 /// Array of data for vertex buffer 1 /// Amount of vertices void InitFromModelVertices(VB0ElementType15* vb0, VB1ElementType15* vb1, uint32 verticesCount); /// /// Sets the index buffer data. /// /// The data. /// The indices count. void SetIndexBuffer(void* data, uint32 indicesCount); public: /// /// Pack mesh data to the stream /// /// Output stream /// True if cannot save data, otherwise false bool Pack2Model(WriteStream* stream) const; /// /// Pack skinned mesh data to the stream /// /// Output stream /// True if cannot save data, otherwise false bool Pack2SkinnedModel(WriteStream* stream) const; /// /// Calculate bounding box for the mesh /// /// Output box void CalculateBox(BoundingBox& result) const; /// /// Calculate bounding sphere for the mesh /// /// Output sphere void CalculateSphere(BoundingSphere& result) const; public: #if COMPILE_WITH_MODEL_TOOL /// /// Generate lightmap uvs for the mesh entry /// /// True if generating lightmap uvs failed, otherwise false bool GenerateLightmapUVs(); /// /// Iterates over the vertex buffers to remove the duplicated vertices and generate the optimized index buffer. /// void BuildIndexBuffer(); /// /// Generate lightmap uvs for the mesh entry /// /// The target position to check. /// The position comparision epsilon. /// The output vertices indices array. void FindPositions(const Float3& position, float epsilon, Array& result); /// /// Generates the normal vectors for the mesh geometry. /// /// Specifies the maximum angle (in degrees) that may be between two face normals at the same vertex position that their are smoothed together. /// True if generating failed, otherwise false bool GenerateNormals(float smoothingAngle = 175.0f); /// /// Generates the tangent vectors for the mesh geometry. Requires normal vector and texture coords channel to be valid. /// /// Specifies the maximum angle (in degrees) that may be between two vertex tangents that their tangents and bi-tangents are smoothed. /// True if generating failed, otherwise false. bool GenerateTangents(float smoothingAngle = 45.0f); /// /// Reorders all triangles for improved vertex cache locality. It tries to arrange all triangles to fans and to render triangles which share vertices directly one after the other. /// void ImproveCacheLocality(); /// /// Sums the area of all triangles in the mesh. /// /// The area sum of all mesh triangles. float CalculateTrianglesArea() const; #endif /// /// Transform a vertex buffer positions, normals, tangents and bitangents using the given matrix. /// /// The matrix to use for the transformation. void TransformBuffer(const Matrix& matrix); /// /// Normalizes the blend weights. Requires to have vertices with positions and blend weights setup. /// void NormalizeBlendWeights(); /// /// Merges this mesh data with the specified other mesh. /// /// The other mesh to merge with. void Merge(MeshData& other); }; /// /// Model texture resource descriptor. /// struct FLAXENGINE_API TextureEntry { enum class TypeHint { ColorRGB, ColorRGBA, Normals, }; /// /// The absolute path to the file. /// String FilePath; /// /// The texture contents hint based on the usage/context. /// TypeHint Type; /// /// The texture asset identifier. /// Guid AssetID; }; /// /// Model material slot entry that describes model mesh appearance. /// struct FLAXENGINE_API MaterialSlotEntry { /// /// The slot name. /// String Name; /// /// Gets or sets shadows casting mode by this visual element /// ShadowsCastingMode ShadowsMode = ShadowsCastingMode::All; /// /// The material asset identifier (material or material instance). /// Guid AssetID; struct { Color Color = Color::White; int32 TextureIndex = -1; bool HasAlphaMask = false; } Diffuse; struct { Color Color = Color::Transparent; int32 TextureIndex = -1; } Emissive; struct { float Value = 1.0f; int32 TextureIndex = -1; } Opacity; struct { int32 TextureIndex = -1; } Normals; bool TwoSided = false; bool UsesProperties() const; }; /// /// Data container for LOD metadata and sub meshes. /// class FLAXENGINE_API ModelLodData { public: /// /// The screen size to switch LODs. Bottom limit of the model screen size to render this LOD. /// float ScreenSize = 1.0f; /// /// The meshes array. /// Array Meshes; public: /// /// Initializes a new instance of the class. /// ModelLodData() { } /// /// Finalizes an instance of the class. /// ~ModelLodData() { Meshes.ClearDelete(); } /// /// Gets the bounding box combined for all meshes in this model LOD. /// BoundingBox GetBox() const; }; /// /// Data container for model metadata and LODs. /// class FLAXENGINE_API ModelData { public: /// /// The minimum screen size to draw model (the bottom limit). /// float MinScreenSize = 0.0f; /// /// The texture slots. /// Array Textures; /// /// The material slots. /// Array Materials; /// /// Array with all LODs. The first element is the top most LOD0 followed by the LOD1, LOD2, etc. /// Array LODs; /// /// The skeleton bones hierarchy. /// SkeletonData Skeleton; /// /// The node animations. /// AnimationData Animation; public: /// /// Initializes a new instance of the class. /// ModelData() { } public: /// /// Gets the valid level of details count. /// /// The LOD count. FORCE_INLINE int32 GetLODsCount() const { return LODs.Count(); } /// /// Determines whether this instance has valid skeleton structure. /// /// True if has skeleton, otherwise false. FORCE_INLINE bool HasSkeleton() const { return Skeleton.Bones.HasItems(); } public: /// /// Automatically calculates the screen size for every model LOD for a proper transitions. /// void CalculateLODsScreenSizes(); /// /// Transform a vertex buffer positions, normals, tangents and bitangents using the given matrix. Applies to all the LODs and meshes. /// /// The matrix to use for the transformation. void TransformBuffer(const Matrix& matrix); public: /// /// Pack mesh data to the header stream /// /// Output stream /// True if cannot save data, otherwise false bool Pack2ModelHeader(WriteStream* stream) const; /// /// Pack skinned mesh data to the header stream /// /// Output stream /// True if cannot save data, otherwise false bool Pack2SkinnedModelHeader(WriteStream* stream) const; /// /// Pack animation data to the header stream /// /// Output stream /// True if cannot save data, otherwise false bool Pack2AnimationHeader(WriteStream* stream) const; };