/// <summary> /// Busca el duplicado del vertice con texcoord u, si no existe lo crea y retorna el indice. /// </summary> /// <param name="vertices"></param> /// <param name="indices"></param> /// <param name="dDup"></param> /// <param name="idx"></param> /// <param name="u"></param> /// <returns></returns> protected static int dupWithU(List <Vertex.PositionColoredTexturedNormal> vertices, List <int> indices, Dictionary <int, int> dDup, int idx, float u) { int newIndx; if (!dDup.ContainsKey(indices[idx])) { Vertex.PositionColoredTexturedNormal newV = vertices[indices[idx]]; newV.Tu = u; newIndx = vertices.Count; vertices.Add(newV); dDup.Add(indices[idx], newIndx); } else { newIndx = dDup[indices[idx]]; } return(newIndx); }
/// <summary> /// Duplica los vertices que deben tener coordenadas de textura diferentes para diferentes triangulos /// </summary> /// <param name="vertices"></param> /// <param name="indices"></param> /// <param name="iverticesU1"></param> /// <param name="polos"></param> protected virtual void fixTexcoords(List<Vertex.PositionColoredTexturedNormal> vertices, List<int> indices, List<int> iverticesU1, int[] polos) { Dictionary<int, int> duplicados = new Dictionary<int, int>(); float U0p5 = 0.5f * UVTiling.X + UVOffset.X; float U1 = UVTiling.X + UVOffset.X; //Fix compartidos foreach (int idx in iverticesU1) { for (int i = 0; i < indices.Count; i += 3) { //Triangulo que tiene ese vertice. if (indices[i] == idx || indices[i + 1] == idx || indices[i + 2] == idx) { int i1 = indices[i]; int i2 = indices[i + 1]; int i3 = indices[i + 2]; //Solo me importan los que tienen un vertice con u=1(fin de la textura) y otro menor a 0.5 (comienzo de la textura) if ((!esPolo(vertices[i1]) && vertices[i1].Tu < U0p5) || (!esPolo(vertices[i2]) && vertices[i2].Tu < U0p5) || (!esPolo(vertices[i3]) && vertices[i3].Tu < U0p5)) { List<int> u1 = new List<int>(); List<int> um = new List<int>(); //Clasifico cada vertice segun su Tu1 for (int j = 0; j < 3; j++) if (vertices[indices[i + j]].Tu == U1 || esPolo(vertices[indices[i + j]])) u1.Add(i + j); else if (vertices[indices[i + j]].Tu < U0p5) um.Add(i + j); if (um.Count == 1 && !(esPolo(vertices[indices[u1[0]]]) && vertices[indices[um[0]]].X >= 0)) { //Casos: //2 vertices con u=1 o uno con u=1 y otro con u>0.5 //1 vertice es el polo, y uno de los vertices esta al final de la textura y otro al principio //La coordenada textura del de u >0.5 pasa a ser 1+u indices[um[0]] = dupWithU(vertices, indices, duplicados, um[0], vertices[indices[um[0]]].Tu + UVTiling.X); } else if (!esPolo(vertices[indices[u1[0]]])) // Caso: // 1 vertice con u=1 y dos con u<0.5 // El u del vertice con u=1 pasa a ser 0 indices[u1[0]] = dupWithU(vertices, indices, duplicados, u1[0], UVOffset.X); } } } } //Fix polos for (int p = 0; p < 2; p++) { bool first = true; for (int i = 0; i < indices.Count; i += 3)//Por cada triangulo { int iipolo = i; for (; iipolo < i + 3 && indices[iipolo] != polos[p]; iipolo++) ; //Si un vertice es el polo if (iipolo < i + 3) { Vertex.PositionColoredTexturedNormal[] u = new Vertex.PositionColoredTexturedNormal[2]; int n = 0; //Guardo los vertices que no son polos. for (int j = 0; j < 3; j++) if (i + j != iipolo) u[n++] = vertices[indices[i + j]]; float minU = FastMath.Min(u[0].Tu, u[1].Tu); Vertex.PositionColoredTexturedNormal pole = vertices[polos[p]]; //Chequea que no sea un triangulo rectangulo Vertex.PositionColoredTexturedNormal zeroXZ = u[0]; bool noRectangulo = false; if (u[0].X != 0 && u[0].Z != 0) zeroXZ = u[0]; else if (u[1].X != 0 && u[1].Z != 0) zeroXZ = u[1]; else noRectangulo = true; //Interpolo Tu1 if (basePoly.Equals(eBasePoly.ICOSAHEDRON) || noRectangulo) pole.Tu = minU + FastMath.Abs(u[0].Tu - u[1].Tu) / 2; else pole.Tu = zeroXZ.Tu; if (first) //Si es la primera vez que lo hago, modifico el vertice. { vertices[polos[p]] = pole; first = false; } else //Sino lo duplico. { indices[iipolo] = vertices.Count; vertices.Add(pole); } } } } }
/// <summary> /// Convierte el TgcSphere en un TgcMesh /// </summary> /// <param name="meshName">Nombre de la malla que se va a crear</param> public TgcMesh toMesh(string meshName) { Device d3dDevice = GuiController.Instance.D3dDevice; //Obtener matriz para transformar vertices if (autoTransformEnable) { this.transform = Matrix.Scaling(radius, radius, radius) * Matrix.Scaling(Scale) * Matrix.RotationYawPitchRoll(rotation.Y, rotation.X, rotation.Z) * Matrix.Translation(translation); } //Crear mesh con DiffuseMap if (texture != null) { //Crear Mesh Mesh d3dMesh = new Mesh(indices.Count / 3, indices.Count, MeshFlags.Managed, TgcSceneLoader.TgcSceneLoader.DiffuseMapVertexElements, d3dDevice); //Cargar VertexBuffer using (VertexBuffer vb = d3dMesh.VertexBuffer) { GraphicsStream data = vb.Lock(0, 0, LockFlags.None); for (int j = 0; j < indices.Count; j++) { TgcSceneLoader.TgcSceneLoader.DiffuseMapVertex v = new TgcSceneLoader.TgcSceneLoader.DiffuseMapVertex(); Vertex.PositionColoredTexturedNormal vSphere = vertices[indices[j]]; //vertices v.Position = Vector3.TransformCoordinate(vSphere.getPosition(), this.transform); //normals v.Normal = vSphere.getNormal(); //texture coordinates diffuseMap v.Tu = vSphere.Tu; v.Tv = vSphere.Tv; //color v.Color = vSphere.Color; data.Write(v); } vb.Unlock(); } //Cargar IndexBuffer en forma plana using (IndexBuffer ib = d3dMesh.IndexBuffer) { short[] vIndices = new short[indices.Count]; for (int j = 0; j < vIndices.Length; j++) { vIndices[j] = (short)j; } ib.SetData(vIndices, 0, LockFlags.None); } //Calcular normales //d3dMesh.ComputeNormals(); //Malla de TGC TgcMesh tgcMesh = new TgcMesh(d3dMesh, meshName, TgcMesh.MeshRenderType.DIFFUSE_MAP); tgcMesh.DiffuseMaps = new TgcTexture[] { texture.clone() }; tgcMesh.Materials = new Material[] { TgcD3dDevice.DEFAULT_MATERIAL }; tgcMesh.createBoundingBox(); tgcMesh.Enabled = true; return(tgcMesh); } //Crear mesh con solo color else { //Crear Mesh Mesh d3dMesh = new Mesh(indices.Count / 3, indices.Count, MeshFlags.Managed, TgcSceneLoader.TgcSceneLoader.VertexColorVertexElements, d3dDevice); //Cargar VertexBuffer using (VertexBuffer vb = d3dMesh.VertexBuffer) { GraphicsStream data = vb.Lock(0, 0, LockFlags.None); for (int j = 0; j < indices.Count; j++) { TgcSceneLoader.TgcSceneLoader.VertexColorVertex v = new TgcSceneLoader.TgcSceneLoader.VertexColorVertex(); Vertex.PositionColoredTexturedNormal vSphere = vertices[indices[j]]; //vertices v.Position = Vector3.TransformCoordinate(vSphere.getPosition(), this.transform); //normals v.Normal = vSphere.getNormal(); //color v.Color = vSphere.Color; data.Write(v); } vb.Unlock(); } //Cargar IndexBuffer en forma plana using (IndexBuffer ib = d3dMesh.IndexBuffer) { short[] vIndices = new short[indices.Count]; for (int j = 0; j < vIndices.Length; j++) { vIndices[j] = (short)j; } ib.SetData(vIndices, 0, LockFlags.None); } //Malla de TGC TgcMesh tgcMesh = new TgcMesh(d3dMesh, meshName, TgcMesh.MeshRenderType.VERTEX_COLOR); tgcMesh.Materials = new Material[] { TgcD3dDevice.DEFAULT_MATERIAL }; tgcMesh.createBoundingBox(); tgcMesh.Enabled = true; return(tgcMesh); } }
/// <summary> /// Duplica los vertices que deben tener coordenadas de textura diferentes para diferentes triangulos /// </summary> /// <param name="vertices"></param> /// <param name="indices"></param> /// <param name="iverticesU1"></param> /// <param name="polos"></param> protected virtual void fixTexcoords(List <Vertex.PositionColoredTexturedNormal> vertices, List <int> indices, List <int> iverticesU1, int[] polos) { Dictionary <int, int> duplicados = new Dictionary <int, int>(); float U0p5 = 0.5f * UVTiling.X + UVOffset.X; float U1 = UVTiling.X + UVOffset.X; //Fix compartidos foreach (int idx in iverticesU1) { for (int i = 0; i < indices.Count; i += 3) { //Triangulo que tiene ese vertice. if (indices[i] == idx || indices[i + 1] == idx || indices[i + 2] == idx) { int i1 = indices[i]; int i2 = indices[i + 1]; int i3 = indices[i + 2]; //Solo me importan los que tienen un vertice con u=1(fin de la textura) y otro menor a 0.5 (comienzo de la textura) if ((!esPolo(vertices[i1]) && vertices[i1].Tu < U0p5) || (!esPolo(vertices[i2]) && vertices[i2].Tu < U0p5) || (!esPolo(vertices[i3]) && vertices[i3].Tu < U0p5)) { List <int> u1 = new List <int>(); List <int> um = new List <int>(); //Clasifico cada vertice segun su Tu1 for (int j = 0; j < 3; j++) { if (vertices[indices[i + j]].Tu == U1 || esPolo(vertices[indices[i + j]])) { u1.Add(i + j); } else if (vertices[indices[i + j]].Tu < U0p5) { um.Add(i + j); } } if (um.Count == 1 && !(esPolo(vertices[indices[u1[0]]]) && vertices[indices[um[0]]].X >= 0)) { //Casos: //2 vertices con u=1 o uno con u=1 y otro con u>0.5 //1 vertice es el polo, y uno de los vertices esta al final de la textura y otro al principio //La coordenada textura del de u >0.5 pasa a ser 1+u indices[um[0]] = dupWithU(vertices, indices, duplicados, um[0], vertices[indices[um[0]]].Tu + UVTiling.X); } else if (!esPolo(vertices[indices[u1[0]]])) { // Caso: // 1 vertice con u=1 y dos con u<0.5 // El u del vertice con u=1 pasa a ser 0 indices[u1[0]] = dupWithU(vertices, indices, duplicados, u1[0], UVOffset.X); } } } } } //Fix polos for (int p = 0; p < 2; p++) { bool first = true; for (int i = 0; i < indices.Count; i += 3)//Por cada triangulo { int iipolo = i; for (; iipolo < i + 3 && indices[iipolo] != polos[p]; iipolo++) { ; } //Si un vertice es el polo if (iipolo < i + 3) { Vertex.PositionColoredTexturedNormal[] u = new Vertex.PositionColoredTexturedNormal[2]; int n = 0; //Guardo los vertices que no son polos. for (int j = 0; j < 3; j++) { if (i + j != iipolo) { u[n++] = vertices[indices[i + j]]; } } float minU = FastMath.Min(u[0].Tu, u[1].Tu); Vertex.PositionColoredTexturedNormal pole = vertices[polos[p]]; //Chequea que no sea un triangulo rectangulo Vertex.PositionColoredTexturedNormal zeroXZ = u[0]; bool noRectangulo = false; if (u[0].X != 0 && u[0].Z != 0) { zeroXZ = u[0]; } else if (u[1].X != 0 && u[1].Z != 0) { zeroXZ = u[1]; } else { noRectangulo = true; } //Interpolo Tu1 if (basePoly.Equals(eBasePoly.ICOSAHEDRON) || noRectangulo) { pole.Tu = minU + FastMath.Abs(u[0].Tu - u[1].Tu) / 2; } else { pole.Tu = zeroXZ.Tu; } if (first) //Si es la primera vez que lo hago, modifico el vertice. { vertices[polos[p]] = pole; first = false; } else //Sino lo duplico. { indices[iipolo] = vertices.Count; vertices.Add(pole); } } } } }
protected bool esPolo(Vertex.PositionColoredTexturedNormal v) { return(v.X == 0 && v.Z == 0); }