/// <summary> /// Parsea el string "[-8.00202,-6.87125,0]" y devuelve un array de 3 floats. /// Sin invertir nada /// </summary> /// <param name="text"></param> /// <returns></returns> public static float[] parseFloat3Array(string text) { string aux = text.Substring(1, text.Length - 2); string[] n = aux.Split(new char[] { ',' }); return(new float[] { TgcParserUtils.parseFloat(n[0]), TgcParserUtils.parseFloat(n[1]), TgcParserUtils.parseFloat(n[2]) }); }
/// <summary> /// Parsea el string "[4,2,1]" y devuelve un array de 3 int. /// Invierte las coordenadas (x,y,z) a (x,z,y), de formato 3DsMAX a DirectX /// </summary> /// <param name="text"></param> /// <returns></returns> public static int[] parseInt3ArrayAdapted(string text) { int[] array = TgcParserUtils.parseInt3Array(text); int aux = array[1]; array[1] = array[2]; array[2] = aux; return(array); }
/// <summary> /// Parsea el string "[-8.00202,-6.87125,0]" y devuelve un array de 3 floats. /// Invierte las coordenadas (x,y,z) a (x,z,y), de formato 3DsMAX a DirectX /// </summary> /// <param name="text"></param> /// <returns></returns> public static float[] parseFloat3ArrayAdapted(string text) { float[] array = TgcParserUtils.parseFloat3Array(text); float aux = array[1]; array[1] = array[2]; array[2] = aux; return(array); }
private void parseStandardMaterial(TgcMaterialData material, XmlElement matNode) { material.name = matNode.Attributes["name"].InnerText; material.type = matNode.Attributes["type"].InnerText; //Valores de Material string ambientStr = matNode.GetElementsByTagName("ambient")[0].InnerText; material.ambientColor = TgcParserUtils.parseFloat4Array(ambientStr); TgcParserUtils.divFloatArrayValues(ref material.ambientColor, 255f); string diffuseStr = matNode.GetElementsByTagName("diffuse")[0].InnerText; material.diffuseColor = TgcParserUtils.parseFloat4Array(diffuseStr); TgcParserUtils.divFloatArrayValues(ref material.diffuseColor, 255f); string specularStr = matNode.GetElementsByTagName("specular")[0].InnerText; material.specularColor = TgcParserUtils.parseFloat4Array(specularStr); TgcParserUtils.divFloatArrayValues(ref material.specularColor, 255f); string opacityStr = matNode.GetElementsByTagName("opacity")[0].InnerText; material.opacity = TgcParserUtils.parseFloat(opacityStr) / 100f; XmlNode alphaBlendEnableNode = matNode.GetElementsByTagName("alphaBlendEnable")[0]; if (alphaBlendEnableNode != null) { string alphaBlendEnableStr = alphaBlendEnableNode.InnerText; material.alphaBlendEnable = bool.Parse(alphaBlendEnableStr); } //Valores de Bitmap XmlNode bitmapNode = matNode.GetElementsByTagName("bitmap")[0]; if (bitmapNode != null) { material.fileName = bitmapNode.InnerText; //TODO: formatear correctamente TILING y OFFSET string uvTilingStr = bitmapNode.Attributes["uvTiling"].InnerText; material.uvTiling = TgcParserUtils.parseFloat2Array(uvTilingStr); string uvOffsetStr = bitmapNode.Attributes["uvOffset"].InnerText; material.uvOffset = TgcParserUtils.parseFloat2Array(uvOffsetStr); } else { material.fileName = null; material.uvTiling = null; material.uvOffset = null; } }
/// <summary> /// Parsea un flujo continuo de floats de la forma: -74.1818 0.0 1.01613 -49.6512 0.0 1.01613... /// </summary> /// <param name="text">flujo de floats</param> /// <param name="count">cantidad de valores dentro del flujo</param> /// <returns></returns> public static float[] parseFloatStream(string text, int count) { float[] array = new float[count]; string[] textArray = text.Split(new char[] { ' ' }); for (int i = 0; i < count; i++) { array[i] = TgcParserUtils.parseFloat(textArray[i]); } return(array); }
/// <summary> /// Levanta la informacion del XML /// </summary> /// <param name="xmlString">contenido del XML</param> /// <returns></returns> public TgcSceneData parseSceneFromString(string xmlString) { XmlDocument dom = new XmlDocument(); dom.LoadXml(xmlString); XmlElement root = dom.DocumentElement; string sceneName = root.GetElementsByTagName("name")[0].InnerText; TgcSceneData tgcSceneData = new TgcSceneData(); tgcSceneData.name = sceneName; //Ver si tiene exportacion de texturas XmlNode texturesExportNode = root.GetElementsByTagName("texturesExport")[0]; bool texturesExportEnabled = bool.Parse(texturesExportNode.Attributes["enabled"].InnerText); if (texturesExportEnabled) { tgcSceneData.texturesDir = texturesExportNode.Attributes["dir"].InnerText; } //Ver si tiene LightMaps XmlNode lightmapsExportNode = root.GetElementsByTagName("lightmapExport")[0]; tgcSceneData.lightmapsEnabled = bool.Parse(lightmapsExportNode.Attributes["enabled"].InnerText); if (tgcSceneData.lightmapsEnabled) { tgcSceneData.lightmapsDir = lightmapsExportNode.Attributes["dir"].InnerText; } //sceneBoundingBox, si está XmlNodeList sceneBoundingBoxNodes = root.GetElementsByTagName("sceneBoundingBox"); if (sceneBoundingBoxNodes != null && sceneBoundingBoxNodes.Count == 1) { XmlNode sceneBoundingBoxNode = sceneBoundingBoxNodes[0]; tgcSceneData.pMin = TgcParserUtils.parseFloat3Array(sceneBoundingBoxNode.Attributes["min"].InnerText); tgcSceneData.pMax = TgcParserUtils.parseFloat3Array(sceneBoundingBoxNode.Attributes["max"].InnerText); } //Parsear Texturas XmlNodeList materialNodes = root.GetElementsByTagName("materials")[0].ChildNodes; tgcSceneData.materialsData = new TgcMaterialData[materialNodes.Count]; int i = 0; foreach (XmlElement matNode in materialNodes) { //determinar tipo de Material TgcMaterialData material = new TgcMaterialData(); material.type = matNode.Attributes["type"].InnerText; //Standard Material if (material.type.Equals(TgcMaterialData.StandardMaterial)) { parseStandardMaterial(material, matNode); } //Multi Material else if (material.type.Equals(TgcMaterialData.MultiMaterial)) { material.name = matNode.Attributes["name"].InnerText; XmlNodeList subMaterialsNodes = matNode.GetElementsByTagName("subM"); material.subMaterials = new TgcMaterialData[subMaterialsNodes.Count]; for (int j = 0; j < subMaterialsNodes.Count; j++) { TgcMaterialData subMaterial = new TgcMaterialData(); parseStandardMaterial(subMaterial, (XmlElement)subMaterialsNodes[j]); material.subMaterials[j] = subMaterial; } } tgcSceneData.materialsData[i++] = material; } //Parsear Meshes XmlNodeList meshesNodes = root.GetElementsByTagName("meshes")[0].ChildNodes; tgcSceneData.meshesData = new TgcMeshData[meshesNodes.Count]; i = 0; int count; foreach (XmlElement meshNode in meshesNodes) { TgcMeshData meshData = new TgcMeshData(); tgcSceneData.meshesData[i++] = meshData; //parser y convertir valores meshData.name = meshNode.Attributes["name"].InnerText; meshData.materialId = int.Parse(meshNode.Attributes["matId"].InnerText); meshData.color = TgcParserUtils.parseFloat3Array(meshNode.Attributes["color"].InnerText); meshData.lightmap = meshNode.Attributes["lightmap"].InnerText; //type XmlAttribute typeAttr = meshNode.Attributes["type"]; meshData.instanceType = TgcMeshData.ORIGINAL; if (typeAttr != null) { meshData.instanceType = typeAttr.InnerText; } //type XmlAttribute layerAttr = meshNode.Attributes["layer"]; if (layerAttr != null) { meshData.layerName = layerAttr.InnerText; } //visibility float visibility = TgcParserUtils.parseFloat(meshNode.Attributes["visibility"].InnerText); meshData.alphaBlending = visibility != 1.0f ? true : false; //parsear boundingBox XmlNodeList boundingBoxNodes = meshNode.GetElementsByTagName("boundingBox"); if (boundingBoxNodes != null && boundingBoxNodes.Count == 1) { XmlNode boundingBoxNode = boundingBoxNodes[0]; meshData.pMin = TgcParserUtils.parseFloat3Array(boundingBoxNode.Attributes["min"].InnerText); meshData.pMax = TgcParserUtils.parseFloat3Array(boundingBoxNode.Attributes["max"].InnerText); } //parsear datos de mesh Original if (meshData.instanceType.Equals(TgcMeshData.ORIGINAL)) { //parsear coordinatesIdx XmlNode coordinatesIdxNode = meshNode.GetElementsByTagName("coordinatesIdx")[0]; count = int.Parse(coordinatesIdxNode.Attributes["count"].InnerText); meshData.coordinatesIndices = TgcParserUtils.parseIntStream(coordinatesIdxNode.InnerText, count); //parsear textCoordsIdx XmlNode textCoordsIdxNode = meshNode.GetElementsByTagName("textCoordsIdx")[0]; count = int.Parse(textCoordsIdxNode.Attributes["count"].InnerText); meshData.texCoordinatesIndices = TgcParserUtils.parseIntStream(textCoordsIdxNode.InnerText, count); //parsear colorsIdx XmlNode colorsIdxNode = meshNode.GetElementsByTagName("colorsIdx")[0]; count = int.Parse(colorsIdxNode.Attributes["count"].InnerText); meshData.colorIndices = TgcParserUtils.parseIntStream(colorsIdxNode.InnerText, count); //parsear matIds //TODO: ver bien como calcula esto el SCRIPT de Exportacion if (meshData.materialId != -1) { XmlNode matIdsNode = meshNode.GetElementsByTagName("matIds")[0]; count = int.Parse(matIdsNode.Attributes["count"].InnerText); meshData.materialsIds = TgcParserUtils.parseIntStream(matIdsNode.InnerText, count); } //parsear textCoordsLightMapIdx meshData.lightmapEnabled = tgcSceneData.lightmapsEnabled && (meshData.lightmap.Trim()).Length > 0; if (meshData.lightmapEnabled) { XmlNode textCoordsLightMapIdxNode = meshNode.GetElementsByTagName("textCoordsLightMapIdx")[0]; count = int.Parse(textCoordsLightMapIdxNode.Attributes["count"].InnerText); meshData.texCoordinatesIndicesLightMap = TgcParserUtils.parseIntStream(textCoordsLightMapIdxNode.InnerText, count); } //parsear vertices XmlNode verticesNode = meshNode.GetElementsByTagName("vertices")[0]; count = int.Parse(verticesNode.Attributes["count"].InnerText); meshData.verticesCoordinates = TgcParserUtils.parseFloatStream(verticesNode.InnerText, count); //parsear normals XmlNode normalsNode = meshNode.GetElementsByTagName("normals")[0]; count = int.Parse(normalsNode.Attributes["count"].InnerText); meshData.verticesNormals = TgcParserUtils.parseFloatStream(normalsNode.InnerText, count); //parsear texCoords XmlNode texCoordsNode = meshNode.GetElementsByTagName("texCoords")[0]; count = int.Parse(texCoordsNode.Attributes["count"].InnerText); meshData.textureCoordinates = TgcParserUtils.parseFloatStream(texCoordsNode.InnerText, count); //parsear colors XmlNode colorsNode = meshNode.GetElementsByTagName("colors")[0]; count = int.Parse(colorsNode.Attributes["count"].InnerText); float[] colorsArray = TgcParserUtils.parseFloatStream(colorsNode.InnerText, count); //convertir a formato DirectX meshData.verticesColors = new int[count / 3]; for (int j = 0; j < meshData.verticesColors.Length; j++) { meshData.verticesColors[j] = Color.FromArgb( (int)colorsArray[j * 3], (int)colorsArray[j * 3 + 1], (int)colorsArray[j * 3 + 2]).ToArgb(); } //parsear texCoordsLightMap if (meshData.lightmapEnabled) { XmlNode texCoordsLightMapNode = meshNode.GetElementsByTagName("texCoordsLightMap")[0]; count = int.Parse(texCoordsLightMapNode.Attributes["count"].InnerText); meshData.textureCoordinatesLightMap = TgcParserUtils.parseFloatStream(texCoordsLightMapNode.InnerText, count); } } //parsear datos de mesh Instancia else if (meshData.instanceType.Equals(TgcMeshData.INSTANCE)) { //originalMesh XmlNode originalMeshNode = meshNode.GetElementsByTagName("originalMesh")[0]; meshData.originalMesh = TgcParserUtils.parseInt(originalMeshNode.InnerText); //transform XmlNode transformNode = meshNode.GetElementsByTagName("transform")[0]; meshData.position = TgcParserUtils.parseFloat3Array(transformNode.Attributes["pos"].InnerText); meshData.rotation = TgcParserUtils.parseFloat4Array(transformNode.Attributes["rotQuat"].InnerText); meshData.scale = TgcParserUtils.parseFloat3Array(transformNode.Attributes["scale"].InnerText); } //Parsear userProperties, si hay XmlNodeList userPropsNodes = meshNode.GetElementsByTagName("userProps"); if (userPropsNodes != null && userPropsNodes.Count == 1) { meshData.userProperties = new Dictionary <string, string>(); XmlElement userPropsNode = (XmlElement)userPropsNodes[0]; foreach (XmlElement prop in userPropsNode.ChildNodes) { meshData.userProperties.Add(prop.Name, prop.InnerText); } } } //Parsear PortalRendering, si hay información XmlNodeList portalRenderingNodes = root.GetElementsByTagName("portalRendering"); if (portalRenderingNodes != null && portalRenderingNodes.Count == 1) { XmlElement portalRenderingNode = (XmlElement)portalRenderingNodes[0]; TgcPortalRenderingParser portalParser = new TgcPortalRenderingParser(); tgcSceneData.portalData = portalParser.parseFromXmlNode(portalRenderingNode); } return(tgcSceneData); }
/// <summary> /// Carga la escena a partir de un objeto TgcSceneData ya parseado /// </summary> /// <param name="sceneData">Objeto con datos de la escena ya parseados</param> /// <param name="mediaPath">Path a partir del cual hay que buscar los recursos de escena (Texturas, LightMaps, etc.)</param> /// <returns></returns> public TgcScene loadScene(TgcSceneData sceneData, string mediaPath) { TgcScene tgcScene = new TgcScene(sceneData.name, null); //Cargar Texturas TgcSceneLoaderMaterialAux[] materialsArray = new TgcSceneLoaderMaterialAux[sceneData.materialsData.Length]; for (int i = 0; i < sceneData.materialsData.Length; i++) { TgcMaterialData materialData = sceneData.materialsData[i]; string texturesPath = mediaPath + sceneData.texturesDir + "\\"; //Crear StandardMaterial if (materialData.type.Equals(TgcMaterialData.StandardMaterial)) { materialsArray[i] = createTextureAndMaterial(materialData, texturesPath); } //Crear MultiMaterial else if (materialData.type.Equals(TgcMaterialData.MultiMaterial)) { TgcSceneLoaderMaterialAux matAux = new TgcSceneLoaderMaterialAux(); materialsArray[i] = matAux; matAux.subMaterials = new TgcSceneLoaderMaterialAux[materialData.subMaterials.Length]; for (int j = 0; j < materialData.subMaterials.Length; j++) { matAux.subMaterials[j] = createTextureAndMaterial(materialData.subMaterials[j], texturesPath); } } } //Cargar Meshes for (int i = 0; i < sceneData.meshesData.Length; i++) { TgcMeshData meshData = sceneData.meshesData[i]; TgcMesh tgcMesh = null; //Crear malla original if (meshData.instanceType.Equals(TgcMeshData.ORIGINAL)) { //Crear mesh que no tiene Material, con un color simple if (meshData.materialId == -1) { tgcMesh = crearMeshSoloColor(meshData); } //Para los que si tienen Material else { //Crear MeshFormat que soporte LightMaps if (meshData.lightmapEnabled) { tgcMesh = crearMeshDiffuseMapLightmap(sceneData, mediaPath, materialsArray, meshData); } //Formato de Mesh con Textura pero sin Lightmap else { tgcMesh = crearMeshDiffuseMap(materialsArray, meshData); } } } //Crear malla instancia else if (meshData.instanceType.Equals(TgcMeshData.INSTANCE)) { tgcMesh = crearMeshInstance(meshData, tgcScene.Meshes); } //Crear BoundingBox, aprovechar lo que viene del XML o crear uno por nuestra cuenta if (meshData.pMin != null && meshData.pMax != null) { tgcMesh.BoundingBox = new TgcBoundingBox( TgcParserUtils.float3ArrayToVector3(meshData.pMin), TgcParserUtils.float3ArrayToVector3(meshData.pMax), tgcMesh.Position, tgcMesh.Scale ); } else { tgcMesh.createBoundingBox(); } //Cargar layer tgcMesh.Layer = meshData.layerName; //Cargar AlphaBlending tgcMesh.AlphaBlendEnable = meshData.alphaBlending; //agregar mesh a escena tgcMesh.Enabled = true; tgcScene.Meshes.Add(tgcMesh); //Cargar userProperties, si hay tgcMesh.UserProperties = meshData.userProperties; } //BoundingBox del escenario, utilizar el que viene del XML o crearlo nosotros if (sceneData.pMin != null && sceneData.pMax != null) { tgcScene.BoundingBox = new TgcBoundingBox( new Vector3(sceneData.pMin[0], sceneData.pMin[1], sceneData.pMin[2]), new Vector3(sceneData.pMax[0], sceneData.pMax[1], sceneData.pMax[2]) ); } else { List <TgcBoundingBox> boundingBoxes = new List <TgcBoundingBox>(); foreach (TgcMesh mesh in tgcScene.Meshes) { boundingBoxes.Add(mesh.BoundingBox); } tgcScene.BoundingBox = TgcBoundingBox.computeFromBoundingBoxes(boundingBoxes); } //Cargar parte de PortalRendering, solo hay información if (sceneData.portalData != null) { TgcPortalRenderingLoader portalLoader = new TgcPortalRenderingLoader(); tgcScene.PortalRendering = portalLoader.loadFromData(tgcScene, sceneData.portalData); } return(tgcScene); }