/// <summary> /// Generates all vertex structures needed for this object /// </summary> private static VertexStructure GenerateStructure(ACFileInfo fileInfo) { VertexStructure result = new VertexStructure(); // Create all vertex structures Matrix4Stack transformStack = new Matrix4Stack(); foreach (ACObjectInfo actObject in fileInfo.Objects) { FillVertexStructure(result, fileInfo.Materials, actObject, transformStack); } return(result); }
/// <summary> /// Imports VertexStructures from the given stream. /// </summary> /// <param name="inStream">The stream to load the data from.</param> /// <param name="originalSource">The original source of the generated geometry.</param> public static VertexStructure ImportVertexStructure(Stream inStream, ResourceLink originalSource) { try { // Load the file and generate all VertexStructures ACFileInfo fileInfo = LoadFile(inStream); VertexStructure result = GenerateStructure(fileInfo); result.ResourceLink = originalSource; // return the result return(result); } catch (Exception) { // Create dummy VertexStructure VertexStructure dummyStructure = new VertexStructure(); dummyStructure.FirstSurface.BuildCube24V( new Vector3(), new Vector3(1f, 1f, 1f), Color4.Transparent); return(dummyStructure); } }
/// <summary> /// Loads a ac file from the given uri /// </summary> private static ACFileInfo LoadFile(Stream inStream) { ACFileInfo result = null; StreamReader reader = null; try { reader = new StreamReader(inStream); //Check for correct header string header = reader.ReadLine(); if (!header.StartsWith("AC3D")) { throw new SeeingSharpGraphicsException("Header of AC3D file not found!"); } //Create file information object result = new ACFileInfo(); //Create a loaded objects stack Stack <ACObjectInfo> loadedObjects = new Stack <ACObjectInfo>(); Stack <ACObjectInfo> parentObjects = new Stack <ACObjectInfo>(); ACSurface currentSurface = null; //Read the file while (!reader.EndOfStream) { string actLine = reader.ReadLine().Trim(); string firstWord = string.Empty; int spaceIndex = actLine.IndexOf(' '); if (spaceIndex == -1) { firstWord = actLine; } else { firstWord = firstWord = actLine.Substring(0, spaceIndex); } switch (firstWord) { //New Material info case "MATERIAL": ACMaterialInfo materialInfo = new ACMaterialInfo(); { //Get the name of the material string[] materialData = actLine.Split(' '); if (materialData.Length > 1) { materialInfo.Name = materialData[1].Trim(' ', '"'); } //Parse components for (int loop = 0; loop < materialData.Length; loop++) { switch (materialData[loop]) { case "rgb": Color4 diffuseColor = materialInfo.Diffuse; diffuseColor.Alpha = 1f; diffuseColor.Red = Single.Parse(materialData[loop + 1], CultureInfo.InvariantCulture); diffuseColor.Green = Single.Parse(materialData[loop + 2], CultureInfo.InvariantCulture); diffuseColor.Blue = Single.Parse(materialData[loop + 3], CultureInfo.InvariantCulture); materialInfo.Diffuse = diffuseColor; break; case "amb": Color4 ambientColor = new Color4(); ambientColor.Red = Single.Parse(materialData[loop + 1], CultureInfo.InvariantCulture); ambientColor.Green = Single.Parse(materialData[loop + 2], CultureInfo.InvariantCulture); ambientColor.Blue = Single.Parse(materialData[loop + 3], CultureInfo.InvariantCulture); materialInfo.Ambient = ambientColor; break; case "emis": Color4 emissiveColor = new Color4(); emissiveColor.Red = Single.Parse(materialData[loop + 1], CultureInfo.InvariantCulture); emissiveColor.Green = Single.Parse(materialData[loop + 2], CultureInfo.InvariantCulture); emissiveColor.Blue = Single.Parse(materialData[loop + 3], CultureInfo.InvariantCulture); materialInfo.Emissive = emissiveColor; break; case "spec": Color4 specularColor = new Color4(); specularColor.Red = Single.Parse(materialData[loop + 1], CultureInfo.InvariantCulture); specularColor.Green = Single.Parse(materialData[loop + 2], CultureInfo.InvariantCulture); specularColor.Blue = Single.Parse(materialData[loop + 3], CultureInfo.InvariantCulture); materialInfo.Specular = specularColor; break; case "shi": materialInfo.Shininess = Single.Parse(materialData[loop + 1], CultureInfo.InvariantCulture); break; case "trans": diffuseColor = materialInfo.Diffuse; diffuseColor.Alpha = 1f - EngineMath.Clamp(Single.Parse(materialData[loop + 1], CultureInfo.InvariantCulture), 0f, 1f); materialInfo.Diffuse = diffuseColor; break; } } result.Materials.Add(materialInfo); } break; //New object starts here case "OBJECT": { ACObjectInfo newObject = new ACObjectInfo(); string[] lineData = actLine.Split(' '); if (lineData[1] == "poly") { newObject.Type = ACObjectType.Poly; } else if (lineData[1] == "group") { newObject.Type = ACObjectType.Group; } else if (lineData[1] == "world") { newObject.Type = ACObjectType.World; } loadedObjects.Push(newObject); } break; //End of an object, kids following case "kids": if (loadedObjects.Count == 0) { break; } { //Parse kid count int kidCount = 0; string[] lineData = actLine.Split(' '); if ((lineData != null) && (lineData.Length >= 1)) { Int32.TryParse(lineData[1], out kidCount); } ACObjectInfo currentObject = loadedObjects.Peek(); if (currentObject != null) { //Add object to parent object, if any related bool addedToParent = false; if (parentObjects.Count > 0) { ACObjectInfo currentParent = parentObjects.Peek(); if (currentParent.Childs.Count < currentParent.KidCount) { currentParent.Childs.Add(currentObject); addedToParent = true; } else { while (parentObjects.Count > 0) { parentObjects.Pop(); if (parentObjects.Count == 0) { break; } currentParent = parentObjects.Peek(); if (currentParent == null) { break; } if (currentParent.Childs.Count < currentParent.KidCount) { break; } } if ((currentParent != null) && (currentParent.Childs.Count < currentParent.KidCount)) { currentParent.Childs.Add(currentObject); addedToParent = true; } } } //Enable this object as parent object currentObject.KidCount = kidCount; if (currentObject.KidCount > 0) { parentObjects.Push(currentObject); } //Add to scene root if this object has no parent loadedObjects.Pop(); if (!addedToParent) { if (loadedObjects.Count == 0) { result.Objects.Add(currentObject); } else { loadedObjects.Peek().Childs.Add(currentObject); } } currentObject = null; } } break; //Current object's name case "name": if (loadedObjects.Count == 0) { break; } { ACObjectInfo currentObject = loadedObjects.Peek(); if (currentObject != null) { currentObject.Name = actLine.Replace("name ", "").Replace("\"", ""); } } break; case "data": break; case "texture": if (loadedObjects.Count == 0) { break; } { ACObjectInfo currentObject = loadedObjects.Peek(); if (currentObject != null) { string[] lineData = actLine.Split(' '); currentObject.Texture = lineData[1].Trim('"'); } } break; case "texrep": if (loadedObjects.Count == 0) { break; } { ACObjectInfo currentObject = loadedObjects.Peek(); if (currentObject != null) { string[] lineData = actLine.Split(' '); Vector2 repetition = new Vector2(); repetition.X = Single.Parse(lineData[1], CultureInfo.InvariantCulture); repetition.Y = Single.Parse(lineData[2], CultureInfo.InvariantCulture); currentObject.TextureRepeat = repetition; } } break; case "texoff": if (loadedObjects.Count == 0) { break; } { ACObjectInfo currentObject = loadedObjects.Peek(); if (currentObject != null) { string[] lineData = actLine.Split(' '); Vector2 offset = new Vector2(); offset.X = Single.Parse(lineData[1], CultureInfo.InvariantCulture); offset.Y = Single.Parse(lineData[2], CultureInfo.InvariantCulture); currentObject.TextureRepeat = offset; } } break; case "rot": if (loadedObjects.Count == 0) { break; } { ACObjectInfo currentObject = loadedObjects.Peek(); if (currentObject != null) { string[] lineData = actLine.Split(' '); Matrix4x4 rotation = Matrix4x4.Identity; rotation.M11 = !string.IsNullOrEmpty(lineData[1]) ? Single.Parse(lineData[1], CultureInfo.InvariantCulture) : 0f; rotation.M12 = !string.IsNullOrEmpty(lineData[2]) ? Single.Parse(lineData[2], CultureInfo.InvariantCulture) : 0f; rotation.M13 = !string.IsNullOrEmpty(lineData[3]) ? Single.Parse(lineData[3], CultureInfo.InvariantCulture) : 0f; rotation.M21 = !string.IsNullOrEmpty(lineData[4]) ? Single.Parse(lineData[4], CultureInfo.InvariantCulture) : 0f; rotation.M22 = !string.IsNullOrEmpty(lineData[5]) ? Single.Parse(lineData[5], CultureInfo.InvariantCulture) : 0f; rotation.M23 = !string.IsNullOrEmpty(lineData[6]) ? Single.Parse(lineData[6], CultureInfo.InvariantCulture) : 0f; rotation.M31 = !string.IsNullOrEmpty(lineData[7]) ? Single.Parse(lineData[7], CultureInfo.InvariantCulture) : 0f; rotation.M32 = !string.IsNullOrEmpty(lineData[8]) ? Single.Parse(lineData[8], CultureInfo.InvariantCulture) : 0f; rotation.M33 = !string.IsNullOrEmpty(lineData[9]) ? Single.Parse(lineData[9], CultureInfo.InvariantCulture) : 0f; currentObject.Rotation = rotation; } } break; case "url": if (loadedObjects.Count == 0) { break; } { ACObjectInfo currentObject = loadedObjects.Peek(); if (currentObject != null) { string[] lineData = actLine.Split(' '); currentObject.Url = lineData[1].Trim('"'); } } break; //Current object's location case "loc": if (loadedObjects.Count == 0) { break; } { ACObjectInfo currentObject = loadedObjects.Peek(); if (currentObject != null) { string[] lineData = actLine.Split(' '); Vector3 location = new Vector3(); location.X = Single.Parse(lineData[1], CultureInfo.InvariantCulture); location.Y = Single.Parse(lineData[2], CultureInfo.InvariantCulture); location.Z = Single.Parse(lineData[3], CultureInfo.InvariantCulture); currentObject.Translation = location; } } break; case "numvert": if (loadedObjects.Count == 0) { break; } { ACObjectInfo currentObject = loadedObjects.Peek(); if (currentObject != null) { string[] lineData = actLine.Split(' '); int numberOfVertices = Int32.Parse(lineData[1], CultureInfo.InvariantCulture); for (int loop = 0; loop < numberOfVertices; loop++) { string actInnerLine = reader.ReadLine().Trim(); string[] splittedVertex = actInnerLine.Split(' '); Vector3 position = new Vector3(); position.X = Single.Parse(splittedVertex[0], CultureInfo.InvariantCulture); position.Y = Single.Parse(splittedVertex[1], CultureInfo.InvariantCulture); position.Z = Single.Parse(splittedVertex[2], CultureInfo.InvariantCulture); currentObject.Vertices.Add(new ACVertex() { Position = position }); } } } break; //Start of a list of surfaces case "numsurf": break; //New surface starts here case "SURF": { if (currentSurface == null) { currentSurface = new ACSurface(); } string[] lineData = actLine.Split(' '); lineData[1] = lineData[1].Substring(2); currentSurface.Flags = Int32.Parse(lineData[1], NumberStyles.HexNumber); } break; //Current surface's material case "mat": { if (currentSurface == null) { currentSurface = new ACSurface(); } string[] lineData = actLine.Split(' '); currentSurface.Material = Int32.Parse(lineData[1], CultureInfo.InvariantCulture); } break; //Current surface's indices case "refs": if (loadedObjects.Count == 0) { break; } { if (currentSurface == null) { currentSurface = new ACSurface(); } string[] lineData = actLine.Split(' '); int numberOfRefs = Int32.Parse(lineData[1], CultureInfo.InvariantCulture); for (int loop = 0; loop < numberOfRefs; loop++) { string actInnerLine = reader.ReadLine().Trim(); string[] splittedRef = actInnerLine.Split(' '); Vector2 texCoord = new Vector2(); int vertexReference = UInt16.Parse(splittedRef[0], CultureInfo.InvariantCulture); texCoord.X = Single.Parse(splittedRef[1], CultureInfo.InvariantCulture); texCoord.Y = Single.Parse(splittedRef[2], CultureInfo.InvariantCulture); currentSurface.TextureCoordinates.Add(texCoord); currentSurface.VertexReferences.Add(vertexReference); } ACObjectInfo currentObject = loadedObjects.Peek(); if (currentObject != null) { currentObject.Surfaces.Add(currentSurface); } currentSurface = null; } break; default: break; } } } finally { if (reader != null) { reader.Dispose(); } } return(result); }