private static IGeometry ConvertDisplayGeometry(Assimp.Node curAiNode, Assimp.Matrix4x4 nodeWorldTransform, List <Assimp.Mesh> aiMeshes, List <MaterialBuildInfo> materialBuildInfos) { var nodeInverseWorldTransform = nodeWorldTransform; nodeInverseWorldTransform.Inverse(); var nodeInverseTransposeWorldTransform = nodeInverseWorldTransform; nodeInverseTransposeWorldTransform.Transpose(); var geometry = new Geometry(); // Convert meshes var vertexPositions = new List <Assimp.Vector3D>(); var vertexNormals = new List <Assimp.Vector3D>(); var vertexUVs = new List <Assimp.Vector3D>(); var vertexColors = new List <Assimp.Color4D>(); var lastRenderState = new MeshRenderState(); foreach (var aiMeshIndex in curAiNode.MeshIndices) { var aiMesh = aiMeshes[aiMeshIndex]; var material = materialBuildInfos[aiMesh.MaterialIndex]; var mesh = new Mesh(); var renderState = new MeshRenderState(); renderState.IndexFlags = IndexAttributeFlags.HasPosition; var useColors = false; var hasColors = aiMesh.HasVertexColors(0); var hasUVs = aiMesh.HasTextureCoords(0); var hasNormals = aiMesh.HasNormals; if (hasColors || !hasNormals) { renderState.IndexFlags |= IndexAttributeFlags.HasColor; useColors = true; } else { renderState.IndexFlags |= IndexAttributeFlags.HasNormal; } if (hasUVs) { renderState.IndexFlags |= IndexAttributeFlags.HasUV; } // Convert faces var triangleIndices = new Index[aiMesh.FaceCount * 3]; for (var i = 0; i < aiMesh.Faces.Count; i++) { var aiFace = aiMesh.Faces[i]; for (var j = 0; j < 3; j++) { var triangleIndicesIndex = (i * 3) + 2 - j; if (j >= aiFace.IndexCount) { triangleIndices[triangleIndicesIndex] = triangleIndices[triangleIndicesIndex + 1]; continue; } int aiFaceIndex = aiFace.Indices[j]; var position = aiMesh.Vertices[aiFaceIndex]; var positionIndex = vertexPositions.AddUnique(position); if (positionIndex > byte.MaxValue) { renderState.IndexFlags |= IndexAttributeFlags.Position16BitIndex; } var normalIndex = 0; var colorIndex = 0; var uvIndex = 0; if (useColors) { var color = hasColors ? aiMesh.VertexColorChannels[0][aiFaceIndex] : new Assimp.Color4D(); colorIndex = vertexColors.AddUnique(color); if (colorIndex > byte.MaxValue) { renderState.IndexFlags |= IndexAttributeFlags.Color16BitIndex; } } else { var normal = aiMesh.Normals[aiFaceIndex]; normalIndex = vertexNormals.AddUnique(normal); if (normalIndex > byte.MaxValue) { renderState.IndexFlags |= IndexAttributeFlags.Normal16BitIndex; } } if (hasUVs) { var uv = aiMesh.TextureCoordinateChannels[0][aiFaceIndex]; uvIndex = vertexUVs.AddUnique(uv); if (uvIndex > byte.MaxValue) { renderState.IndexFlags |= IndexAttributeFlags.UV16BitIndex; } } triangleIndices[triangleIndicesIndex] = new Index { PositionIndex = ( ushort )positionIndex, NormalIndex = ( ushort )normalIndex, ColorIndex = ( ushort )colorIndex, UVIndex = ( ushort )uvIndex }; } } // Build display list var displayList = new GXDisplayList(GXPrimitive.Triangles, triangleIndices); mesh.DisplayLists.Add(displayList); // Set up render params if (renderState.IndexFlags != lastRenderState.IndexFlags) { mesh.Parameters.Add(new IndexAttributeFlagsParam(renderState.IndexFlags)); } // Set up render lighting params { if (useColors) { renderState.LightingValue1 = 0x0b11; } else { renderState.LightingValue2 = 0x0011; } renderState.LightingValue2 = 1; if (renderState.LightingValue1 != lastRenderState.LightingValue1 || renderState.LightingValue2 != lastRenderState.LightingValue2) { mesh.Parameters.Add(new LightingParams() { Value1 = renderState.LightingValue1, Value2 = renderState.LightingValue2 }); } } // Set up render texture params { renderState.TextureId = ( ushort )material.TextureId; renderState.TileMode = TileMode.WrapU | TileMode.WrapV; if (renderState.TextureId != lastRenderState.TextureId || renderState.TileMode != lastRenderState.TileMode) { mesh.Parameters.Add(new TextureParams(renderState.TextureId, renderState.TileMode)); } } // Set up render mipmap params { renderState.MipMapValue1 = 0x104a; renderState.MipMapValue2 = 0; if (renderState.MipMapValue1 != lastRenderState.MipMapValue1 || renderState.MipMapValue2 != lastRenderState.MipMapValue2) { mesh.Parameters.Add(new MipMapParams { Value1 = renderState.MipMapValue1, Value2 = renderState.MipMapValue2 }); } } //if ( material.UseAlpha ) //{ // mesh.Parameters.Add( new BlendAlphaParam() { Flags = BlendAlphaFlags.UseAlpha } ); // geometry.TranslucentMeshes.Add( mesh ); //} //else //{ // geometry.OpaqueMeshes.Add( mesh ); //} geometry.OpaqueMeshes.Add(mesh); lastRenderState = renderState; } // Build vertex buffers if (vertexPositions.Count > 0) { Debug.Assert(vertexPositions.Count <= ushort.MaxValue); var localVertexPositions = vertexPositions.Select(x => { Assimp.Unmanaged.AssimpLibrary.Instance.TransformVecByMatrix4(ref x, ref nodeWorldTransform); return(AssimpHelper.FromAssimp(x)); }).ToArray(); geometry.VertexBuffers.Add(new VertexPositionBuffer(localVertexPositions)); geometry.Bounds = BoundingSphere.Calculate(localVertexPositions); } if (vertexNormals.Count > 0) { Debug.Assert(vertexNormals.Count <= ushort.MaxValue); geometry.VertexBuffers.Add(new VertexNormalBuffer(vertexNormals.Select(x => { Assimp.Unmanaged.AssimpLibrary.Instance.TransformVecByMatrix4(ref x, ref nodeInverseTransposeWorldTransform); return(AssimpHelper.FromAssimp(x)); }).ToArray())); } if (vertexColors.Count > 0) { Debug.Assert(vertexColors.Count <= ushort.MaxValue); geometry.VertexBuffers.Add(new VertexColorBuffer(vertexColors.Select(AssimpHelper.FromAssimp).ToArray())); } if (vertexUVs.Count > 0) { Debug.Assert(vertexUVs.Count <= ushort.MaxValue); geometry.VertexBuffers.Add(new VertexUVBuffer(vertexUVs.Select(x => UVCodec.Encode255(AssimpHelper .FromAssimpAsVector2(x))) .ToArray())); } return(geometry); }
public StripIndexUVN(ushort index, Vector2 uv) { Index = index; UV = UVCodec.Encode255(uv); }