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); }
private static void AddVertexContainer(GXVertexDecompressor decom, List <IndexedVertexData <MeleeVertex> > vertexContainers, DatPolygon polygon, GXDisplayList displayList) { List <MeleeVertex> vertices = new List <MeleeVertex>(); List <int> vertexIndices = new List <int>(); for (int i = 0; i < displayList.Indices.Length; i++) { vertexIndices.Add(i); } vertices.AddRange(ConvertVerts(decom.GetFormattedVertices(displayList, polygon))); PrimitiveType primitiveType = MeleeDatToOpenGL.GetGLPrimitiveType(displayList.PrimitiveType); var vertexContainer = new IndexedVertexData <MeleeVertex>(vertices, vertexIndices, primitiveType); vertexContainers.Add(vertexContainer); }
private void ParseDOBJs(IHSDNode node, HSD_JOBJ parent, List <HSD_JOBJ> BoneList) { if (node is HSD_JOBJ jobj) { if (jobj.DOBJ != null) { foreach (var child in jobj.DOBJ.List) { ParseDOBJs(child, jobj, BoneList); } } foreach (var child in jobj.Children) { ParseDOBJs(child, child, BoneList); } } if (node is HSD_DOBJ dobj) { Console.WriteLine("DOBJ found"); GenericMesh mesh = new GenericMesh(); mesh.Name = "Mesh_" + outModel.Meshes.Count; GenericMaterial mat = new GenericMaterial(); mesh.MaterialName = "material_" + outModel.MaterialBank.Count; outModel.MaterialBank.Add(mesh.MaterialName, mat); var Xscale = 1; var Yscale = 1; if (dobj.MOBJ != null) { if (dobj.MOBJ.Textures != null) { var tobj = dobj.MOBJ.Textures; mat.SWrap = GXTranslator.toWrapMode(tobj.WrapS); mat.TWrap = GXTranslator.toWrapMode(tobj.WrapT); Xscale = tobj.WScale; Yscale = tobj.HScale; if (!tobjToIndex.ContainsKey(tobj.ImageData.Data)) { Bitmap B = null; if (tobj.ImageData != null) { if (tobj.Tlut != null) { B = TPL.ConvertFromTextureMelee(tobj.ImageData.Data, tobj.ImageData.Width, tobj.ImageData.Height, (int)tobj.ImageData.Format, tobj.Tlut.Data, tobj.Tlut.ColorCount, (int)tobj.Tlut.Format); } else { B = TPL.ConvertFromTextureMelee(tobj.ImageData.Data, tobj.ImageData.Width, tobj.ImageData.Height, (int)tobj.ImageData.Format, null, 0, 0); } } GenericTexture t = new GenericTexture(); t.FromBitmap(B); B.Dispose(); tobjToIndex.Add(tobj.ImageData.Data, outModel.TextureBank.Count); outModel.TextureBank.Add("texture_" + outModel.TextureBank.Count, t); } mat.TextureDiffuse = outModel.TextureBank.Keys.ToArray()[tobjToIndex[tobj.ImageData.Data]]; } } outModel.Meshes.Add(mesh); if (dobj.POBJ != null) { foreach (HSD_POBJ pobj in dobj.POBJ.List) { // Decode the Display List Data GXDisplayList DisplayList = new GXDisplayList(pobj.DisplayListBuffer, pobj.VertexAttributes); var Vertices = ToGenericVertex(VertexAccessor.GetDecodedVertices(pobj), BoneList, pobj.BindGroups != null ? new List <HSD_JOBJWeight>(pobj.BindGroups.Elements) : null, parent); int bufferOffset = 0; foreach (GXPrimitiveGroup g in DisplayList.Primitives) { var primitiveType = GXTranslator.toPrimitiveType(g.PrimitiveType); var strip = new List <GenericVertex>(); for (int i = bufferOffset; i < bufferOffset + g.Count; i++) { strip.Add(Vertices[i]); } bufferOffset += g.Count; switch (primitiveType) { case OpenTK.Graphics.OpenGL.PrimitiveType.TriangleStrip: Tools.TriangleConverter.StripToList(strip, out strip); break; case OpenTK.Graphics.OpenGL.PrimitiveType.Quads: Tools.TriangleConverter.QuadToList(strip, out strip); break; case OpenTK.Graphics.OpenGL.PrimitiveType.Triangles: break; default: Debug.WriteLine("Error converting primitive type " + primitiveType); break; } mesh.Vertices.AddRange(strip); } } } for (int i = 0; i < mesh.Vertices.Count; i++) { var vert = mesh.Vertices[i]; vert.UV0 = new Vector2(vert.UV0.X * Xscale, vert.UV0.Y * Yscale); mesh.Vertices[i] = vert; } mesh.Optimize(); Tools.TriangleConverter.ReverseFaces(mesh.Triangles, out mesh.Triangles); } }