public override VertexStructure BuildStructure(StructureBuildOptions buildOptions) { VertexStructure result = new VertexStructure(); result.CreateOrGetExistingSurface(MaterialProperties.Empty) .BuildCube24V( new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(1f, 1f, 1f), Color4.Transparent); return(result); }
/// <summary> /// Imports the texture node where the xml reader is currently located. /// </summary> /// <param name="inStreamXml">The xml reader object.</param> /// <param name="container">The container where to import to.</param> /// <param name="xglImportOptions">Current import options.</param> private void ImportMesh(XmlReader inStreamXml, ImportedModelContainer container, XglImportOptions xglImportOptions) { string id = inStreamXml.GetAttribute("ID"); VertexStructure actVertexStructure = new VertexStructure(); int minVertexID = int.MaxValue; int actVertexIndex = -1; int actNormalIndex = -1; int actTextureIndex = -1; Vertex actTempVertex = Vertex.Empty; int[] actFaceReferences = new int[3]; Dictionary <int, MaterialProperties> localMaterialInfos = new Dictionary <int, MaterialProperties>(); while (inStreamXml.Read()) { // Ending condition if ((inStreamXml.NodeType == XmlNodeType.EndElement) && (inStreamXml.Name == NODE_NAME_MESH)) { break; } // Continue condition if (inStreamXml.NodeType != XmlNodeType.Element) { continue; } switch (inStreamXml.Name) { case NODE_NAME_SURFACE: // If this tag is present, faces will be visible from both sides. If this flag is absent, faces will be visible from only one side as described in the <F> tag break; case NODE_NAME_MAT: // Read the next material var materialAndID = ImportMaterial(inStreamXml, container, xglImportOptions); localMaterialInfos[materialAndID.Item1] = materialAndID.Item2; break; case NODE_NAME_PATCH: // A patch is a group of faces // We don't need to handle this one break; case NODE_NAME_POINT: // Read next point if (minVertexID == int.MaxValue) { minVertexID = Int32.Parse(inStreamXml.GetAttribute("ID")); } actVertexIndex++; actTempVertex = actVertexStructure.EnsureVertexAt(actVertexIndex); actTempVertex.Color = Color4.White; inStreamXml.Read(); actTempVertex.Position = inStreamXml.ReadContentAsVector3() * xglImportOptions.ResizeFactor; actVertexStructure.Vertices[actVertexIndex] = actTempVertex; break; case NODE_NAME_NORMAL: // Read next normal if (minVertexID == int.MaxValue) { minVertexID = Int32.Parse(inStreamXml.GetAttribute("ID")); } actNormalIndex++; actTempVertex = actVertexStructure.EnsureVertexAt(actNormalIndex); inStreamXml.Read(); actTempVertex.Normal = inStreamXml.ReadContentAsVector3(); actVertexStructure.Vertices[actNormalIndex] = actTempVertex; break; case NODE_NAME_TC: // Read next texture coordinate if (minVertexID == int.MaxValue) { minVertexID = Int32.Parse(inStreamXml.GetAttribute("ID")); } actTextureIndex++; actTempVertex = actVertexStructure.EnsureVertexAt(actTextureIndex); inStreamXml.Read(); actTempVertex.TexCoord = inStreamXml.ReadContentAsVector2(); actVertexStructure.Vertices[actTextureIndex] = actTempVertex; break; case NODE_NAME_FACE: // Read next face actFaceReferences[0] = 0; actFaceReferences[1] = 0; actFaceReferences[2] = 0; int loopFacePoint = 0; int referencedMat = -1; int referencedTexture = -1; while (inStreamXml.Read()) { // Ending condition if ((inStreamXml.NodeType == XmlNodeType.EndElement) && (inStreamXml.Name == NODE_NAME_FACE)) { break; } if (inStreamXml.NodeType != XmlNodeType.Element) { continue; } // Read next face index if (inStreamXml.Name == NODE_NAME_FACE_MATERIAL_REF) { inStreamXml.Read(); referencedMat = inStreamXml.ReadContentAsInt(); } else if (inStreamXml.Name == NODE_NAME_FACE_TEXTUREREF_REF) { inStreamXml.Read(); referencedTexture = inStreamXml.ReadContentAsInt(); } else if (inStreamXml.Name == NODE_NAME_FACE_POINT_REF) { if (loopFacePoint >= 3) { throw new SeeingSharpGraphicsException("Invalid face index count!"); } inStreamXml.Read(); actFaceReferences[loopFacePoint] = inStreamXml.ReadContentAsInt() - minVertexID; loopFacePoint++; } else { } } // Get the correct material MaterialProperties referencedMatObject = MaterialProperties.Empty; if (referencedMat > -1) { localMaterialInfos.TryGetValue(referencedMat, out referencedMatObject); } if (referencedTexture > -1) { referencedMatObject = referencedMatObject.Clone(); referencedMatObject.TextureKey = container.GetResourceKey(RES_CLASS_TEXTURE, referencedTexture.ToString()); } //for (int actFaceLoc = 0; actFaceLoc < 3; actFaceLoc++) //{ // int actVertexIndexInner = actFaceReferences[actFaceLoc]; // actTempVertex = actVertexStructure.Vertices[actVertexIndexInner]; // actTempVertex.Color = referencedMatObject.DiffuseColor; // actVertexStructure.Vertices[actVertexIndexInner] = actTempVertex; //} // Add the triangle if (loopFacePoint != 3) { throw new SeeingSharpGraphicsException("Invalid face index count!"); } actVertexStructure .CreateOrGetExistingSurface(referencedMatObject) .AddTriangle(actFaceReferences[0], actFaceReferences[1], actFaceReferences[2]); break; default: //throw new SeeingSharpGraphicsException(string.Format( // "Unknown element {0} in xgl file!", // inStreamXml.Name)); break; } } // Add the geometry resource container.ImportedResources.Add(new ImportedResourceInfo( container.GetResourceKey(RES_CLASS_MESH, id), () => new GeometryResource(actVertexStructure))); }
/// <summary> /// Fills the given vertex structure using information from the given AC-File-Objects. /// </summary> /// <param name="objInfo">The object information from the AC file.</param> /// <param name="acMaterials">A list containing all materials from the AC file.</param> /// <param name="structure">The VertexStructure to be filled.</param> /// <param name="transformStack">Current matrix stack (for stacked objects).</param> private static void FillVertexStructure(VertexStructure structure, List <ACMaterialInfo> acMaterials, ACObjectInfo objInfo, Matrix4Stack transformStack) { List <Tuple <int, int> > standardShadedVertices = new List <Tuple <int, int> >(); transformStack.Push(); try { // Perform local transformation for the current AC object transformStack.TransformLocal(objInfo.Rotation); transformStack.TranslateLocal(objInfo.Translation); // Build structures material by material for (int actMaterialIndex = 0; actMaterialIndex < acMaterials.Count; actMaterialIndex++) { ACMaterialInfo actMaterial = acMaterials[actMaterialIndex]; VertexStructureSurface actStructSurface = structure.CreateOrGetExistingSurface(actMaterial.CreateMaterialProperties()); bool isNewSurface = actStructSurface.CountTriangles == 0; // Create and configure vertex structure actStructSurface.Material = NamedOrGenericKey.Empty; actStructSurface.TextureKey = !string.IsNullOrEmpty(objInfo.Texture) ? new NamedOrGenericKey(objInfo.Texture) : NamedOrGenericKey.Empty; actStructSurface.MaterialProperties.DiffuseColor = actMaterial.Diffuse; actStructSurface.MaterialProperties.AmbientColor = actMaterial.Ambient; actStructSurface.MaterialProperties.EmissiveColor = actMaterial.Emissive; actStructSurface.MaterialProperties.Shininess = actMaterial.Shininess; actStructSurface.MaterialProperties.SpecularColor = actMaterial.Specular; // Initialize local index table (needed for vertex reuse) int oneSideVertexCount = objInfo.Vertices.Count; int[] localIndices = new int[oneSideVertexCount * 2]; for (int loop = 0; loop < localIndices.Length; loop++) { localIndices[loop] = int.MaxValue; } // Process all surfaces foreach (ACSurface actSurface in objInfo.Surfaces) { // Get the vertex index on which to start int startVertexIndex = structure.CountVertices; int startTriangleIndex = actStructSurface.CountTriangles; // Only handle surfaces of the current material if (actSurface.Material != actMaterialIndex) { continue; } // Sort out unsupported surfaces if (actSurface.VertexReferences.Count < 3) { continue; } if (actSurface.IsLine) { continue; } if (actSurface.IsClosedLine) { continue; } // Preprocess referenced vertices int oneSideSurfaceVertexCount = actSurface.VertexReferences.Count; int countSurfaceSides = actSurface.IsTwoSided ? 2 : 1; int[] onStructureReferencedVertices = new int[oneSideSurfaceVertexCount * countSurfaceSides]; List <int> surfaceVertexReferences = actSurface.VertexReferences; for (int loop = 0; loop < surfaceVertexReferences.Count; loop++) { Vector2 actTexCoord = actSurface.TextureCoordinates[loop]; if (!actSurface.IsFlatShaded) { // Try to reuse vertices on standard shading if (localIndices[surfaceVertexReferences[loop]] == int.MaxValue) { Vector3 position = Vector3.Transform( objInfo.Vertices[surfaceVertexReferences[loop]].Position, transformStack.Top); localIndices[surfaceVertexReferences[loop]] = structure.AddVertex(new Vertex( position, Color4.White, actTexCoord, Vector3.Zero)); if (actSurface.IsTwoSided) { localIndices[surfaceVertexReferences[loop] + oneSideVertexCount] = structure.AddVertex(new Vertex( position, Color4.White, actTexCoord, Vector3.Zero)); } } // Store vertex reference for this surface's index onStructureReferencedVertices[loop] = localIndices[surfaceVertexReferences[loop]]; if (actSurface.IsTwoSided) { onStructureReferencedVertices[loop + oneSideSurfaceVertexCount] = localIndices[surfaceVertexReferences[loop] + oneSideVertexCount]; } } else { // Create one vertex for one reference for flat shading Vector3 position = Vector3.Transform( objInfo.Vertices[surfaceVertexReferences[loop]].Position, transformStack.Top); onStructureReferencedVertices[loop] = structure.AddVertex(new Vertex( position, Color4.White, actTexCoord, Vector3.Zero)); if (actSurface.IsTwoSided) { onStructureReferencedVertices[loop + oneSideSurfaceVertexCount] = structure.AddVertex(new Vertex( position, Color4.White, actTexCoord, Vector3.Zero)); } } } // Build object geometry switch (actSurface.VertexReferences.Count) { case 3: // Front side actStructSurface.AddTriangle( onStructureReferencedVertices[0], onStructureReferencedVertices[1], onStructureReferencedVertices[2]); // Back side if (actSurface.IsTwoSided) { actStructSurface.AddTriangle( onStructureReferencedVertices[5], onStructureReferencedVertices[4], onStructureReferencedVertices[3]); } break; case 4: // Front side actStructSurface.AddTriangle( onStructureReferencedVertices[0], onStructureReferencedVertices[1], onStructureReferencedVertices[2]); actStructSurface.AddTriangle( onStructureReferencedVertices[2], onStructureReferencedVertices[3], onStructureReferencedVertices[0]); // Back side if (actSurface.IsTwoSided) { actStructSurface.AddTriangle( onStructureReferencedVertices[6], onStructureReferencedVertices[5], onStructureReferencedVertices[4]); actStructSurface.AddTriangle( onStructureReferencedVertices[4], onStructureReferencedVertices[7], onStructureReferencedVertices[6]); } break; default: if (!actSurface.IsTwoSided) { // Front side actStructSurface.AddPolygonByCuttingEars(onStructureReferencedVertices); } else { // Front and back side actStructSurface.AddPolygonByCuttingEars(onStructureReferencedVertices.Subset(0, oneSideSurfaceVertexCount)); actStructSurface.AddPolygonByCuttingEars(onStructureReferencedVertices.Subset(oneSideSurfaceVertexCount, oneSideSurfaceVertexCount)); } break; } // Perform shading if (actSurface.IsFlatShaded) { actStructSurface.CalculateNormalsFlat( startTriangleIndex, actStructSurface.CountTriangles - startTriangleIndex); } else { // Nothing to be done for now.. int vertexCount = structure.CountVertices - startVertexIndex; if (vertexCount > 0) { standardShadedVertices.Add( Tuple.Create((int)startVertexIndex, vertexCount)); } } } // Calculate default shading finally (if any) foreach (var actStandardShadedPair in standardShadedVertices) { structure.CalculateNormals( actStandardShadedPair.Item1, actStandardShadedPair.Item2); } standardShadedVertices.Clear(); // Append generated VertexStructure to the output collection if ((actStructSurface.CountTriangles <= 0) && (isNewSurface)) { structure.RemoveSurface(actStructSurface); } } //Fill in all child object data foreach (ACObjectInfo actObjInfo in objInfo.Childs) { FillVertexStructure(structure, acMaterials, actObjInfo, transformStack); } } finally { transformStack.Pop(); } }