/// <summary> /// Radio del BoundingBox /// </summary> public float calculateBoxRadius() { float rsq = calculateBoxRadiusSquare(); return(FastMath.Sqrt(rsq)); }
/// <summary> /// Construye el mesh del BoundingSphere /// </summary> private void updateValues() { if (vertices == null) { int verticesCount = (SPHERE_MESH_RESOLUTION * 2 + 2) * 3; this.vertices = new CustomVertex.PositionColored[verticesCount]; } int index = 0; float step = FastMath.TWO_PI / (float)SPHERE_MESH_RESOLUTION; // Plano XY for (float a = 0f; a <= FastMath.TWO_PI; a += step) { vertices[index++] = new CustomVertex.PositionColored(new Vector3(FastMath.Cos(a) * radius, FastMath.Sin(a) * radius, 0f) + center, renderColor); vertices[index++] = new CustomVertex.PositionColored(new Vector3(FastMath.Cos(a + step) * radius, FastMath.Sin(a + step) * radius, 0f) + center, renderColor); } // Plano XZ for (float a = 0f; a <= FastMath.TWO_PI; a += step) { vertices[index++] = new CustomVertex.PositionColored(new Vector3(FastMath.Cos(a) * radius, 0f, FastMath.Sin(a) * radius) + center, renderColor); vertices[index++] = new CustomVertex.PositionColored(new Vector3(FastMath.Cos(a + step) * radius, 0f, FastMath.Sin(a + step) * radius) + center, renderColor); } // Plano YZ for (float a = 0f; a <= FastMath.TWO_PI; a += step) { vertices[index++] = new CustomVertex.PositionColored(new Vector3(0f, FastMath.Cos(a) * radius, FastMath.Sin(a) * radius) + center, renderColor); vertices[index++] = new CustomVertex.PositionColored(new Vector3(0f, FastMath.Cos(a + step) * radius, FastMath.Sin(a + step) * radius) + center, renderColor); } }
/// <summary> /// Devuelve el menor valor de los 3 componentes del vector /// </summary> /// <param name="v">Vector</param> /// <returns>Menor valor de los tres</returns> public static float min(Vector3 v) { return(FastMath.Min(FastMath.Min(v.X, v.Y), v.Z)); }
/// <summary> /// Aplica el valor absoluto a todos los componentes del vector /// </summary> /// <param name="v">Vector</param> /// <returns>Vector resultante</returns> public static Vector3 abs(Vector3 v) { return(new Vector3(FastMath.Abs(v.X), FastMath.Abs(v.Y), FastMath.Abs(v.Z))); }
/// <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> /// Vuelve a crear la esfera si hubo cambio en el nivel de detalle, color o coordenadas de textura o si ForceUpdate esta en true. /// </summary> public virtual void updateValues() { if (!mustUpdate && !ForceUpdate) { return; } if (indexBuffer != null && !indexBuffer.Disposed) { indexBuffer.Dispose(); } if (vertexBuffer != null && !vertexBuffer.Disposed) { vertexBuffer.Dispose(); } //Obtengo las posiciones de los vertices e indices de la esfera List <Vector3> positions; createSphereSubdividingAPolyhedron(out positions, out indices); /////// vertices = new List <Vertex.PositionColoredTexturedNormal>(); List <int> iverticesU1 = new List <int>(); int[] polos = new int[2]; int p = 0; int c = color.ToArgb(); float twoPi = FastMath.TWO_PI; //Creo la lista de vertices for (int i = 0; i < positions.Count; i++) { Vector3 pos = positions[i]; float u = 0.5f + FastMath.Atan2(pos.Z, pos.X) / twoPi; float v = 0.5f - 2 * FastMath.Asin(pos.Y) / twoPi; vertices.Add(new Vertex.PositionColoredTexturedNormal(pos, c, UVTiling.X * u + UVOffset.X, UVTiling.Y * v + UVOffset.Y, pos)); if (u == 1 || esPolo(vertices[i])) { iverticesU1.Add(i); if (u != 1) { polos[p++] = i; } } } //Corrijo los triangulos que tienen mal las coordenadas debido a vertices compartidos fixTexcoords(vertices, indices, iverticesU1, polos); verticesCount = vertices.Count; triangleCount = indices.Count / 3; Device d3dDevice = GuiController.Instance.D3dDevice; vertexBuffer = new VertexBuffer(typeof(Vertex.PositionColoredTexturedNormal), verticesCount, d3dDevice, Usage.Dynamic | Usage.WriteOnly, Vertex.PositionColoredTexturedNormal.Format, Pool.Default); vertexBuffer.SetData(vertices.ToArray(), 0, LockFlags.None); indexBuffer = new IndexBuffer(typeof(int), indices.Count, d3dDevice, Usage.Dynamic | Usage.WriteOnly, Pool.Default); indexBuffer.SetData(indices.ToArray(), 0, LockFlags.None); mustUpdate = false; }