private void BuildVertices(int actualSegments, int actualStacks, int vertexCount) { GeometryContext.AllocateVertices(vertexCount); GeometryContext.AllocateTextureCoordinates(vertexCount); var yStart = (float)Size / 2; var yEnd = (float)-Size / 2; var yDelta = yEnd - yStart; var yAdd = yDelta / actualStacks; var startRadian = MathHelper.ToRadians((float)StartAngle); var endRadian = MathHelper.ToRadians((float)EndAngle); var deltaRadian = endRadian - startRadian; var addRadian = deltaRadian / actualSegments; var uDelta = 1f; var vDelta = 2f; var uAdd = uDelta / actualSegments; var vAdd = vDelta / actualStacks; var vertexIndex = 0; var currentY = yStart; var currentV = 0f; for (var stack = 0; stack < actualStacks; stack++) { var currentU = 0f; var currentRadian = startRadian; for (var segment = 0; segment < actualSegments; segment++) { var innerX = (float)(System.Math.Sin(currentRadian) * InnerRadius); var innerZ = (float)(System.Math.Cos(currentRadian) * InnerRadius); var innerVertex = new Vertex(innerX, currentY, innerZ); GeometryContext.SetVertex(vertexIndex, innerVertex); var textureCoordinate = new TextureCoordinate(1f - currentU, 0); GeometryContext.SetTextureCoordinate(vertexIndex, textureCoordinate); vertexIndex++; var outerX = (float)(System.Math.Sin(currentRadian) * OuterRadius); var outerZ = (float)(System.Math.Cos(currentRadian) * OuterRadius); var outerVertex = new Vertex(outerX, currentY, outerZ); GeometryContext.SetVertex(vertexIndex, outerVertex); textureCoordinate = new TextureCoordinate(1f - currentU, 1); GeometryContext.SetTextureCoordinate(vertexIndex, textureCoordinate); vertexIndex++; currentRadian += addRadian; currentU += uAdd; } currentY += yAdd; currentV += vAdd; } }
private static void SetSphericalEnvironmentMapTextureCoordinate(ref Vertex vertex, ref TextureCoordinate textureCoordinate) { var u = vertex.TransformedVectorNormalized; var n = vertex.TransformedNormal; var r = Vector.Reflect(n, u); var m = MathHelper.Sqrt((r.X * r.X) + (r.Y * r.Y) + ((r.Z + 0f) * (r.Z + 0f))); var s = (r.X / m); var t = (r.Y / m); textureCoordinate.U = (s * 0.5f) + 0.5f; textureCoordinate.V = -(t * 0.5f) + 0.5f; }
public void SetTextureCoordinate(int index, TextureCoordinate textureCoordinate) { TextureCoordinates[index] = textureCoordinate; }
public void AllocateTextureCoordinates(int count) { TextureCoordinates = new TextureCoordinate[count]; }
public static void Draw(IBuffers buffers, ISpanRenderer renderer, TriangleShade shade, Face face, Vertex[] vertices, TextureCoordinate[] textureCoordinates) { var vertexA = vertices[face.A]; var vertexB = vertices[face.B]; var vertexC = vertices[face.C]; var textureA = ZeroTextureCoordinate; var textureB = ZeroTextureCoordinate; var textureC = ZeroTextureCoordinate; Image image = null; ImageContext texture = null; var useTexture = false; if( null != face.Material && null != face.Material.DiffuseMap) { useTexture = true; image = face.Material.DiffuseMap; texture = face.Material.DiffuseMap.ImageContext as ImageContext; textureA = textureCoordinates[face.DiffuseA]; textureB = textureCoordinates[face.DiffuseB]; textureC = textureCoordinates[face.DiffuseC]; } /* SetSphericalEnvironmentMapTextureCoordinate(ref vertexA, ref textureA); SetSphericalEnvironmentMapTextureCoordinate(ref vertexB, ref textureB); SetSphericalEnvironmentMapTextureCoordinate(ref vertexC, ref textureC); */ GetSortedPoints(ref vertexA, ref vertexB, ref vertexC, ref textureA, ref textureB, ref textureC); var interpolator = GetInterpolatorForFace(face, shade); var secondaryStartY = (int)(vertexB.TranslatedScreenCoordinates.Y - vertexA.TranslatedScreenCoordinates.Y); var spreadCount = ((int)(vertexC.TranslatedScreenCoordinates.Y - vertexA.TranslatedScreenCoordinates.Y)) + 1; interpolator.SetPoint(0, (int)vertexA.TranslatedScreenCoordinates.X, (int)vertexC.TranslatedScreenCoordinates.X); interpolator.SetPoint(1, (int)vertexA.TranslatedScreenCoordinates.X, (int)vertexB.TranslatedScreenCoordinates.X, (int)vertexB.TranslatedScreenCoordinates.X, (int)vertexC.TranslatedScreenCoordinates.X, secondaryStartY); interpolator.SetPoint(2, vertexA.DepthBufferAdjustedZ, vertexC.DepthBufferAdjustedZ); interpolator.SetPoint(3, vertexA.DepthBufferAdjustedZ, vertexB.DepthBufferAdjustedZ, vertexB.DepthBufferAdjustedZ, vertexC.DepthBufferAdjustedZ, secondaryStartY); if (useTexture) { interpolator.SetPoint(4, textureA.U, textureC.U); interpolator.SetPoint(5, textureA.U, textureB.U, textureB.U, textureC.U, secondaryStartY); interpolator.SetPoint(6, textureA.V, textureC.V); interpolator.SetPoint(7, textureA.V, textureB.V, textureB.V, textureC.V, secondaryStartY); } var color = Color.FromArgb(0xff, 0xff, 0xff, 0xff); if (shade == TriangleShade.Gouraud && !useTexture) { var vertexAColor = vertexA.Color; var vertexBColor = vertexB.Color; var vertexCColor = vertexC.Color; interpolator.SetPoint(4, vertexAColor.RedAsFloat, vertexCColor.RedAsFloat); interpolator.SetPoint(5, vertexAColor.RedAsFloat, vertexBColor.RedAsFloat, vertexBColor.RedAsFloat, vertexCColor.RedAsFloat, secondaryStartY); interpolator.SetPoint(6, vertexAColor.GreenAsFloat, vertexCColor.GreenAsFloat); interpolator.SetPoint(7, vertexAColor.GreenAsFloat, vertexBColor.GreenAsFloat, vertexBColor.GreenAsFloat, vertexCColor.GreenAsFloat, secondaryStartY); interpolator.SetPoint(8, vertexAColor.BlueAsFloat, vertexCColor.BlueAsFloat); interpolator.SetPoint(9, vertexAColor.BlueAsFloat, vertexBColor.BlueAsFloat, vertexBColor.BlueAsFloat, vertexCColor.BlueAsFloat, secondaryStartY); interpolator.SetPoint(10, vertexAColor.AlphaAsFloat, vertexCColor.AlphaAsFloat); interpolator.SetPoint(11, vertexAColor.AlphaAsFloat, vertexBColor.AlphaAsFloat, vertexBColor.AlphaAsFloat, vertexCColor.AlphaAsFloat, secondaryStartY); } else { color = face.Color; } interpolator.Interpolate(spreadCount); var yPosition = vertexA.TranslatedScreenCoordinates.Y; var clip = false; if( null == buffers ) { return; } for (var index = 0; index < spreadCount; index++) { if( yPosition < 0 || yPosition >= buffers.Height ) { clip = true; } else { clip = false; } var span = GetSpan(index, interpolator, vertexA, useTexture); if (null != span && !clip ) { var actualSpan = (Span)span; var swapIndex = ((Span)span).Swap ? 1 : 0; actualSpan.ZStart = interpolator.Points[2 + swapIndex].InterpolatedValues[index]; actualSpan.ZEnd = interpolator.Points[3 - swapIndex].InterpolatedValues[index]; switch (shade) { case TriangleShade.Flat: { if (useTexture) { renderer.Texture(buffers, actualSpan, image, texture); } else { renderer.Flat(buffers, actualSpan, color); } } break; case TriangleShade.Gouraud: { if (useTexture) { renderer.Texture(buffers, actualSpan, image, texture); } else { actualSpan.ColorStart.RedAsFloat = interpolator.Points[4 + swapIndex].InterpolatedValues[index]; actualSpan.ColorEnd.RedAsFloat = interpolator.Points[5 - swapIndex].InterpolatedValues[index]; actualSpan.ColorStart.GreenAsFloat = interpolator.Points[6 + swapIndex].InterpolatedValues[index]; actualSpan.ColorEnd.GreenAsFloat = interpolator.Points[7 - swapIndex].InterpolatedValues[index]; actualSpan.ColorStart.BlueAsFloat = interpolator.Points[8 + swapIndex].InterpolatedValues[index]; actualSpan.ColorEnd.BlueAsFloat = interpolator.Points[9 - swapIndex].InterpolatedValues[index]; actualSpan.ColorStart.AlphaAsFloat = interpolator.Points[10 + swapIndex].InterpolatedValues[index]; actualSpan.ColorEnd.AlphaAsFloat = interpolator.Points[11 - swapIndex].InterpolatedValues[index]; renderer.Gouraud(buffers, actualSpan); } } break; } } yPosition++; } }
private static void GetSortedPoints(ref Vertex vertexA, ref Vertex vertexB, ref Vertex vertexC, ref TextureCoordinate textureA, ref TextureCoordinate textureB, ref TextureCoordinate textureC) { var point1 = vertexA; var point2 = vertexB; var point3 = vertexC; if (point2.TranslatedScreenCoordinates.Y < point1.TranslatedScreenCoordinates.Y) { var p = point1; point1 = point2; point2 = p; var t = textureA; textureA = textureB; textureB = t; } if (point3.TranslatedScreenCoordinates.Y < point2.TranslatedScreenCoordinates.Y) { var p = point2; point2 = point3; point3 = p; var t = textureB; textureB = textureC; textureC = t; } if (point2.TranslatedScreenCoordinates.Y < point1.TranslatedScreenCoordinates.Y) { var p = point1; point1 = point2; point2 = p; var t = textureA; textureA = textureB; textureB = t; } vertexA = point1; vertexB = point2; vertexC = point3; }
private void BuildVertices(int actualSegments, int actualStacks, double startRadian, double radianAdd, float currentY, double currentRadius, float currentV, float uAdd, double radiusAdd, float yAdd, float vAdd) { Vertex vertex; var vertexCount = (actualStacks * (actualSegments + 1)); var vertexIndex = 0; GeometryContext.AllocateVertices(vertexCount); GeometryContext.AllocateTextureCoordinates(vertexCount); for (var y = 0; y < actualStacks; y++) { var currentU = 0f; var currentRadian = startRadian; var centerTextureCoordinate = new TextureCoordinate(0.5f, 0.5f); vertex = new Vertex(0, currentY, 0); GeometryContext.SetVertex(vertexIndex, vertex); GeometryContext.SetTextureCoordinate(vertexIndex, centerTextureCoordinate); vertexIndex++; for (var x = 0; x < actualSegments; x++) { var currentX = (float)(System.Math.Sin(currentRadian) * currentRadius); var currentZ = (float)(System.Math.Cos(currentRadian) * currentRadius); vertex = new Vertex(currentX, currentY, currentZ); GeometryContext.SetVertex(vertexIndex, vertex); var textureCoordinate = new TextureCoordinate(1f - currentU, currentV); GeometryContext.SetTextureCoordinate(vertexIndex, textureCoordinate); vertexIndex++; currentRadian += radianAdd; currentU += uAdd; } currentRadius += radiusAdd; currentY -= yAdd; currentV += vAdd; } }