/* * Copyright (c) <2021> Side Effects Software Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. The name of Side Effects Software may not be used to endorse or * promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "CoreMinimal.h" #include "Engine/StaticMesh.h" #include "HoudiniStaticMesh.generated.h" /** * This is a simple static mesh that is meant to be built in one go, without modifications afterwards. * The number of vertices and triangles must be known before hand. */ UCLASS() class HOUDINIENGINERUNTIME_API UHoudiniStaticMesh : public UObject { GENERATED_BODY() public: UHoudiniStaticMesh(const FObjectInitializer &ObjectInitializer); // Clears all existing data and initializes internal arrays to the relevant sizes to accommodate the // mesh based InNumVertices, InNumTriangles, UVs etc. UFUNCTION() void Initialize(uint32 InNumVertices, uint32 InNumTriangles, uint32 InNumUVLayers, uint32 InInitialNumStaticMaterials, bool bInHasNormals, bool bInHasTangents, bool bInHasColors, bool bInHasPerFaceMaterials); UFUNCTION() bool HasPerFaceMaterials() const { return bHasPerFaceMaterials; } UFUNCTION() void SetHasPerFaceMaterials(bool bInHasPerFaceMaterials); UFUNCTION() bool HasNormals() const { return bHasNormals; } UFUNCTION() void SetHasNormals(bool bInHasNormals); UFUNCTION() bool HasTangents() const { return bHasTangents; } UFUNCTION() void SetHasTangents(bool bInHasTangents); UFUNCTION() bool HasColors() const { return bHasColors; } UFUNCTION() void SetHasColors(bool bInHasColors); UFUNCTION() uint32 GetNumUVLayers() const { return NumUVLayers; } UFUNCTION() void SetNumUVLayers(uint32 InNumUVLayers); UFUNCTION() uint32 GetNumStaticMaterials() const { return StaticMaterials.Num(); } UFUNCTION() void SetNumStaticMaterials(uint32 InNumStaticMaterials); UFUNCTION() uint32 GetNumVertices() const { return VertexPositions.Num(); } UFUNCTION() uint32 GetNumTriangles() const { return TriangleIndices.Num(); } UFUNCTION() uint32 GetNumVertexInstances() const { return TriangleIndices.Num() * 3; } UFUNCTION() void SetVertexPosition(uint32 InVertexIndex, const FVector& InPosition); UFUNCTION() void SetTriangleVertexIndices(uint32 InTriangleIndex, const FIntVector& InTriangleVertexIndices); UFUNCTION() void SetTriangleVertexNormal(uint32 InTriangleIndex, uint8 InTriangleVertexIndex, const FVector& InNormal); UFUNCTION() void SetTriangleVertexUTangent(uint32 InTriangleIndex, uint8 InTriangleVertexIndex, const FVector& InUTangent); UFUNCTION() void SetTriangleVertexVTangent(uint32 InTriangleIndex, uint8 InTriangleVertexIndex, const FVector& InVTangent); UFUNCTION() void SetTriangleVertexColor(uint32 InTriangleIndex, uint8 InTriangleVertexIndex, const FColor& InColor); UFUNCTION() void SetTriangleVertexUV(uint32 InTriangleIndex, uint8 InTriangleVertexIndex, uint8 InUVLayer, const FVector2D& InUV); UFUNCTION() void SetTriangleMaterialID(uint32 InTriangleIndex, int32 InMaterialID); UFUNCTION() void SetStaticMaterial(uint32 InMaterialIndex, const FStaticMaterial& InStaticMaterial); UFUNCTION() uint32 AddStaticMaterial(const FStaticMaterial& InStaticMaterial) { return StaticMaterials.Add(InStaticMaterial); } /** Calculate the normals of the mesh by calculating the face normal of each triangle (if a triangle has vertices * V0, V1, V2, get the vector perpendicular to the face Pf = (V2 - V0) x (V1 - V0). To calculate the * vertex normal for V0 sum and then normalize all its shared face normals. If bInComputeWeightedNormals is true * then the weight of each face normal that contributes to V0's normal is the area of the face multiplied by the V0 * corner angle of that face. If bInComputeWeightedNormals is false then the weight is 1. * * @param bInComputeWeightedNormals Whether or not to use weighted normal calculation. Defaults to false. */ UFUNCTION() void CalculateNormals(bool bInComputeWeightedNormals=false); /** * Calculate tangents from the normals. Calculates normals first via CalculateNormals() if the mesh does not yet * have normals. * * @param bInComputeWeightedNormals Whether or not to use weighted normal calculation if CalculateNormals() is * called. Defaults to false. */ UFUNCTION() void CalculateTangents(bool bInComputeWeightedNormals=false); /** * Meant to be called after the mesh data arrays are populated. * Currently only calls Shrink on the arrays */ UFUNCTION() void Optimize(); UFUNCTION() FBox CalcBounds() const; UFUNCTION() const TArray& GetVertexPositions() const { return VertexPositions; } UFUNCTION() const TArray& GetTriangleIndices() const { return TriangleIndices; } UFUNCTION() const TArray& GetVertexInstanceColors() const { return VertexInstanceColors; } UFUNCTION() const TArray& GetVertexInstanceNormals() const { return VertexInstanceNormals; } UFUNCTION() const TArray& GetVertexInstanceUTangents() const { return VertexInstanceUTangents; } UFUNCTION() const TArray& GetVertexInstanceVTangents() const { return VertexInstanceVTangents; } UFUNCTION() const TArray& GetVertexInstanceUVs() const { return VertexInstanceUVs; } UFUNCTION() const TArray& GetMaterialIDsPerTriangle() const { return MaterialIDsPerTriangle; } UFUNCTION() const TArray& GetStaticMaterials() const { return StaticMaterials; } TArray& GetStaticMaterials() { return StaticMaterials; } UFUNCTION() UMaterialInterface* GetMaterial(int32 InMaterialIndex); UFUNCTION() int32 GetMaterialIndex(FName InMaterialSlotName) const; // Checks if the mesh is valid by checking face, vertex and attribute (normals etc) counts. // If bSkipVertexIndicesCheck is true, then we don't loop over all triangle vertex indices to // check if each index is valid (< NumVertices) UFUNCTION() bool IsValid(bool bInSkipVertexIndicesCheck=false) const; // Custom serialization: we use TArray::BulkSerialize to speed up array serialization virtual void Serialize(FArchive &InArchive) override; protected: UPROPERTY() bool bHasNormals; UPROPERTY() bool bHasTangents; UPROPERTY() bool bHasColors; /** The number of UV layers that the mesh has */ UPROPERTY() uint32 NumUVLayers; UPROPERTY() bool bHasPerFaceMaterials; /** Vertex positions. The vertex id == vertex index => indexes into this array. */ UPROPERTY(SkipSerialization) TArray VertexPositions; /** Triangle vertices. Triangle id == triangle index => indexes into this array, which returns a FIntVector of * vertex ids/indices for VertexPositions. */ UPROPERTY(SkipSerialization) TArray TriangleIndices; /** Array of colors per vertex instance, in other words, a color per triangle-vertex. Index 3 * TriangleID + LocalTriangleVertexIndex. */ UPROPERTY(SkipSerialization) TArray VertexInstanceColors; /** Array of normals per vertex instance, in other words, a normal per triangle-vertex. Index 3 * TriangleID + LocalTriangleVertexIndex. */ UPROPERTY(SkipSerialization) TArray VertexInstanceNormals; /** Array of U tangents per vertex instance, in other words, a tangent per triangle-vertex. Index 3 * TriangleID + LocalTriangleVertexIndex. */ UPROPERTY(SkipSerialization) TArray VertexInstanceUTangents; /** Array of V tangents per vertex instance, in other words, a tangent per triangle-vertex. Index 3 * TriangleID + LocalTriangleVertexIndex. */ UPROPERTY(SkipSerialization) TArray VertexInstanceVTangents; /** Array of UV layers to array of per triangle-vertex UVs. Index: UVLayerIndex * (NumVertexInstances) + 3 * TriangleID + LocalTriangleVertexIndex. */ UPROPERTY(SkipSerialization) TArray VertexInstanceUVs; /** Array of material ID per triangle. Indexed by Triangle ID/Index. */ UPROPERTY(SkipSerialization) TArray MaterialIDsPerTriangle; /** The materials of the mesh. Index by MaterialID (MaterialIndex). */ UPROPERTY() TArray StaticMaterials; };