SHARE
TWEET

Untitled

a guest Apr 21st, 2019 178 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*=============================================================================
  2.     UnSkeletalTools.cpp: Skeletal mesh helper classes.
  3.  
  4.     Copyright 2001,2004   Epic Games, Inc. All Rights Reserved.
  5. =============================================================================*/
  6.  
  7. #include "EnginePrivate.h"
  8.  
  9. //
  10. //  PointsEqual
  11. //
  12.  
  13. static inline UBOOL PointsEqual(FVector& V1,FVector& V2)
  14. {
  15.     if(Abs(V1.X - V2.X) > THRESH_POINTS_ARE_SAME * 4.0f)
  16.         return 0;
  17.  
  18.     if(Abs(V1.Y - V2.Y) > THRESH_POINTS_ARE_SAME * 4.0f)
  19.         return 0;
  20.  
  21.     if(Abs(V1.Z - V2.Z) > THRESH_POINTS_ARE_SAME * 4.0f)
  22.         return 0;
  23.  
  24.     return 1;
  25. }
  26.  
  27. //
  28. //  UVsEqual
  29. //
  30.  
  31. static inline UBOOL UVsEqual(FMeshWedge& V1,FMeshWedge& V2)
  32. {
  33.     if(Abs(V1.U - V2.U) > (1.0f / 1024.0f))
  34.         return 0;
  35.  
  36.     if(Abs(V1.V - V2.V) > (1.0f / 1024.0f))
  37.         return 0;
  38.  
  39.     return 1;
  40. }
  41.  
  42. //
  43. //  AddSkinVertex
  44. //
  45.  
  46. static INT AddSkinVertex(TArray<FSoftSkinVertex>& Vertices,FSoftSkinVertex& Vertex)
  47. {
  48.     for(UINT VertexIndex = 0;VertexIndex < (UINT)Vertices.Num();VertexIndex++)
  49.     {
  50.         FSoftSkinVertex&    OtherVertex = Vertices(VertexIndex);
  51.  
  52.         if(!PointsEqual(OtherVertex.Position,Vertex.Position))
  53.             continue;
  54.  
  55.         if(Abs(Vertex.U - OtherVertex.U) > (1.0f / 1024.0f))
  56.             continue;
  57.  
  58.         if(Abs(Vertex.V - OtherVertex.V) > (1.0f / 1024.0f))
  59.             continue;
  60.  
  61.         if(!(OtherVertex.TangentX == Vertex.TangentX))
  62.             continue;
  63.  
  64.         if(!(OtherVertex.TangentY == Vertex.TangentY))
  65.             continue;
  66.  
  67.         if(!(OtherVertex.TangentZ == Vertex.TangentZ))
  68.             continue;
  69.  
  70.         UBOOL   InfluencesMatch = 1;
  71.         for(UINT InfluenceIndex = 0;InfluenceIndex < 4;InfluenceIndex++)
  72.         {
  73.             if(Vertex.InfluenceBones[InfluenceIndex] != OtherVertex.InfluenceBones[InfluenceIndex] || Vertex.InfluenceWeights[InfluenceIndex] != OtherVertex.InfluenceWeights[InfluenceIndex])
  74.             {
  75.                 InfluencesMatch = 0;
  76.                 break;
  77.             }
  78.         }
  79.         if(!InfluencesMatch)
  80.             continue;
  81.  
  82.         return VertexIndex;
  83.     }
  84.  
  85.     return Vertices.AddItem(Vertex);
  86. }
  87.  
  88. //
  89. //  FindEdgeIndex
  90. //
  91.  
  92. static INT FindEdgeIndex(TArray<FMeshEdge>& Edges,const TArray<FSoftSkinVertex>& Vertices,FMeshEdge& Edge)
  93. {
  94.     for(INT EdgeIndex = 0;EdgeIndex < Edges.Num();EdgeIndex++)
  95.     {
  96.         FMeshEdge&  OtherEdge = Edges(EdgeIndex);
  97.  
  98.         if(Vertices(OtherEdge.Vertices[0]).Position != Vertices(Edge.Vertices[1]).Position)
  99.             continue;
  100.  
  101.         if(Vertices(OtherEdge.Vertices[1]).Position != Vertices(Edge.Vertices[0]).Position)
  102.             continue;
  103.  
  104.         UBOOL   InfluencesMatch = 1;
  105.         for(UINT InfluenceIndex = 0;InfluenceIndex < 4;InfluenceIndex++)
  106.         {
  107.             if(Vertices(OtherEdge.Vertices[0]).InfluenceBones[InfluenceIndex] != Vertices(Edge.Vertices[1]).InfluenceBones[InfluenceIndex] ||
  108.                 Vertices(OtherEdge.Vertices[0]).InfluenceWeights[InfluenceIndex] != Vertices(Edge.Vertices[1]).InfluenceWeights[InfluenceIndex] ||
  109.                 Vertices(OtherEdge.Vertices[1]).InfluenceBones[InfluenceIndex] != Vertices(Edge.Vertices[0]).InfluenceBones[InfluenceIndex] ||
  110.                 Vertices(OtherEdge.Vertices[1]).InfluenceWeights[InfluenceIndex] != Vertices(Edge.Vertices[0]).InfluenceWeights[InfluenceIndex])
  111.             {
  112.                 InfluencesMatch = 0;
  113.                 break;
  114.             }
  115.         }
  116.  
  117.         if(!InfluencesMatch)
  118.             break;
  119.  
  120.         if(OtherEdge.Faces[1] != INDEX_NONE)
  121.             continue;
  122.  
  123.         OtherEdge.Faces[1] = Edge.Faces[0];
  124.         return EdgeIndex;
  125.     }
  126.  
  127.     new(Edges) FMeshEdge(Edge);
  128.  
  129.     return Edges.Num() - 1;
  130. }
  131.  
  132. /**
  133.  * Create all render specific (but serializable) data like e.g. the 'compiled' rendering stream,
  134.  * mesh sections and index buffer.
  135.  *
  136.  * @todo: currently only handles LOD level 0.
  137.  */
  138. void USkeletalMesh::CreateSkinningStreams()
  139. {
  140. #ifndef CONSOLE
  141.     check( LODModels.Num() );
  142.     FStaticLODModel& LODModel = LODModels(0);
  143.    
  144.     // Allow multiple calls to CreateSkinningStreams for same model/LOD.
  145.  
  146.     LODModel.Sections.Empty();
  147.     LODModel.SoftVertices.Empty();
  148.     LODModel.RigidVertices.Empty();
  149.     LODModel.ShadowIndices.Empty();
  150.     LODModel.IndexBuffer.Indices.Empty();
  151.     LODModel.IndexBuffer.Size = 0;
  152.     LODModel.Edges.Empty();
  153.  
  154.     // Calculate face tangent vectors.
  155.  
  156.     TArray<FVector> FaceTangentX(LODModel.Faces.Num());
  157.     TArray<FVector> FaceTangentY(LODModel.Faces.Num());
  158.  
  159.     for(INT FaceIndex = 0;FaceIndex < LODModel.Faces.Num();FaceIndex++)
  160.     {
  161.         FVector P1 = LODModel.Points(LODModel.Wedges(LODModel.Faces(FaceIndex).iWedge[0]).iVertex),
  162.                 P2 = LODModel.Points(LODModel.Wedges(LODModel.Faces(FaceIndex).iWedge[1]).iVertex),
  163.                 P3 = LODModel.Points(LODModel.Wedges(LODModel.Faces(FaceIndex).iWedge[2]).iVertex);
  164.         FVector TriangleNormal = FPlane(P3,P2,P1);
  165.         FMatrix ParameterToLocal(
  166.             FPlane( P2.X - P1.X,    P2.Y - P1.Y,    P2.Z - P1.Z,    0   ),
  167.             FPlane( P3.X - P1.X,    P3.Y - P1.Y,    P3.Z - P1.Z,    0   ),
  168.             FPlane( P1.X,           P1.Y,           P1.Z,           0   ),
  169.             FPlane( 0,              0,              0,              1   )
  170.             );
  171.  
  172.         FLOAT   U1 = LODModel.Wedges(LODModel.Faces(FaceIndex).iWedge[0]).U,
  173.                 U2 = LODModel.Wedges(LODModel.Faces(FaceIndex).iWedge[1]).U,
  174.                 U3 = LODModel.Wedges(LODModel.Faces(FaceIndex).iWedge[2]).U,
  175.                 V1 = LODModel.Wedges(LODModel.Faces(FaceIndex).iWedge[0]).V,
  176.                 V2 = LODModel.Wedges(LODModel.Faces(FaceIndex).iWedge[1]).V,
  177.                 V3 = LODModel.Wedges(LODModel.Faces(FaceIndex).iWedge[2]).V;
  178.  
  179.         FMatrix ParameterToTexture(
  180.             FPlane( U2 - U1,    V2 - V1,    00   ),
  181.             FPlane( U3 - U1,    V3 - V1,    00   ),
  182.             FPlane( U1,         V1,         10   ),
  183.             FPlane( 0,          0,          01   )
  184.             );
  185.  
  186.         FMatrix TextureToLocal = ParameterToTexture.Inverse() * ParameterToLocal;
  187.         FVector TangentX = TextureToLocal.TransformNormal(FVector(1,0,0)).SafeNormal(),
  188.                 TangentY = TextureToLocal.TransformNormal(FVector(0,1,0)).SafeNormal(),
  189.                 TangentZ;
  190.  
  191.         TangentX = TangentX - TriangleNormal * (TangentX | TriangleNormal);
  192.         TangentY = TangentY - TriangleNormal * (TangentY | TriangleNormal);
  193.  
  194.         FaceTangentX(FaceIndex) = TangentX.SafeNormal();
  195.         FaceTangentY(FaceIndex) = TangentY.SafeNormal();
  196.     }
  197.  
  198.     // Find wedge influences.
  199.  
  200.     TArray<INT> WedgeInfluenceIndices;
  201.     INT InfIdx = 0;
  202.  
  203.     for(INT WedgeIndex = 0;WedgeIndex < LODModel.Wedges.Num();WedgeIndex++)
  204.     {
  205.         for(UINT LookIdx = 0;LookIdx < (UINT)LODModel.Influences.Num();LookIdx++)
  206.         {
  207.             if(LODModel.Influences(LookIdx).VertIndex == LODModel.Wedges(WedgeIndex).iVertex)
  208.             {
  209.                 WedgeInfluenceIndices.AddItem(LookIdx);
  210.                 break;
  211.             }
  212.         }
  213.     }
  214.     check(LODModel.Wedges.Num() == WedgeInfluenceIndices.Num());
  215.  
  216.     // Calculate smooth wedge tangent vectors.
  217.  
  218.     TArray<FRawIndexBuffer> SectionIndexBuffers;
  219.     FSkelMeshSection*       Section = NULL;
  220.     FRawIndexBuffer*        SectionIndexBuffer = NULL;
  221.     TArray<FSoftSkinVertex> Vertices;
  222.  
  223.     for(INT FaceIndex = 0;FaceIndex < LODModel.Faces.Num();FaceIndex++)
  224.     {
  225.         FMeshFace&  Face = LODModel.Faces(FaceIndex);
  226.  
  227.         FVector VertexTangentX[3],
  228.                 VertexTangentY[3],
  229.                 VertexTangentZ[3];
  230.  
  231.         for(INT VertexIndex = 0;VertexIndex < 3;VertexIndex++)
  232.         {
  233.             VertexTangentX[VertexIndex] = FVector(0,0,0);
  234.             VertexTangentY[VertexIndex] = FVector(0,0,0);
  235.             VertexTangentZ[VertexIndex] = FVector(0,0,0);
  236.         }
  237.  
  238.         FVector TriangleNormal = FPlane(
  239.             LODModel.Points(LODModel.Wedges(Face.iWedge[2]).iVertex),
  240.             LODModel.Points(LODModel.Wedges(Face.iWedge[1]).iVertex),
  241.             LODModel.Points(LODModel.Wedges(Face.iWedge[0]).iVertex)
  242.             );
  243.         FLOAT   Determinant = FTriple(FaceTangentX(FaceIndex),FaceTangentY(FaceIndex),TriangleNormal);
  244.         for(INT OtherFaceIndex = 0;OtherFaceIndex < LODModel.Faces.Num();OtherFaceIndex++)
  245.         {
  246.             FMeshFace&  OtherFace = LODModel.Faces(OtherFaceIndex);
  247.             FVector     OtherTriangleNormal = FPlane(
  248.                             LODModel.Points(LODModel.Wedges(OtherFace.iWedge[2]).iVertex),
  249.                             LODModel.Points(LODModel.Wedges(OtherFace.iWedge[1]).iVertex),
  250.                             LODModel.Points(LODModel.Wedges(OtherFace.iWedge[0]).iVertex)
  251.                             );
  252.             FLOAT       OtherFaceDeterminant = FTriple(FaceTangentX(OtherFaceIndex),FaceTangentY(OtherFaceIndex),OtherTriangleNormal);
  253.  
  254.             for(INT VertexIndex = 0;VertexIndex < 3;VertexIndex++)
  255.             {
  256.                 for(INT OtherVertexIndex = 0;OtherVertexIndex < 3;OtherVertexIndex++)
  257.                 {
  258.                     if(PointsEqual(
  259.                         LODModel.Points(LODModel.Wedges(OtherFace.iWedge[OtherVertexIndex]).iVertex),
  260.                         LODModel.Points(LODModel.Wedges(Face.iWedge[VertexIndex]).iVertex)
  261.                         ))                 
  262.                     {
  263.                         if(Determinant * OtherFaceDeterminant > 0.0f && UVsEqual(LODModel.Wedges(OtherFace.iWedge[OtherVertexIndex]),LODModel.Wedges(Face.iWedge[VertexIndex])))
  264.                         {
  265.                             VertexTangentX[VertexIndex] += FaceTangentX(OtherFaceIndex);
  266.                             VertexTangentY[VertexIndex] += FaceTangentY(OtherFaceIndex);
  267.                         }
  268.  
  269.                         // Only contribute 'normal' if the vertices are truly one and the same to obey hard "smoothing" edges baked into
  270.                         // the mesh by vertex duplication.. - Erik
  271.                         if( LODModel.Wedges(OtherFace.iWedge[OtherVertexIndex]).iVertex == LODModel.Wedges(Face.iWedge[VertexIndex]).iVertex )
  272.                         {
  273.                             VertexTangentZ[VertexIndex] += OtherTriangleNormal;
  274.                         }
  275.                     }
  276.                 }
  277.             }
  278.         }
  279.  
  280.         // Add this triangle to a section.
  281.  
  282.         if(!Section || (Face.MeshMaterialIndex != Section->MaterialIndex))
  283.         {
  284.             // Create a new static mesh section.
  285.  
  286.             Section = new(LODModel.Sections)FSkelMeshSection;
  287.             Section->FirstFace = FaceIndex;
  288.             Section->MaterialIndex = Face.MeshMaterialIndex;   
  289.             Section->TotalFaces = 0;
  290.  
  291.             SectionIndexBuffer = new(SectionIndexBuffers) FRawIndexBuffer;
  292.         }
  293.  
  294.         Section->TotalFaces++;
  295.  
  296.         _WORD   TriangleIndices[3];
  297.  
  298.         for(INT VertexIndex = 0;VertexIndex < 3;VertexIndex++)
  299.         {
  300.             FSoftSkinVertex Vertex;
  301.             FVector         TangentX = VertexTangentX[VertexIndex].SafeNormal(),
  302.                             TangentY = VertexTangentY[VertexIndex].SafeNormal(),
  303.                             TangentZ = VertexTangentZ[VertexIndex].SafeNormal();
  304.  
  305.             TangentY -= TangentX * (TangentX | TangentY);
  306.             TangentY.Normalize();
  307.  
  308.             TangentX -= TangentZ * (TangentZ | TangentX);
  309.             TangentY -= TangentZ * (TangentZ | TangentY);
  310.  
  311.             TangentX.Normalize();
  312.             TangentY.Normalize();
  313.  
  314.             Vertex.Position = LODModel.Points(LODModel.Wedges(Face.iWedge[VertexIndex]).iVertex);
  315.             Vertex.TangentX = TangentX;
  316.             Vertex.TangentY = TangentY;
  317.             Vertex.TangentZ = TangentZ;
  318.             Vertex.U = LODModel.Wedges(Face.iWedge[VertexIndex]).U;
  319.             Vertex.V = LODModel.Wedges(Face.iWedge[VertexIndex]).V;
  320.  
  321.             // Count the influences.
  322.  
  323.             InfIdx = WedgeInfluenceIndices(Face.iWedge[VertexIndex]);
  324.             INT LookIdx = InfIdx;
  325.  
  326.             UINT InfluenceCount = 0;
  327.             while ( (LODModel.Influences(LookIdx).VertIndex == LODModel.Wedges(Face.iWedge[VertexIndex]).iVertex) && ( LODModel.Influences.Num() > LookIdx) )
  328.             {          
  329.                 InfluenceCount++;
  330.                 LookIdx++;
  331.             }
  332.  
  333.             if( InfluenceCount > 4 )
  334.                 InfluenceCount = 4;
  335.  
  336.             // Setup the vertex influences.
  337.  
  338.             Vertex.InfluenceBones[0] = 0;
  339.             Vertex.InfluenceWeights[0] = 255;
  340.  
  341.             for(UINT i = 1;i < 4;i++)
  342.             {
  343.                 Vertex.InfluenceBones[i] = 0;
  344.                 Vertex.InfluenceWeights[i] = 0;
  345.             }
  346.  
  347.             UINT    TotalInfluenceWeight = 0;
  348.  
  349.             for(UINT i = 0;i < InfluenceCount;i++)
  350.             {
  351.                 BYTE    BoneIndex = 0;
  352.  
  353.                 BoneIndex = (BYTE)LODModel.Influences(InfIdx+i).BoneIndex;
  354.  
  355.                 if( BoneIndex >= RefSkeleton.Num() )
  356.                     continue;
  357.  
  358.                 Vertex.InfluenceBones[i] = LODModel.ActiveBoneIndices.AddUniqueItem(BoneIndex);
  359.                 Vertex.InfluenceWeights[i] = (BYTE)(LODModel.Influences(InfIdx+i).Weight * 255.0f);
  360.                 TotalInfluenceWeight += Vertex.InfluenceWeights[i];
  361.             }
  362.  
  363.             Vertex.InfluenceWeights[0] += 255 - TotalInfluenceWeight;
  364.  
  365.             InfIdx = LookIdx;
  366.  
  367.             // Add the vertex.
  368.  
  369.             INT V = AddSkinVertex(Vertices,Vertex);
  370.             check(V >= 0 && V <= MAXWORD);
  371.             TriangleIndices[VertexIndex] = (_WORD)V;
  372.         }
  373.  
  374.         if(TriangleIndices[0] != TriangleIndices[1] && TriangleIndices[0] != TriangleIndices[2] && TriangleIndices[1] != TriangleIndices[2])
  375.         {
  376.             for(UINT EdgeIndex = 0;EdgeIndex < 3;EdgeIndex++)
  377.             {
  378.                 FMeshEdge   Edge;
  379.  
  380.                 Edge.Vertices[0] = TriangleIndices[EdgeIndex];
  381.                 Edge.Vertices[1] = TriangleIndices[(EdgeIndex + 1) % 3];
  382.                 Edge.Faces[0] = LODModel.ShadowIndices.Num() / 3;
  383.                 Edge.Faces[1] = -1;
  384.  
  385.                 FindEdgeIndex(LODModel.Edges,Vertices,Edge);
  386.             }
  387.  
  388.             for(UINT VertexIndex = 0;VertexIndex < 3;VertexIndex++)
  389.             {
  390.                 SectionIndexBuffer->Indices.AddItem(TriangleIndices[VertexIndex]);
  391.                 LODModel.ShadowIndices.AddItem(TriangleIndices[VertexIndex]);
  392.             }
  393.             SectionIndexBuffer->Size += sizeof(_WORD) * 3;
  394.         }
  395.     }
  396.  
  397.     // Find mesh sections with open edges.
  398.  
  399.     TArray<INT> SeparateTriangles;
  400.  
  401.     while(1)
  402.     {
  403.         INT InitialSeparate = SeparateTriangles.Num();
  404.         for(INT EdgeIndex = 0;EdgeIndex < LODModel.Edges.Num();EdgeIndex++)
  405.         {
  406.             FMeshEdge&  Edge = LODModel.Edges(EdgeIndex);
  407.             if(Edge.Faces[1] == INDEX_NONE || SeparateTriangles.FindItemIndex(Edge.Faces[1]) != INDEX_NONE)
  408.                 SeparateTriangles.AddUniqueItem(Edge.Faces[0]);
  409.             else if(SeparateTriangles.FindItemIndex(Edge.Faces[0]) != INDEX_NONE)
  410.                 SeparateTriangles.AddUniqueItem(Edge.Faces[1]);
  411.         }
  412.         if(SeparateTriangles.Num() == InitialSeparate)
  413.             break;
  414.     };
  415.  
  416.     LODModel.ShadowTriangleDoubleSided.Empty(LODModel.ShadowIndices.Num() / 3);
  417.     LODModel.ShadowTriangleDoubleSided.AddZeroed(LODModel.ShadowIndices.Num() / 3);
  418.  
  419.     for(UINT TriangleIndex = 0;TriangleIndex < (UINT)SeparateTriangles.Num();TriangleIndex++)
  420.         LODModel.ShadowTriangleDoubleSided(SeparateTriangles(TriangleIndex)) = 1;
  421.  
  422.     // Separate the vertices into soft and rigid vertices.
  423.  
  424.     TArray<_WORD>   VertexMap(Vertices.Num());
  425.  
  426.     for(UINT VertexIndex = 0;VertexIndex < (UINT)Vertices.Num();VertexIndex++)
  427.     {
  428.         const FSoftSkinVertex&  SoftVertex = Vertices(VertexIndex);
  429.  
  430.         if(SoftVertex.InfluenceWeights[1] == 0)
  431.         {
  432.             FRigidSkinVertex    RigidVertex;
  433.             RigidVertex.Position = SoftVertex.Position;
  434.             RigidVertex.TangentX = SoftVertex.TangentX;
  435.             RigidVertex.TangentY = SoftVertex.TangentY;
  436.             RigidVertex.TangentZ = SoftVertex.TangentZ;
  437.             RigidVertex.U = SoftVertex.U;
  438.             RigidVertex.V = SoftVertex.V;
  439.             RigidVertex.Bone = SoftVertex.InfluenceBones[0];
  440.             VertexMap(VertexIndex) = (_WORD)LODModel.RigidVertices.AddItem(RigidVertex);
  441.         }
  442.     }
  443.  
  444.     for(UINT VertexIndex = 0;VertexIndex < (UINT)Vertices.Num();VertexIndex++)
  445.     {
  446.         const FSoftSkinVertex&  SoftVertex = Vertices(VertexIndex);
  447.  
  448.         if(SoftVertex.InfluenceWeights[1] > 0)
  449.             VertexMap(VertexIndex) = (_WORD)LODModel.RigidVertices.Num() + (_WORD)LODModel.SoftVertices.AddItem(SoftVertex);
  450.     }
  451.  
  452.     // Remap the edge and shadow vertex indices.
  453.  
  454.     for(UINT EdgeIndex = 0;EdgeIndex < (UINT)LODModel.Edges.Num();EdgeIndex++)
  455.     {
  456.         LODModel.Edges(EdgeIndex).Vertices[0] = VertexMap(LODModel.Edges(EdgeIndex).Vertices[0]);
  457.         LODModel.Edges(EdgeIndex).Vertices[1] = VertexMap(LODModel.Edges(EdgeIndex).Vertices[1]);
  458.     }
  459.  
  460.     for(UINT Index = 0;Index < (UINT)LODModel.ShadowIndices.Num();Index++)
  461.         LODModel.ShadowIndices(Index) = VertexMap(LODModel.ShadowIndices(Index));
  462.  
  463.     UINT    NumOpenEdges = 0;
  464.     for(UINT EdgeIndex = 0;EdgeIndex < (UINT)LODModel.Edges.Num();EdgeIndex++)
  465.         if(LODModel.Edges(EdgeIndex).Faces[1] == INDEX_NONE)
  466.             NumOpenEdges++;
  467.  
  468.     debugf(TEXT("%u rigid, %u soft, %u double-sided, %u edges(%u open)"),LODModel.RigidVertices.Num(),LODModel.SoftVertices.Num(),SeparateTriangles.Num(),LODModel.Edges.Num(),NumOpenEdges);
  469.  
  470.     // Finish building the sections.
  471.  
  472.     for(UINT SectionIndex = 0,GlobalTriangleIndex = 0;SectionIndex < (UINT)LODModel.Sections.Num();SectionIndex++)
  473.     {
  474.         FSkelMeshSection&   Section = LODModel.Sections(SectionIndex);
  475.         FRawIndexBuffer&    SectionIndexBuffer = SectionIndexBuffers(SectionIndex);
  476.  
  477.         SectionIndexBuffer.CacheOptimize();
  478.  
  479.         Section.MinIndex = MAXWORD;
  480.         Section.MaxIndex = 0;
  481.  
  482.         for(UINT Index = 0;Index < (UINT)SectionIndexBuffer.Indices.Num();Index++)
  483.         {
  484.             _WORD&  VertexIndex = SectionIndexBuffer.Indices(Index);
  485.             VertexIndex = VertexMap(VertexIndex);
  486.             Section.MinIndex = Min(Section.MinIndex,VertexIndex);
  487.             Section.MaxIndex = Max(Section.MaxIndex,VertexIndex);
  488.         }
  489.  
  490.         Section.FirstIndex = LODModel.IndexBuffer.Indices.Num();
  491.         Section.TotalFaces = SectionIndexBuffer.Indices.Num() / 3;
  492.         appMemcpy(&LODModel.IndexBuffer.Indices(LODModel.IndexBuffer.Indices.Add(SectionIndexBuffer.Indices.Num())),&SectionIndexBuffer.Indices(0),SectionIndexBuffer.Indices.Num() * sizeof(_WORD));
  493.  
  494.         Section.TotalVerts = (Section.MaxIndex - Section.MinIndex )+1;
  495.  
  496.         debugf(TEXT(" Smooth section constructed: [%3i], MinIndex  %3i, MaxIndex %3i, Material %3i Faces %3i FirstFace %3i Wedges: %i ActiveBones: %i"),
  497.             SectionIndex,
  498.             Section.MinIndex,
  499.             Section.MaxIndex,
  500.             Section.MaterialIndex,
  501.             Section.TotalFaces,
  502.             Section.FirstFace,
  503.             LODModel.Faces.Num() * 3,
  504.             Section.ActiveBoneIndices.Num()
  505.         );
  506.     }
  507.  
  508.     LODModel.IndexBuffer.Size = LODModel.IndexBuffer.Indices.Num() * sizeof(_WORD);
  509.     GResourceManager->UpdateResource(&LODModel.IndexBuffer);
  510. #else
  511.     appErrorf(TEXT("Cannot call USkeletalMesh::CreateSkinningStreams on a console!"));
  512. #endif
  513. }
  514.  
  515. // Pre-calculate refpose-to-local transforms
  516. void USkeletalMesh::CalculateInvRefMatrices()
  517. {
  518.     if( RefBasesInvMatrix.Num() != RefSkeleton.Num() )
  519.     {
  520.         RefBasesInvMatrix.Empty();
  521.         RefBasesInvMatrix.Add( RefSkeleton.Num() );
  522.  
  523.         // Temporary storage for calculating mesh-space ref pose
  524.         TArray<FMatrix> RefBases;
  525.         RefBases.Add( RefSkeleton.Num() );
  526.  
  527.         // Precompute the Mesh.RefBasesInverse.
  528.         for( INT b=0; b<RefSkeleton.Num(); b++)
  529.         {
  530.             // Render the default pose.
  531.             RefBases(b) = GetRefPoseMatrix(b);
  532.  
  533.             // Construct mesh-space skeletal hierarchy.
  534.             if( b>0 )
  535.             {
  536.                 INT Parent = RefSkeleton(b).ParentIndex;
  537.                 RefBases(b) = RefBases(b) * RefBases(Parent);
  538.             }
  539.  
  540.             // Precompute inverse so we can use from-refpose-skin vertices.
  541.             RefBasesInvMatrix(b) = RefBases(b).Inverse();
  542.         }
  543.     }
  544. }
  545.  
  546. // Find the most dominant bone for each vertex
  547. static INT GetDominantBoneIndex(FSoftSkinVertex* SoftVert)
  548. {
  549.     BYTE MaxWeightBone = 0;
  550.     BYTE MaxWeightWeight = 0;
  551.  
  552.     for(INT i=0; i<4; i++)
  553.     {
  554.         if(SoftVert->InfluenceWeights[i] > MaxWeightWeight)
  555.         {
  556.             MaxWeightWeight = SoftVert->InfluenceWeights[i];
  557.             MaxWeightBone = SoftVert->InfluenceBones[i];
  558.         }
  559.     }
  560.  
  561.     return MaxWeightBone;
  562. }
  563.  
  564. /**
  565.  *  Calculate the verts associated weighted to each bone of the skeleton.
  566.  *  The vertices returned are in the local space of the bone.
  567.  *
  568.  *  @param  Infos   The output array of vertices associated with each bone.
  569.  *  @param  bOnlyDominant   Controls whether a vertex is added to the info for a bone if it is most controlled by that bone, or if that bone has ANY influence on that vert.
  570.  */
  571. void USkeletalMesh::CalcBoneVertInfos( TArray<FBoneVertInfo>& Infos, UBOOL bOnlyDominant )
  572. {
  573.     if( LODModels.Num() == 0)
  574.         return;
  575.  
  576.     CalculateInvRefMatrices();
  577.     check( RefSkeleton.Num() == RefBasesInvMatrix.Num() );
  578.  
  579.     Infos.Empty();
  580.     Infos.AddZeroed( RefSkeleton.Num() );
  581.  
  582.     FStaticLODModel* LODModel = &LODModels(0);
  583.     for(INT i=0; i<LODModel->RigidVertices.Num(); i++)
  584.     {
  585.         FRigidSkinVertex* RigidVert = &LODModel->RigidVertices(i);
  586.         INT BoneIndex = LODModel->ActiveBoneIndices( RigidVert->Bone );
  587.  
  588.         FVector LocalPos = RefBasesInvMatrix(BoneIndex).TransformFVector(RigidVert->Position);
  589.         Infos(BoneIndex).Positions.AddItem(LocalPos);
  590.  
  591.         FVector LocalNormal = RefBasesInvMatrix(BoneIndex).TransformNormal(RigidVert->TangentZ);
  592.         Infos(BoneIndex).Normals.AddItem(LocalNormal);
  593.     }
  594.  
  595.     for(INT i=0; i<LODModel->SoftVertices.Num(); i++)
  596.     {
  597.         FSoftSkinVertex* SoftVert = &LODModel->SoftVertices(i);
  598.  
  599.         if(bOnlyDominant)
  600.         {
  601.             INT BoneIndex = LODModel->ActiveBoneIndices( GetDominantBoneIndex(SoftVert) );
  602.  
  603.             FVector LocalPos = RefBasesInvMatrix(BoneIndex).TransformFVector(SoftVert->Position);
  604.             Infos(BoneIndex).Positions.AddItem(LocalPos);
  605.  
  606.             FVector LocalNormal = RefBasesInvMatrix(BoneIndex).TransformNormal(SoftVert->TangentZ);
  607.             Infos(BoneIndex).Normals.AddItem(LocalNormal);
  608.         }
  609.         else
  610.         {
  611.             for(INT j=0; j<4; j++)
  612.             {
  613.                 if(SoftVert->InfluenceWeights[j] > 0.01f)
  614.                 {
  615.                     INT BoneIndex = LODModel->ActiveBoneIndices( SoftVert->InfluenceBones[j] );
  616.  
  617.                     FVector LocalPos = RefBasesInvMatrix(BoneIndex).TransformFVector(SoftVert->Position);
  618.                     Infos(BoneIndex).Positions.AddItem(LocalPos);
  619.  
  620.                     FVector LocalNormal = RefBasesInvMatrix(BoneIndex).TransformNormal(SoftVert->TangentZ);
  621.                     Infos(BoneIndex).Normals.AddItem(LocalNormal);
  622.                 }
  623.             }
  624.         }
  625.     }
  626. }
  627.  
  628. /**
  629.  * Find if one bone index is a child of another.
  630.  * Note - will return FALSE if ChildBoneIndex is the same as ParentBoneIndex ie. must be strictly a child.
  631.  */
  632. UBOOL USkeletalMesh::BoneIsChildOf(INT ChildBoneIndex, INT ParentBoneIndex )
  633. {
  634.     if(ChildBoneIndex == ParentBoneIndex)
  635.         return false;
  636.  
  637.     INT BoneIndex = RefSkeleton(ChildBoneIndex).ParentIndex;
  638.     while(1)
  639.     {
  640.         if(BoneIndex == ParentBoneIndex)
  641.             return true;
  642.  
  643.         if(BoneIndex == 0)
  644.             return false;
  645.  
  646.         BoneIndex = RefSkeleton(BoneIndex).ParentIndex;
  647.     }
  648. }
  649.  
  650. ////// SKELETAL MESH THUMBNAIL SUPPORT ////////
  651.  
  652. struct FSkeletalMeshThumbnailScene: FPreviewScene
  653. {
  654.     FSceneView  View;
  655.  
  656.     // Constructor/destructor.
  657.  
  658.     FSkeletalMeshThumbnailScene(USkeletalMesh* InSkeletalMesh)
  659.     {
  660.         USkeletalMeshComponent*     SkeletalMeshComponent = ConstructObject<USkeletalMeshComponent>(USkeletalMeshComponent::StaticClass());
  661.         SkeletalMeshComponent->SkeletalMesh = InSkeletalMesh;
  662.         SkeletalMeshComponent->Scene = this;
  663.         SkeletalMeshComponent->SetParentToWorld(FMatrix::Identity);
  664.         SkeletalMeshComponent->Created();
  665.         Components.AddItem(SkeletalMeshComponent);
  666.  
  667.         // We look at the bounding box to see which side to render it from.
  668.         if(SkeletalMeshComponent->Bounds.BoxExtent.X > SkeletalMeshComponent->Bounds.BoxExtent.Y)
  669.         {
  670.             View.ViewMatrix = FTranslationMatrix(-(SkeletalMeshComponent->Bounds.Origin - FVector(0,SkeletalMeshComponent->Bounds.SphereRadius / (75.0f * (FLOAT)PI / 360.0f),0)));
  671.             View.ViewMatrix = View.ViewMatrix * FInverseRotationMatrix(FRotator(0,16384,0));
  672.         }
  673.         else
  674.         {
  675.             View.ViewMatrix = FTranslationMatrix(-(SkeletalMeshComponent->Bounds.Origin - FVector(-SkeletalMeshComponent->Bounds.SphereRadius / (75.0f * (FLOAT)PI / 360.0f),0,0)));
  676.             View.ViewMatrix = View.ViewMatrix * FInverseRotationMatrix(FRotator(0,32768,0));
  677.         }
  678.  
  679.         View.ViewMatrix = View.ViewMatrix * FMatrix(
  680.             FPlane(0,   010),
  681.             FPlane(1,   000),
  682.             FPlane(0,   100),
  683.             FPlane(0,   001));
  684.         View.ProjectionMatrix = FPerspectiveMatrix(
  685.             75.0f * (FLOAT)PI / 360.0f,
  686.             1.0f,
  687.             1.0f,
  688.             NEAR_CLIPPING_PLANE
  689.             );
  690.         View.ShowFlags = SHOW_DefaultEditor;
  691.         View.BackgroundColor = FColor(0,0,0);
  692.     }
  693. };
  694.  
  695. FString USkeletalMesh::GetDesc()
  696. {
  697.     check(LODModels.Num());
  698.     LODModels(0).Faces.Load();
  699.     return FString::Printf( TEXT("%d Polys, %d Bones"), LODModels(0).Faces.Num(), RefSkeleton.Num() );
  700. }
  701.  
  702. void USkeletalMesh::DrawThumbnail( EThumbnailPrimType InPrimType, INT InX, INT InY, struct FChildViewport* InViewport, struct FRenderInterface* InRI, FLOAT InZoom, UBOOL InShowBackground, FLOAT InZoomPct, INT InFixedSz )
  703. {
  704.     FSkeletalMeshThumbnailScene ThumbnailScene(this);
  705.  
  706.     InRI->DrawScene(
  707.         FSceneContext(
  708.             &ThumbnailScene.View,
  709.             &ThumbnailScene,
  710.             InX,
  711.             InY,
  712.             InFixedSz ? InFixedSz : 1024 * InZoom,
  713.             InFixedSz ? InFixedSz : 1024 * InZoom
  714.             )
  715.         );
  716.  
  717. }
  718.  
  719. FThumbnailDesc USkeletalMesh::GetThumbnailDesc( FRenderInterface* InRI, FLOAT InZoom, INT InFixedSz )
  720. {
  721.     FThumbnailDesc td;
  722.  
  723.     td.Width = InFixedSz ? InFixedSz : 1024*InZoom;
  724.     td.Height = InFixedSz ? InFixedSz : 1024*InZoom;
  725.     return td;
  726.  
  727. }
  728.  
  729. INT USkeletalMesh::GetThumbnailLabels( TArray<FString>* InLabels )
  730. {
  731.     InLabels->Empty();
  732.  
  733.     new( *InLabels )FString( GetName() );
  734.  
  735.     check(LODModels.Num());
  736.     LODModels(0).Faces.Load();
  737.     new( *InLabels )FString( FString::Printf( TEXT("%d Polys, %d Bones"), LODModels(0).Faces.Num(), RefSkeleton.Num() ) );
  738.  
  739.     return InLabels->Num();
  740. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top