private bool LoadTextureIndicesChunk() { PrimitiveState primitiveState = m_primitiveStates[m_currentPrimitiveStateIndex]; primitiveState.TextureIndexCount = m_chunkReader.ReadInt(); primitiveState.TextureIndices = new int[primitiveState.TextureIndexCount]; for (int k = 0; k < primitiveState.TextureIndexCount; k++) { primitiveState.TextureIndices[k] = m_chunkReader.ReadInt(); } return(true); }
protected internal virtual void copy(PrimitiveState from) { p1x = from.p1x; p1y = from.p1y; p1z = from.p1z; p1w = from.p1w; p1wInverted = from.p1wInverted; p2x = from.p2x; p2y = from.p2y; p2z = from.p2z; p2w = from.p2w; p2wInverted = from.p2wInverted; p3x = from.p3x; p3y = from.p3y; p3z = from.p3z; p3w = from.p3w; p3wInverted = from.p3wInverted; pxMin = from.pxMin; pxMax = from.pxMax; pyMin = from.pyMin; pyMax = from.pyMax; pzMin = from.pzMin; pzMax = from.pzMax; t1u = from.t1u; t1v = from.t1v; t2u = from.t2u; t2v = from.t2v; t3u = from.t3u; t3v = from.t3v; tuMin = from.tuMin; tuMax = from.tuMax; tvMin = from.tvMin; tvMax = from.tvMax; uStart = from.uStart; uStep = from.uStep; vStart = from.vStart; vStep = from.vStep; destinationWidth = from.destinationWidth; destinationHeight = from.destinationHeight; diff13x = from.diff13x; diff13y = from.diff13y; diff32x = from.diff32x; diff23y = from.diff23y; denomInverted = from.denomInverted; }
private bool LoadPrimitiveStateChunk() { var primitiveState = new PrimitiveState(); m_currentPrimitiveStateIndex = m_primitiveStates.Count; m_primitiveStates.Add(primitiveState); primitiveState.Flags = m_chunkReader.ReadInt(); primitiveState.ShaderIndex = m_chunkReader.ReadInt(); // Console.WriteLine("ShaderIndex = " + primitiveState.ShaderIndex); LoadChunk(); primitiveState.Zbias = m_chunkReader.ReadInt(); primitiveState.VertexStateIndex = m_chunkReader.ReadInt(); primitiveState.AlphaTestMode = m_chunkReader.ReadInt(); primitiveState.LightConfigurationIndex = m_chunkReader.ReadInt(); primitiveState.ZBufferMode = m_chunkReader.ReadInt(); // Tell loadchunk not to read the end of the chunk return(true); }
private static void ParseBlock(Block block, ref MsTsShape shape, ref Vertex vertex, ref int[] intArray) { float x, y, z; Vector3 point; KujuTokenID currentToken = KujuTokenID.error; Block newBlock; uint flags; switch (block.Token) { case KujuTokenID.shape: newBlock = block.ReadSubBlock(KujuTokenID.shape_header); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.volumes); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.shader_names); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.texture_filter_names); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.points); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.uv_points); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.normals); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.sort_vectors); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.colours); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.matrices); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.images); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.textures); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.light_materials); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.light_model_cfgs); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.vtx_states); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.prim_states); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.lod_controls); ParseBlock(newBlock, ref shape); break; case KujuTokenID.shape_header: case KujuTokenID.volumes: case KujuTokenID.texture_filter_names: case KujuTokenID.sort_vectors: case KujuTokenID.colours: case KujuTokenID.light_materials: case KujuTokenID.light_model_cfgs: //Unsupported stuff, so just read to the end at the minute block.Skip((int)block.Length()); break; case KujuTokenID.vtx_state: flags = block.ReadUInt32(); int matrix1 = block.ReadInt32(); int lightMaterialIdx = block.ReadInt32(); int lightStateCfgIdx = block.ReadInt32(); uint lightFlags = block.ReadUInt32(); int matrix2 = -1; if ((block is BinaryBlock && block.Length() - block.Position() > 1) || (!(block is BinaryBlock) && block.Length() - block.Position() > 2)) { matrix2 = block.ReadInt32(); } VertexStates vs = new VertexStates(); vs.flags = flags; vs.hierarchyID = matrix1; vs.lightingMatrixID = lightMaterialIdx; vs.lightingConfigIdx = lightStateCfgIdx; vs.lightingFlags = lightFlags; vs.matrix2ID = matrix2; shape.vtx_states.Add(vs); break; case KujuTokenID.vtx_states: int vtxStateCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (vtxStateCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.vtx_state); ParseBlock(newBlock, ref shape); vtxStateCount--; } break; case KujuTokenID.prim_state: flags = block.ReadUInt32(); int shader = block.ReadInt32(); int[] texIdxs = {}; newBlock = block.ReadSubBlock(KujuTokenID.tex_idxs); ParseBlock(newBlock, ref shape, ref texIdxs); float zBias = block.ReadSingle(); int vertexStates = block.ReadInt32(); int alphaTestMode = block.ReadInt32(); int lightCfgIdx = block.ReadInt32(); int zBufferMode = block.ReadInt32(); PrimitiveState p = new PrimitiveState(); p.Name = block.Label; p.Flags = flags; p.Shader = shader; p.Textures = texIdxs; p.ZBias = zBias; p.vertexStates = vertexStates; p.alphaTestMode = alphaTestMode; p.lightCfgIdx = lightCfgIdx; p.zBufferMode = zBufferMode; shape.prim_states.Add(p); break; case KujuTokenID.tex_idxs: int texIdxCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } Array.Resize(ref intArray, texIdxCount); int idx = 0; while (texIdxCount > 0) { intArray[idx] = block.ReadUInt16(); idx++; texIdxCount--; } break; case KujuTokenID.prim_states: int primStateCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (primStateCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.prim_state); ParseBlock(newBlock, ref shape); primStateCount--; } break; case KujuTokenID.texture: int imageIDX = block.ReadInt32(); int filterMode = (int)block.ReadUInt32(); float mipmapLODBias = block.ReadSingle(); uint borderColor = 0xff000000U; if (block.Length() - block.Position() > 1) { borderColor = block.ReadUInt32(); } //Unpack border color float r, g, b, a; r = borderColor % 256; g = (borderColor / 256) % 256; b = (borderColor / 256 / 256) % 256; a = (borderColor / 256 / 256 / 256) % 256; Texture t = new Texture(); t.fileName = shape.images[imageIDX]; t.filterMode = filterMode; t.mipmapLODBias = (int)mipmapLODBias; t.borderColor = new Color32((byte)r, (byte)g, (byte)b, (byte)a); shape.textures.Add(t); break; case KujuTokenID.textures: int textureCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (textureCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.texture); ParseBlock(newBlock, ref shape); textureCount--; } break; case KujuTokenID.image: shape.images.Add(block.ReadString()); break; case KujuTokenID.images: int imageCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (imageCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.image); ParseBlock(newBlock, ref shape); imageCount--; } break; case KujuTokenID.cullable_prims: int numPrims = block.ReadInt32(); int numFlatSections = block.ReadInt32(); int numPrimIdxs = block.ReadInt32(); break; case KujuTokenID.geometry_info: int faceNormals = block.ReadInt32(); int txLightCommands = block.ReadInt32(); int nodeXTrilistIdxs = block.ReadInt32(); int trilistIdxs = block.ReadInt32(); int lineListIdxs = block.ReadInt32(); nodeXTrilistIdxs = block.ReadInt32(); //Duped, or is the first one actually something else? int trilists = block.ReadInt32(); int lineLists = block.ReadInt32(); int pointLists = block.ReadInt32(); int nodeXTrilists = block.ReadInt32(); newBlock = block.ReadSubBlock(KujuTokenID.geometry_nodes); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.geometry_node_map); ParseBlock(newBlock, ref shape); break; case KujuTokenID.geometry_node_map: int[] geometryNodes = new int[block.ReadInt32()]; for (int i = 0; i < geometryNodes.Length; i++) { geometryNodes[i] = block.ReadInt32(); } break; case KujuTokenID.geometry_node: int n_txLightCommands = block.ReadInt32(); int n_nodeXTxLightCmds = block.ReadInt32(); int n_trilists = block.ReadInt32(); int n_lineLists = block.ReadInt32(); int n_pointLists = block.ReadInt32(); newBlock = block.ReadSubBlock(KujuTokenID.cullable_prims); ParseBlock(newBlock, ref shape); break; case KujuTokenID.geometry_nodes: int geometryNodeCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (geometryNodeCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.geometry_node); ParseBlock(newBlock, ref shape); geometryNodeCount--; } break; case KujuTokenID.point: x = block.ReadSingle(); y = block.ReadSingle(); z = block.ReadSingle(); point = new Vector3(x, y, z); shape.points.Add(point); break; case KujuTokenID.vector: x = block.ReadSingle(); y = block.ReadSingle(); z = block.ReadSingle(); point = new Vector3(x, y, z); shape.normals.Add(point); break; case KujuTokenID.points: int pointCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (pointCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.point); ParseBlock(newBlock, ref shape); pointCount--; } break; case KujuTokenID.uv_point: x = block.ReadSingle(); y = block.ReadSingle(); var uv_point = new Vector2(x, y); shape.uv_points.Add(uv_point); break; case KujuTokenID.uv_points: int uvPointCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (uvPointCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.uv_point); ParseBlock(newBlock, ref shape); uvPointCount--; } break; case KujuTokenID.matrices: int matrixCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (matrixCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.matrix); ParseBlock(newBlock, ref shape); matrixCount--; } break; case KujuTokenID.matrix: Matrix currentMatrix = new Matrix(); currentMatrix.Name = block.Label; currentMatrix.A = new Vector3(block.ReadSingle(), block.ReadSingle(), block.ReadSingle()); currentMatrix.B = new Vector3(block.ReadSingle(), block.ReadSingle(), block.ReadSingle()); currentMatrix.C = new Vector3(block.ReadSingle(), block.ReadSingle(), block.ReadSingle()); currentMatrix.D = new Vector3(block.ReadSingle(), block.ReadSingle(), block.ReadSingle()); shape.matrices.Add(currentMatrix); break; case KujuTokenID.normals: int normalCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (normalCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.vector); ParseBlock(newBlock, ref shape); normalCount--; } break; case KujuTokenID.distance_levels_header: int DLevBias = block.ReadInt16(); break; case KujuTokenID.distance_levels: int distanceLevelCount = block.ReadInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (distanceLevelCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.distance_level); ParseBlock(newBlock, ref shape); distanceLevelCount--; } break; case KujuTokenID.distance_level_header: newBlock = block.ReadSubBlock(KujuTokenID.dlevel_selection); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.hierarchy); ParseBlock(newBlock, ref shape); break; case KujuTokenID.distance_level: newBlock = block.ReadSubBlock(KujuTokenID.distance_level_header); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.sub_objects); ParseBlock(newBlock, ref shape); shape.LODs.Add(currentLOD); break; case KujuTokenID.dlevel_selection: currentLOD = new LOD(block.ReadSingle()); break; case KujuTokenID.hierarchy: currentLOD.hierarchy = new int[block.ReadInt32()]; for (int i = 0; i < currentLOD.hierarchy.Length; i++) { currentLOD.hierarchy[i] = block.ReadInt32(); } break; case KujuTokenID.lod_control: newBlock = block.ReadSubBlock(KujuTokenID.distance_levels_header); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.distance_levels); ParseBlock(newBlock, ref shape); break; case KujuTokenID.lod_controls: int lodCount = block.ReadInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (lodCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.lod_control); ParseBlock(newBlock, ref shape); lodCount--; } break; case KujuTokenID.primitives: int capacity = block.ReadInt32(); //Count of the number of entries in the block, not the number of primitives while (capacity > 0) { newBlock = block.ReadSubBlock(new KujuTokenID[] { KujuTokenID.prim_state_idx, KujuTokenID.indexed_trilist }); switch (newBlock.Token) { case KujuTokenID.prim_state_idx: ParseBlock(newBlock, ref shape); string txF = null; try { txF = OpenBveApi.Path.CombineFile(currentFolder, shape.textures[shape.prim_states[shape.currentPrimitiveState].Textures[0]].fileName); if (!File.Exists(txF)) { Interface.AddMessage(MessageType.Warning, true, "Texture file " + shape.textures[shape.prim_states[shape.currentPrimitiveState].Textures[0]].fileName + " was not found."); txF = null; } } catch { Interface.AddMessage(MessageType.Warning, true, "Texture file path " + shape.textures[shape.prim_states[shape.currentPrimitiveState].Textures[0]].fileName + " was invalid."); } currentLOD.subObjects[currentLOD.subObjects.Count - 1].materials.Add(new Material(txF)); break; case KujuTokenID.indexed_trilist: ParseBlock(newBlock, ref shape); break; default: throw new Exception("Unexpected primitive type, got " + currentToken); } capacity--; } break; case KujuTokenID.prim_state_idx: shape.currentPrimitiveState = block.ReadInt32(); break; case KujuTokenID.indexed_trilist: newBlock = block.ReadSubBlock(KujuTokenID.vertex_idxs); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.normal_idxs); ParseBlock(newBlock, ref shape); break; case KujuTokenID.sub_object: newBlock = block.ReadSubBlock(KujuTokenID.sub_object_header); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.vertices); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.vertex_sets); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.primitives); ParseBlock(newBlock, ref shape); break; case KujuTokenID.sub_objects: int subObjectCount = block.ReadInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (subObjectCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.sub_object); ParseBlock(newBlock, ref shape); subObjectCount--; } break; case KujuTokenID.sub_object_header: currentLOD.subObjects.Add(new SubObject()); shape.totalObjects++; flags = block.ReadUInt32(); int sortVectorIdx = block.ReadInt32(); int volIdx = block.ReadInt32(); uint sourceVertexFormatFlags = block.ReadUInt32(); uint destinationVertexFormatFlags = block.ReadUInt32(); newBlock = block.ReadSubBlock(KujuTokenID.geometry_info); ParseBlock(newBlock, ref shape); /* * Optional stuff, need to check if we're running off the end of the stream before reading each block */ if (block.Length() - block.Position() > 1) { newBlock = block.ReadSubBlock(KujuTokenID.subobject_shaders); ParseBlock(newBlock, ref shape); } if (block.Length() - block.Position() > 1) { newBlock = block.ReadSubBlock(KujuTokenID.subobject_light_cfgs); ParseBlock(newBlock, ref shape); } if (block.Length() - block.Position() > 1) { int subObjectID = block.ReadInt32(); } break; case KujuTokenID.subobject_light_cfgs: int[] subobject_light_cfgs = new int[block.ReadInt32()]; for (int i = 0; i < subobject_light_cfgs.Length; i++) { subobject_light_cfgs[i] = block.ReadInt32(); } break; case KujuTokenID.subobject_shaders: int[] subobject_shaders = new int[block.ReadInt32()]; for (int i = 0; i < subobject_shaders.Length; i++) { subobject_shaders[i] = block.ReadInt32(); } break; case KujuTokenID.vertices: int vertexCount = block.ReadInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (vertexCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.vertex); ParseBlock(newBlock, ref shape); vertexCount--; } break; case KujuTokenID.vertex: flags = block.ReadUInt32(); //Various control variables, not supported int myPoint = block.ReadInt32(); //Index to points array int myNormal = block.ReadInt32(); //Index to normals array Vertex v = new Vertex(shape.points[myPoint], shape.normals[myNormal]); uint Color1 = block.ReadUInt32(); uint Color2 = block.ReadUInt32(); newBlock = block.ReadSubBlock(KujuTokenID.vertex_uvs); ParseBlock(newBlock, ref shape, ref v); currentLOD.subObjects[currentLOD.subObjects.Count - 1].verticies.Add(v); break; case KujuTokenID.vertex_idxs: int remainingVertex = block.ReadInt32() / 3; while (remainingVertex > 0) { int v1 = block.ReadInt32(); int v2 = block.ReadInt32(); int v3 = block.ReadInt32(); currentLOD.subObjects[currentLOD.subObjects.Count - 1].faces.Add(new Face(new int[] { v1, v2, v3 }, currentLOD.subObjects[currentLOD.subObjects.Count - 1].materials.Count - 1)); remainingVertex--; } break; case KujuTokenID.vertex_set: int vertexStateIndex = block.ReadInt32(); //Index to the vtx_states member int hierarchy = shape.vtx_states[vertexStateIndex].hierarchyID; //Now pull the hierachy ID out int setStartVertexIndex = block.ReadInt32(); //First vertex int setVertexCount = block.ReadInt32(); //Total number of vert VertexSet vts = new VertexSet(); vts.hierarchyIndex = hierarchy; vts.startVertex = setStartVertexIndex; vts.numVerticies = setVertexCount; currentLOD.subObjects[currentLOD.subObjects.Count - 1].vertexSets.Add(vts); break; case KujuTokenID.vertex_sets: int vertexSetCount = block.ReadInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (vertexSetCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.vertex_set); ParseBlock(newBlock, ref shape); vertexSetCount--; } //We now need to transform our verticies currentLOD.subObjects[currentLOD.subObjects.Count - 1].TransformVerticies(shape.matrices); break; case KujuTokenID.vertex_uvs: int[] vertex_uvs = new int[block.ReadInt32()]; for (int i = 0; i < vertex_uvs.Length; i++) { vertex_uvs[i] = block.ReadInt32(); } //Looks as if vertex_uvs should always be of length 1, thus: vertex.TextureCoordinates = shape.uv_points[vertex_uvs[0]]; break; } }
private bool LoadIndexedTrilistChunk() { m_geometryVertexIndices.Clear(); LoadChildChunks(); if (m_currentDistanceLevelIndex == 0) { // Each indexed trilist becomes a geometry node // We only add the vertices that are actually used in this geometry node. // This also means that the indices must be renumbered. int uniqueIndexCount = 0; var indexRenumbering = new Dictionary <int, int>(); var usedVertexIndices = new List <int>(); for (int indexIndex = 0; indexIndex < m_geometryVertexIndices.Count; indexIndex++) { int index = m_geometryVertexIndices[indexIndex]; if (!indexRenumbering.ContainsKey(index)) { indexRenumbering.Add(index, uniqueIndexCount); // original index, renumbered index usedVertexIndices.Add(index); uniqueIndexCount++; } } Debug.Assert(m_geometryVertexUVs.Count <= 2); int vertexCount = uniqueIndexCount; var positions = new Vector3[vertexCount]; var normals = new Vector3[vertexCount]; var uv1 = m_geometryVertexUVs.Count >= 1 ? new Vector2[vertexCount] : null; var uv2 = m_geometryVertexUVs.Count == 2 ? new Vector2[vertexCount] : null; for (int vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) { int sourceVertexIndex = usedVertexIndices[vertexIndex]; positions[vertexIndex] = m_geometryVertexPositions[sourceVertexIndex]; normals[vertexIndex] = m_geometryVertexNormals[sourceVertexIndex]; if (m_geometryVertexUVs.Count == 1) { uv1[vertexIndex] = new Vector2(m_geometryVertexUVs[0][sourceVertexIndex].x, 1 - m_geometryVertexUVs[0][sourceVertexIndex].y); } else if (m_geometryVertexUVs.Count == 2) { uv2[vertexIndex] = new Vector2(m_geometryVertexUVs[1][sourceVertexIndex].x, 1 - m_geometryVertexUVs[1][sourceVertexIndex].y); } } var indices = new int[m_geometryVertexIndices.Count]; int triangleCount = m_geometryVertexIndices.Count / 3; for (int triangleIndex = 0; triangleIndex < triangleCount; triangleIndex++) { indices[3 * triangleIndex + 0] = indexRenumbering[m_geometryVertexIndices[3 * triangleIndex + 0]]; indices[3 * triangleIndex + 1] = indexRenumbering[m_geometryVertexIndices[3 * triangleIndex + 1]]; indices[3 * triangleIndex + 2] = indexRenumbering[m_geometryVertexIndices[3 * triangleIndex + 2]]; } PrimitiveState primitiveState = m_primitiveStates[m_currentPrimitiveStateIndex]; VertexState vertexState = m_vertexStates[primitiveState.VertexStateIndex]; var gameObject = m_gameObjects[vertexState.MatrixIndex]; var mesh = new Mesh { name = gameObject.name, vertices = positions, normals = normals, triangles = indices, uv = uv1, // uv2 = uv2 }; if (gameObject.GetComponent <MeshFilter>() != null) { gameObject = new GameObject(gameObject.name); AddChildToGameObject(vertexState.MatrixIndex, gameObject.transform); } var meshFilter = gameObject.AddComponent <MeshFilter>(); meshFilter.mesh = mesh; var meshRenderer = gameObject.AddComponent <MeshRenderer>(); Debug.Assert(primitiveState.TextureIndexCount == 1); meshRenderer.sharedMaterial = m_materials[primitiveState.TextureIndices[0]]; } return(false); }
private void AddPolygon(PrimitiveState state, ObjModel objModel, Polygon poly) { var v1 = poly.Vertices[0]; var v2 = poly.Vertices[1]; var v3 = poly.Vertices[2]; var v1Index = (int)(v1.V - 1); var v2Index = (int)(v2.V - 1); var v3Index = (int)(v3.V - 1); var v1v = objModel.Positions[v1Index]; var v2v = objModel.Positions[v2Index]; var v3v = objModel.Positions[v3Index]; UpdateMinMax(state.VertexXMM, v1v.X, v2v.X, v3v.X); UpdateMinMax(state.VertexYMM, v1v.Y, v2v.Y, v3v.Y); UpdateMinMax(state.VertexZMM, v1v.Z, v2v.Z, v3v.Z); var hasNormal = v1.VN.HasValue; var hasUV = v1.VT.HasValue; Normal n1, n2, n3; if (hasNormal) { var n1Index = (int)(v1.VN.Value - 1); var n2Index = (int)(v2.VN.Value - 1); var n3Index = (int)(v3.VN.Value - 1); n1 = objModel.Normals[n1Index]; n2 = objModel.Normals[n2Index]; n3 = objModel.Normals[n3Index]; UpdateMinMax(state.NormalXMM, n1.X, n2.X, n3.X); UpdateMinMax(state.NormalYMM, n1.Y, n2.Y, n3.Y); UpdateMinMax(state.NormalZMM, n1.Z, n2.Z, n3.Z); } else { n1 = new Normal(); n2 = n1; n3 = n1; } Uv t1, t2, t3; if (hasUV) { var t1Index = (int)(v1.VT.Value - 1); var t2Index = (int)(v2.VT.Value - 1); var t3Index = (int)(v3.VT.Value - 1); t1 = objModel.TextureCoords[t1Index]; t2 = objModel.TextureCoords[t2Index]; t3 = objModel.TextureCoords[t3Index]; UpdateMinMax(state.UvUMM, t1.U, t2.U, t3.U); UpdateMinMax(state.UvVMM, 1 - t1.V, 1 - t2.V, 1 - t3.V); } else { t1 = new Uv(); t2 = t1; t3 = t1; } if (state.AddVertex(v1)) { state.VertexCount++; FillBytes(state.VertexBuffers, v1v.ToArray()); if (hasNormal) { state.NormalCount++; FillBytes(state.NormalBuffers, n1.ToArray()); } if (hasUV) { state.UvCount++; FillBytes(state.TextureBuffers, new Uv(t1.U, 1 - t1.V).ToArray()); } } if (state.AddVertex(v2)) { state.VertexCount++; FillBytes(state.VertexBuffers, v2v.ToArray()); if (hasNormal) { state.NormalCount++; FillBytes(state.NormalBuffers, n2.ToArray()); } if (hasUV) { state.UvCount++; FillBytes(state.TextureBuffers, new Uv(t2.U, 1 - t2.V).ToArray()); } } if (state.AddVertex(v3)) { state.VertexCount++; FillBytes(state.VertexBuffers, v3v.ToArray()); if (hasNormal) { state.NormalCount++; FillBytes(state.NormalBuffers, n3.ToArray()); } if (hasUV) { state.UvCount++; FillBytes(state.TextureBuffers, new Uv(t3.U, 1 - t3.V).ToArray()); } } var correctWinding = CheckWindingCorrect(v1v, v2v, v3v, n1); if (correctWinding) { state.Indices.AddRange(new[] { state.PolyVertexCache[v1], state.PolyVertexCache[v2], state.PolyVertexCache[v3] }); } else { state.Indices.AddRange(new[] { state.PolyVertexCache[v1], state.PolyVertexCache[v3], state.PolyVertexCache[v2] }); } }
private void AddNodes(Model model, ObjModel objModel) { var u32Indices = RequiresU32Indices(objModel); var scene = new Scene(); model.Scenes.Add(scene); var nodeName = objModel.Name; if (String.IsNullOrEmpty(nodeName)) { nodeName = "default"; } var node = new Node { Name = nodeName }; model.Nodes.Add(node); scene.Nodes.Add(0); var polyMatDict = GetPolygonMatDict(objModel); foreach (var gd in objModel.GetGroups()) { var key = gd.Key; var g = gd.Value; var mesh = new Mesh { Name = key }; var faceList = new SortedList <int, List <int> >(); foreach (var pp in g.Polygons) { for (var i = pp.Start; i < pp.End; i++) { var pIndex = (int)i; var matName = polyMatDict[pIndex]; var matId = _matDict[matName]; if (!faceList.ContainsKey(matId)) { faceList.Add(matId, new List <int>()); } faceList[matId].Add(pIndex); } } var faceIndex = 0; foreach (var fd in faceList) { var matIndex = fd.Key; var polygons = fd.Value; string faceName; if (faceIndex > 0) { faceName = key + "_" + faceIndex; } else { faceName = key; } var p = new Primitive { Material = matIndex, Mode = new CheckedValue <Mode, int>(Mode.Triangles) }; p.Attributes = new Dictionary <Semantic, int>(); var state = new PrimitiveState(); foreach (var pIndex in polygons) { var poly = objModel.Polygons[pIndex]; if (poly.Vertices.Count == 3) { AddPolygon(state, objModel, poly); } else if (poly.Vertices.Count == 4) { var v1 = poly.Vertices[0]; var v2 = poly.Vertices[1]; var v3 = poly.Vertices[2]; var v4 = poly.Vertices[3]; var p1 = new Polygon(); p1.Vertices.AddRange(new[] { v1, v2, v3 }); AddPolygon(state, objModel, p1); var p2 = new Polygon(); p2.Vertices.AddRange(new[] { v1, v3, v4 }); AddPolygon(state, objModel, p2); } else if (poly.Vertices.Count > 4) { //TODO: var polys = SplitPolygons(poly, objModel); foreach (var pp in polys) { AddPolygon(state, objModel, pp); } } } // Accessors // Position Accessors var accessorIndex = model.Accessors.Count; var accessorVertex = new Accessor { Min = new float[] { state.VertexXMM.Min, state.VertexYMM.Min, state.VertexZMM.Min }, Max = new float[] { state.VertexXMM.Max, state.VertexYMM.Max, state.VertexZMM.Max }, AccessorType = new CheckedValue <AccessorType, string>(AccessorType.VEC3), Count = state.VertexCount, ComponentType = new CheckedValue <ComponentType, int>(ComponentType.F32) }; p.Attributes.Add(Semantic.POSITION, accessorIndex); model.Accessors.Add(accessorVertex); _buffers.Positions.Add(state.VertexBuffers); _buffers.PositionAccessors.Add(accessorIndex); // Normal Accessors if (state.NormalCount > 0) { accessorIndex = model.Accessors.Count; var accessorNormal = new Accessor { Min = new float[] { state.NormalXMM.Min, state.NormalYMM.Min, state.NormalZMM.Min }, Max = new float[] { state.NormalXMM.Max, state.NormalYMM.Max, state.NormalZMM.Max }, AccessorType = new CheckedValue <AccessorType, string>(AccessorType.VEC3), Count = state.NormalCount, ComponentType = new CheckedValue <ComponentType, int>(ComponentType.F32) }; p.Attributes.Add(Semantic.NORMAL, accessorIndex); model.Accessors.Add(accessorNormal); _buffers.Normals.Add(state.NormalBuffers); _buffers.NormalAccessors.Add(accessorIndex); } // UV Accessors if (state.UvCount > 0) { accessorIndex = model.Accessors.Count; var accessorUV = new Accessor { Min = new float[] { state.UvUMM.Min, state.UvVMM.Min }, Max = new float[] { state.UvUMM.Max, state.UvVMM.Max }, AccessorType = new CheckedValue <AccessorType, string>(AccessorType.VEC2), ComponentType = new CheckedValue <ComponentType, int>(ComponentType.F32), Count = state.UvCount }; p.Attributes.Add(Semantic.TEXCOORD_0, accessorIndex); model.Accessors.Add(accessorUV); _buffers.Uvs.Add(state.TextureBuffers); _buffers.UvAccessors.Add(accessorIndex); } else { model.Materials[matIndex].PbrMetallicRoughness.BaseColorTexture = null; } // Index Accessors accessorIndex = model.Accessors.Count; var componentType = u32Indices ? ComponentType.U32 : ComponentType.U16; var mm = new MinMax(); UpdateMinMax(mm, state.Indices); var accessor = new Accessor { Min = new float[] { mm.Min }, Max = new float[] { mm.Max }, AccessorType = new CheckedValue <AccessorType, string>(AccessorType.SCALAR), ComponentType = new CheckedValue <ComponentType, int>(componentType), Count = state.Indices.Count }; model.Accessors.Add(accessor); _buffers.Indices.Add(GetBytes(state.Indices, u32Indices)); _buffers.IndexAccessors.Add(accessorIndex); p.Indices = accessorIndex; mesh.Primitives.Add(p); } var meshIndex = model.Meshes.Count; model.Meshes.Add(mesh); var nodeIndex = model.Nodes.Count; var cNode = new Node { Name = key, Mesh = meshIndex }; model.Nodes.Add(cNode); node.Children.Add(nodeIndex); } AddBuffers(model); }