/// <inheritdoc /> public override Vector3 GetPositionAt(Vector2 uv) { float v = uv.Y; Vector3 translation = CenterCurve.GetPositionAt(v); float radius = Radius.GetValueAt(uv); return(translation + radius * GetNormalAt(uv)); }
/// <inheritdoc /> public override dvec3 GetPositionAt(dvec2 uv) { DebugUtil.AssertAllFinite(uv, nameof(uv)); double v = uv.y; dvec3 translation = CenterCurve.GetPositionAt(v); double radius = Radius.GetValueAt(uv); return(translation + radius * GetNormalAt(uv)); }
/// <inheritdoc /> public override List <Vertex> GenerateVertexList(int resolutionU, int resolutionV) { // If asked to sample at zero points, return an empty list. if (resolutionU <= 0 || resolutionV <= 0) { return(new List <Vertex>()); } var roughs = ParallelEnumerable.Range(0, resolutionV + 1).AsOrdered().SelectMany((j => { double v = (double)j / (double)resolutionV; // Find the values at each ring: dvec3 curveTangent = CenterCurve.GetTangentAt(v).Normalized; dvec3 curveNormal = CenterCurve.GetNormalAt(v).Normalized; dvec3 curveBinormal = dvec3.Cross(curveTangent, curveNormal); dvec3 translation = CenterCurve.GetPositionAt(v); double startAngle = StartAngle.GetValueAt(v); double endAngle = EndAngle.GetValueAt(v); return(Enumerable.Range(0, resolutionU).Select((i) => { double u = startAngle + (endAngle - startAngle) * (double)i / (double)resolutionU; double radius = Radius.GetValueAt(new dvec2(u, v)); // Calculate the position of the rings of vertices: dvec3 surfaceNormal = (double)Math.Cos(u) * curveNormal + (double)Math.Sin(u) * curveBinormal; dvec3 surfacePosition = translation + radius * surfaceNormal; return new Vertex((vec3)surfacePosition, (vec3)surfaceNormal); })); })); List <Vertex> output = roughs.ToList(); // Recalculate the surface normal after deformation: for (int j = 1; j < resolutionV; j++) { for (int i = 0; i < (resolutionU - 1); i++) { dvec3 surfacePosition = output[(j - 1) * resolutionU + i].Position; dvec3 du = surfacePosition - output[(j - 1) * resolutionU + i + 1].Position; dvec3 dv = surfacePosition - output[(j) * resolutionU + i].Position; // Calculate the position of the rings of vertices: dvec3 surfaceNormal = dvec3.Cross(du.Normalized, dv.Normalized); output[(j - 1) * resolutionU + i] = new Vertex((vec3)surfacePosition, (vec3)surfaceNormal); } // Stitch the end of the triangles: dvec3 surfacePosition2 = output[(j - 1) * resolutionU + resolutionU - 1].Position; dvec3 du2 = surfacePosition2 - output[(j - 1) * resolutionU].Position; dvec3 dv2 = surfacePosition2 - output[(j) * resolutionU + resolutionU - 1].Position; // Calculate the position of the rings of vertices: dvec3 surfaceNormal2 = dvec3.Cross(du2.Normalized, dv2.Normalized); output[(j - 1) * resolutionU + resolutionU - 1] = new Vertex((vec3)surfacePosition2, (vec3)surfaceNormal2); } return(output); }
/// <inheritdoc /> public override List <Vertex> GenerateVertexList(int resolutionU, int resolutionV) { List <Vertex> output = new List <Vertex>(CalculateVertexCount(resolutionU, resolutionV)); // Load all required variables: dvec3 up = dvec3.UnitZ; dvec3 pointTangent = Direction; dvec3 pointNormal = Normal; dvec3 pointBinormal = Binormal; dvec3 translation = Center; // Get the radius at the top of the hemisphere: double topRadius = Radius.GetValueAt(new dvec2(0.0, 0.5 * Math.PI)); // Generate the first point at the pole of the hemisphere: output.Add(new Vertex((vec3)(translation + topRadius * pointTangent), (vec3)pointTangent)); // Generate rings of the other points: for (int j = 1; j < (resolutionV + 1); j++) { for (int i = 0; i < resolutionU; i++) { // First find the normalized uv-coordinates, u = [0, 2pi], v = [0, 1/2pi]: double u = i / (double)resolutionU * 2.0 * Math.PI; double v = j / (double)resolutionV * 0.5 * Math.PI; // Calculate the position of the rings of vertices: double x = Math.Sin(v) * Math.Cos(u); double y = Math.Sin(v) * Math.Sin(u); double z = Math.Cos(v); double radius = Radius.GetValueAt(new dvec2(u, v)); dvec3 surfaceNormal = x * pointNormal + y * pointBinormal + z * pointTangent; dvec3 surfacePosition = translation + radius * surfaceNormal; output.Add(new Vertex((vec3)surfacePosition, (vec3)surfaceNormal)); } } // Recalculate the surface normal after deformation: for (int j = 1; j < resolutionV; j++) { for (int i = 0; i < (resolutionU - 1); i++) { dvec3 surfacePosition = output[(j - 1) * resolutionU + i + 1].Position; dvec3 du = surfacePosition - output[(j - 1) * resolutionU + i + 1 + 1].Position; dvec3 dv = surfacePosition - output[(j) * resolutionU + i + 1].Position; // Calculate the position of the rings of vertices: dvec3 surfaceNormal = dvec3.Cross(du.Normalized, dv.Normalized); output[(j - 1) * resolutionU + i + 1] = new Vertex((vec3)surfacePosition, (vec3)surfaceNormal); } // Stitch the end of the triangles: dvec3 surfacePosition2 = output[(j - 1) * resolutionU + resolutionU].Position; dvec3 du2 = surfacePosition2 - output[(j - 1) * resolutionU + 1].Position; dvec3 dv2 = surfacePosition2 - output[(j) * resolutionU + resolutionU].Position; // Calculate the position of the rings of vertices: dvec3 surfaceNormal2 = dvec3.Cross(du2.Normalized, dv2.Normalized); output[(j - 1) * resolutionU + resolutionU] = new Vertex((vec3)surfacePosition2, (vec3)surfaceNormal2); } return(output); }
/// <inheritdoc /> public override List <Vertex> GenerateVertexList(int resolutionU, int resolutionV) { List <Vertex> output = new List <Vertex>(CalculateVertexCount(resolutionU, resolutionV)); for (int j = 0; j < (resolutionV + 1); j++) { float v = (float)j / (float)resolutionV; // Find the values at each ring: Vector3 curveTangent = Vector3.Normalize(CenterCurve.GetTangentAt(v)); Vector3 curveNormal = Vector3.Normalize(CenterCurve.GetNormalAt(v)); Vector3 curveBinormal = Vector3.Cross(curveTangent, curveNormal); Vector3 translation = CenterCurve.GetPositionAt(v); float startAngle = StartAngle.GetValueAt(v); float endAngle = EndAngle.GetValueAt(v); for (int i = 0; i < resolutionU; i++) { // First find the normalized uv-coordinates, u = [0, 2pi], v = [0, 1]: float u = startAngle + (endAngle - startAngle) * (float)i / (float)resolutionU; float radius = Radius.GetValueAt(new Vector2(u, v)); // Calculate the position of the rings of vertices: Vector3 surfaceNormal = (float)Math.Cos(u) * curveNormal + (float)Math.Sin(u) * curveBinormal; Vector3 surfacePosition = translation + radius * surfaceNormal; output.Add(new Vertex(surfacePosition, surfaceNormal)); } } // Recalculate the surface normal after deformation: for (int j = 1; j < resolutionV; j++) { for (int i = 0; i < (resolutionU - 1); i++) { Vector3 surfacePosition = output[(j - 1) * resolutionU + i].Position; Vector3 du = surfacePosition - output[(j - 1) * resolutionU + i + 1].Position; Vector3 dv = surfacePosition - output[(j) * resolutionU + i].Position; // Calculate the position of the rings of vertices: Vector3 surfaceNormal = Vector3.Cross(Vector3.Normalize(du), Vector3.Normalize(dv)); output[(j - 1) * resolutionU + i] = new Vertex(surfacePosition, surfaceNormal); } // Stitch the end of the triangles: Vector3 surfacePosition2 = output[(j - 1) * resolutionU + resolutionU - 1].Position; Vector3 du2 = surfacePosition2 - output[(j - 1) * resolutionU].Position; Vector3 dv2 = surfacePosition2 - output[(j) * resolutionU + resolutionU - 1].Position; // Calculate the position of the rings of vertices: Vector3 surfaceNormal2 = Vector3.Cross(Vector3.Normalize(du2), Vector3.Normalize(dv2)); output[(j - 1) * resolutionU + resolutionU - 1] = new Vertex(surfacePosition2, surfaceNormal2); } return(output); }
public override List <Vertex> GenerateVertexList(int resolutionU, int resolutionV) { List <Vertex> output = new List <Vertex>(CalculateVertexCount(resolutionU, resolutionV)); Console.WriteLine(resolutionV); for (int j = 0; j < (resolutionV + 1); j++) { float v = (float)j / (float)resolutionV; // Generate a rotation matrix to rotate each circle in the cylinder // to align with the tangent vector of the center curve. The matrix // rotates the 'up' vector onto the 'direction' vector, using // Rodrigues' Rotation Formula: Vector3 up = new Vector3(0.0f, 0.0f, 1.0f); // To prevent division by zero, flip the direction if facing the other way: float sign = 1.0f; if (Vector3.Dot(up, CenterCurve.GetTangentAt(v)) < 0.0f) { sign = -1.0f; } Vector3 direction = Vector3.Normalize(CenterCurve.GetTangentAt(v)); Vector3 k = Vector3.Cross(sign * direction, up); Matrix4x4 identity = new Matrix4x4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); Matrix4x4 K = new Matrix4x4(0.0f, -k.Z, k.Y, 0.0f, k.Z, 0.0f, -k.X, 0.0f, -k.Y, k.X, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); Matrix4x4 rotationMatrix = identity + K + K * K * (1.0f / (1.0f + Vector3.Dot(up, sign * direction))); Matrix4x4 transformationMatrix = rotationMatrix; transformationMatrix.Translation = CenterCurve.GetPositionAt(v); float radius = Radius.GetValueAt(v); for (int i = 0; i < resolutionU; i++) { // First find the normalized uv-coordinates, u = [0, 2pi], v = [0, 1]: float u = (float)i / (float)resolutionU * 2.0f * (float)Math.PI; // Calculate the position of the rings of vertices: float x = sign * (float)Math.Cos(u); float y = sign * (float)Math.Sin(sign * u); float z = 0; Vector3 position = new Vector3(x, y, z); // Rotate the vector to orient the hemisphere correctly: Vector3 vertexPosition = Vector3.Transform(sign * radius * position, transformationMatrix); Vector3 normal = Vector3.Transform(sign * position, rotationMatrix); output.Add(new Vertex(vertexPosition, normal)); } } return(output); }