/// <summary> /// Function to create the vertex data for the sphere. /// </summary> /// <param name="vertexData">Pointer to the buffer that will hold the vertex data.</param> /// <param name="indexData">Pointer to the buffer that will hold the index data.</param> /// <param name="radius">Radius of the sphere.</param> /// <param name="textureCoordinates">Texture coordinates for the sphere.</param> /// <param name="ringCount">Number of rings in the sphere.</param> /// <param name="segmentCount">Number of segments in the sphere.</param> private void GetVertices(GorgonNativeBuffer <Vertex3D> vertexData, GorgonNativeBuffer <int> indexData, float radius, RectangleF textureCoordinates, int ringCount, int segmentCount) { int index = 0; // Current index. int vertexOffset = 0; int indexOffset = 0; float deltaRingAngle = ((float)System.Math.PI) / ringCount; float deltaSegAngle = (((float)System.Math.PI) * 2.0f) / segmentCount; Radius = radius; // Build our sphere. for (int ring = 0; ring <= ringCount; ring++) { float ringAngle = ring * deltaRingAngle; radius = ringAngle.Sin() * 0.5f * Radius; float radiusY = ringAngle.Cos() * Radius * 0.5f; for (int segment = 0; segment <= segmentCount; segment++) { var textureDelta = new DX.Vector2(1.0f - (segment / (float)segmentCount), ring / (float)ringCount); float segmentAngle = deltaSegAngle * segment; var position = new DX.Vector3(radius * segmentAngle.Sin(), radiusY, radius * segmentAngle.Cos()); DX.Vector3.Multiply(ref position, 2.0f, out DX.Vector3 normal); DX.Vector3.TransformCoordinate(ref position, ref _orientation, out position); DX.Vector3.TransformCoordinate(ref normal, ref _orientation, out normal); normal.Normalize(); // Create the vertex. textureDelta.X *= textureCoordinates.Width; textureDelta.Y *= textureCoordinates.Height; textureDelta.X += textureCoordinates.X; textureDelta.Y += textureCoordinates.Y; vertexData[vertexOffset++] = new Vertex3D { Position = new DX.Vector4(position, 1.0f), UV = textureDelta, Normal = normal }; // Add the indices and skip the last ring. if (ring == ringCount) { continue; } indexData[indexOffset++] = (index + segmentCount + 1); indexData[indexOffset++] = index; indexData[indexOffset++] = (index + segmentCount); indexData[indexOffset++] = (index + segmentCount + 1); indexData[indexOffset++] = (index + 1); indexData[indexOffset++] = index; index++; } } }
/// <summary> /// Function to calculate tangent information for bump mapping. /// </summary> /// <param name="vertexData">Buffer holding the vertices.</param> /// <param name="indexData">Buffer holding the indices.</param> protected void CalculateTangents(GorgonNativeBuffer <Vertex3D> vertexData, GorgonNativeBuffer <int> indexData) { var biTanData = new DX.Vector3[VertexCount]; var tanData = new DX.Vector3[VertexCount]; int indexOffset = 0; for (int i = 0; i < TriangleCount; ++i) { int index1 = indexData[indexOffset++]; // If we hit a strip-restart index, then skip to the next index. if ((PrimitiveType == PrimitiveType.TriangleStrip) && (index1 < 0)) { index1 = indexData[indexOffset++]; } int index2 = indexData[indexOffset++]; int index3 = indexData[indexOffset++]; Vertex3D vertex1 = vertexData[index1]; Vertex3D vertex2 = vertexData[index2]; Vertex3D vertex3 = vertexData[index3]; DX.Vector4.Subtract(ref vertex2.Position, ref vertex1.Position, out DX.Vector4 deltaPos1); DX.Vector4.Subtract(ref vertex3.Position, ref vertex1.Position, out DX.Vector4 deltaPos2); DX.Vector2.Subtract(ref vertex2.UV, ref vertex1.UV, out DX.Vector2 deltaUV1); DX.Vector2.Subtract(ref vertex3.UV, ref vertex1.UV, out DX.Vector2 deltaUV2); float denom = ((deltaUV1.X * deltaUV2.Y) - (deltaUV1.Y * deltaUV2.X)); float r = 0.0f; if (!denom.EqualsEpsilon(0)) { r = 1.0f / denom; } var tangent = new DX.Vector3(((deltaUV2.Y * deltaPos1.X) - (deltaUV1.Y * deltaPos2.X)) * r, ((deltaUV2.Y * deltaPos1.Y) - (deltaUV1.Y * deltaPos2.Y)) * r, ((deltaUV2.Y * deltaPos1.Z) - (deltaUV1.Y * deltaPos2.Z)) * r); var biTangent = new DX.Vector3(((deltaUV1.X * deltaPos2.X) - (deltaUV2.X * deltaPos1.X)) * r, ((deltaUV1.X * deltaPos2.Y) - (deltaUV2.X * deltaPos1.Y)) * r, ((deltaUV1.X * deltaPos2.Z) - (deltaUV2.X * deltaPos1.Z)) * r); DX.Vector3.Add(ref tanData[index1], ref tangent, out tanData[index1]); DX.Vector3.Add(ref tanData[index2], ref tangent, out tanData[index2]); DX.Vector3.Add(ref tanData[index3], ref tangent, out tanData[index3]); DX.Vector3.Add(ref biTanData[index1], ref biTangent, out biTanData[index1]); DX.Vector3.Add(ref biTanData[index2], ref biTangent, out biTanData[index2]); DX.Vector3.Add(ref biTanData[index3], ref biTangent, out biTanData[index3]); } for (int i = 0; i < VertexCount; ++i) { Vertex3D vertex = vertexData[i]; DX.Vector3.Dot(ref vertex.Normal, ref tanData[i], out float dot); DX.Vector3.Multiply(ref vertex.Normal, dot, out DX.Vector3 tangent); DX.Vector3.Subtract(ref tanData[i], ref tangent, out tangent); DX.Vector3.Normalize(ref tangent, out tangent); DX.Vector3.Cross(ref vertex.Normal, ref tanData[i], out DX.Vector3 cross); DX.Vector3.Dot(ref cross, ref biTanData[i], out dot); vertexData[i] = new Vertex3D { Position = vertex.Position, Normal = vertex.Normal, UV = vertex.UV, Tangent = new DX.Vector4(tangent, dot < 0.0f ? -1.0f : 1.0f) }; } }