private void ParseVertices(PrimitiveData data, byte[] bytes) { if (data.NumVertices == 0) { throw new ArgumentOutOfRangeException(nameof(data), "Cannot add vertices when size is unknown."); } if (bytes.Length < data.NumVertices * Vertex3DNoTex2.Size) { throw new ArgumentOutOfRangeException($"Tried to read {data.NumVertices} vertices for primitive item \"${data.Name}\" (${data.StorageName}), but only ${bytes.Length} bytes available."); } if (!(GetValue(data) is Mesh mesh)) { throw new ArgumentException("BiffVertices attribute must sit on a Mesh object."); } var vertices = new Vertex3DNoTex2[data.NumVertices]; using (var stream = new MemoryStream(bytes)) using (var reader = new BinaryReader(stream)) { for (var i = 0; i < data.NumVertices; i++) { vertices[i] = new Vertex3DNoTex2(reader); } } mesh.Vertices = vertices; }
private Mesh GenerateFlatRightWall(float tableWidth, float tableHeight, RampVertex rv) { var invTableWidth = 1.0f / tableWidth; var invTableHeight = 1.0f / tableHeight; var numVertices = rv.VertexCount * 2; var numIndices = (rv.VertexCount - 1) * 6; var mesh = new Mesh("RightWall") { Vertices = new Vertex3DNoTex2[numVertices], Indices = new int[numIndices] }; for (var i = 0; i < rv.VertexCount; i++) { var rgv3d1 = new Vertex3DNoTex2(); var rgv3d2 = new Vertex3DNoTex2(); rgv3d1.X = rv.RgvLocal[i].X; rgv3d1.Y = rv.RgvLocal[i].Y; rgv3d1.Z = rv.PointHeights[i]; rgv3d2.X = rv.RgvLocal[i].X; rgv3d2.Y = rv.RgvLocal[i].Y; rgv3d2.Z = (rv.PointHeights[i] + _data.RightWallHeightVisible); if (_data.ImageAlignment == RampImageAlignment.ImageModeWorld) { rgv3d1.Tu = rgv3d1.X * invTableWidth; rgv3d1.Tv = rgv3d1.Y * invTableHeight; } else { rgv3d1.Tu = 0; rgv3d1.Tv = rv.PointRatios[i]; } rgv3d2.Tu = rgv3d1.Tu; rgv3d2.Tv = rgv3d1.Tv; mesh.Vertices[i * 2] = rgv3d1; mesh.Vertices[i * 2 + 1] = rgv3d2; if (i == rv.VertexCount - 1) { break; } mesh.Indices[i * 6] = i * 2; mesh.Indices[i * 6 + 1] = i * 2 + 1; mesh.Indices[i * 6 + 2] = i * 2 + 3; mesh.Indices[i * 6 + 3] = i * 2; mesh.Indices[i * 6 + 4] = i * 2 + 3; mesh.Indices[i * 6 + 5] = i * 2 + 2; } Mesh.ComputeNormals(mesh.Vertices, numVertices, mesh.Indices, (rv.VertexCount - 1) * 6); return(mesh); }
private static void AssertVerticesEqual(ObjVector4 expected, Vertex3DNoTex2 actual, float threshold, bool switchZ = false) { var sign = switchZ ? -1 : 1; actual.X.Should().BeApproximately(expected.X, threshold); actual.Y.Should().BeApproximately(expected.Y, threshold); actual.Z.Should().BeApproximately(sign * expected.Z, threshold); }
private static void AssertVerticesEqual(ObjVector4 expected, Vertex3DNoTex2 actual, double threshold = FloatThresholdComparer.Threshold) { Assert.Equal(expected.X, actual.X, new FloatThresholdComparer(threshold)); Assert.Equal(expected.Y, actual.Y, new FloatThresholdComparer(threshold)); Assert.Equal(expected.Z, actual.Z, new FloatThresholdComparer(threshold)); }
private Mesh CalculateBuiltinOriginal() { var mesh = new Mesh(_data.Name); // this recalculates the Original Vertices -> should be only called, when sides are altered. var outerRadius = -0.5f / MathF.Cos(MathF.PI / _data.Sides); var addAngle = 2.0f * MathF.PI / _data.Sides; var offsAngle = MathF.PI / _data.Sides; var minX = Constants.FloatMax; var minY = Constants.FloatMax; var maxX = -Constants.FloatMax; var maxY = -Constants.FloatMax; mesh.Vertices = new Vertex3DNoTex2[4 * _data.Sides + 2]; // middle point top mesh.Vertices[0] = new Vertex3DNoTex2 { X = 0.0f, Y = 0.0f, Z = 0.5f }; // middle point bottom mesh.Vertices[_data.Sides + 1] = new Vertex3DNoTex2 { X = 0.0f, Y = 0.0f, Z = -0.5f }; for (var i = 0; i < _data.Sides; ++i) { var currentAngle = addAngle * i + offsAngle; // calculate Top var topVert = new Vertex3DNoTex2 { // top point at side X = MathF.Sin(currentAngle) * outerRadius, Y = MathF.Cos(currentAngle) * outerRadius, Z = 0.5f }; mesh.Vertices[i + 1] = topVert; // calculate bottom var bottomVert = new Vertex3DNoTex2 { // bottom point at side X = topVert.X, Y = topVert.Y, Z = -0.5f }; mesh.Vertices[i + 1 + _data.Sides + 1] = bottomVert; // calculate sides mesh.Vertices[_data.Sides * 2 + 2 + i] = topVert.Clone(); // sideTopVert mesh.Vertices[_data.Sides * 3 + 2 + i] = bottomVert.Clone(); // sideBottomVert // calculate bounds for X and Y if (topVert.X < minX) { minX = topVert.X; } if (topVert.X > maxX) { maxX = topVert.X; } if (topVert.Y < minY) { minY = topVert.Y; } if (topVert.Y > maxY) { maxY = topVert.Y; } } // these have to be replaced for image mapping var middle = mesh.Vertices[0]; // middle point top middle.Tu = 0.25f; // /4 middle.Tv = 0.25f; // /4 middle = mesh.Vertices[_data.Sides + 1]; // middle point bottom middle.Tu = 0.25f * 3.0f; // /4*3 middle.Tv = 0.25f; // /4 var invX = 0.5f / (maxX - minX); var invY = 0.5f / (maxY - minY); var invS = 1.0f / _data.Sides; for (var i = 0; i < _data.Sides; i++) { var topVert = mesh.Vertices[i + 1]; // top point at side topVert.Tu = (topVert.X - minX) * invX; topVert.Tv = (topVert.Y - minY) * invY; var bottomVert = mesh.Vertices[i + 1 + _data.Sides + 1]; // bottom point at side bottomVert.Tu = topVert.Tu + 0.5f; bottomVert.Tv = topVert.Tv; var sideTopVert = mesh.Vertices[_data.Sides * 2 + 2 + i]; var sideBottomVert = mesh.Vertices[_data.Sides * 3 + 2 + i]; sideTopVert.Tu = i * invS; sideTopVert.Tv = 0.5f; sideBottomVert.Tu = sideTopVert.Tu; sideBottomVert.Tv = 1.0f; } // So how many indices are needed? // 3 per Triangle top - we have m_sides triangles -> 0, 1, 2, 0, 2, 3, 0, 3, 4, ... // 3 per Triangle bottom - we have m_sides triangles // 6 per Side at the side (two triangles form a rectangle) - we have m_sides sides // == 12 * m_sides // * 2 for both cullings (m_DrawTexturesInside == true) // == 24 * m_sides // this will also be the initial sorting, when depths, Vertices and Indices are recreated, because calculateRealTimeOriginal is called. // 2 restore indices // check if anti culling is enabled: if (_data.DrawTexturesInside) { mesh.Indices = new int[_data.Sides * 24]; // draw yes everything twice // restore indices for (var i = 0; i < _data.Sides; i++) { var tmp = i == _data.Sides - 1 ? 1 : i + 2; // wrapping around // top mesh.Indices[i * 6] = 0; mesh.Indices[i * 6 + 1] = i + 1; mesh.Indices[i * 6 + 2] = tmp; mesh.Indices[i * 6 + 3] = 0; mesh.Indices[i * 6 + 4] = tmp; mesh.Indices[i * 6 + 5] = i + 1; var tmp2 = tmp + 1; // bottom mesh.Indices[6 * (i + _data.Sides)] = _data.Sides + 1; mesh.Indices[6 * (i + _data.Sides) + 1] = _data.Sides + tmp2; mesh.Indices[6 * (i + _data.Sides) + 2] = _data.Sides + 2 + i; mesh.Indices[6 * (i + _data.Sides) + 3] = _data.Sides + 1; mesh.Indices[6 * (i + _data.Sides) + 4] = _data.Sides + 2 + i; mesh.Indices[6 * (i + _data.Sides) + 5] = _data.Sides + tmp2; // sides mesh.Indices[12 * (i + _data.Sides)] = _data.Sides * 2 + tmp2; mesh.Indices[12 * (i + _data.Sides) + 1] = _data.Sides * 2 + 2 + i; mesh.Indices[12 * (i + _data.Sides) + 2] = _data.Sides * 3 + 2 + i; mesh.Indices[12 * (i + _data.Sides) + 3] = _data.Sides * 2 + tmp2; mesh.Indices[12 * (i + _data.Sides) + 4] = _data.Sides * 3 + 2 + i; mesh.Indices[12 * (i + _data.Sides) + 5] = _data.Sides * 3 + tmp2; mesh.Indices[12 * (i + _data.Sides) + 6] = _data.Sides * 2 + tmp2; mesh.Indices[12 * (i + _data.Sides) + 7] = _data.Sides * 3 + 2 + i; mesh.Indices[12 * (i + _data.Sides) + 8] = _data.Sides * 2 + 2 + i; mesh.Indices[12 * (i + _data.Sides) + 9] = _data.Sides * 2 + tmp2; mesh.Indices[12 * (i + _data.Sides) + 10] = _data.Sides * 3 + tmp2; mesh.Indices[12 * (i + _data.Sides) + 11] = _data.Sides * 3 + 2 + i; } } else { // only no out-facing polygons // restore indices mesh.Indices = new int[_data.Sides * 12]; for (var i = 0; i < _data.Sides; i++) { var tmp = i == _data.Sides - 1 ? 1 : i + 2; // wrapping around // top mesh.Indices[i * 3] = 0; mesh.Indices[i * 3 + 2] = i + 1; mesh.Indices[i * 3 + 1] = tmp; //SetNormal(mesh.Vertices[0], &mesh.Indices[i+3], 3); // see below var tmp2 = tmp + 1; // bottom mesh.Indices[3 * (i + _data.Sides)] = _data.Sides + 1; mesh.Indices[3 * (i + _data.Sides) + 1] = _data.Sides + 2 + i; mesh.Indices[3 * (i + _data.Sides) + 2] = _data.Sides + tmp2; //SetNormal(mesh.Vertices[0], &mesh.Indices[3*(i+_data.Sides)], 3); // see below // sides mesh.Indices[6 * (i + _data.Sides)] = _data.Sides * 2 + tmp2; mesh.Indices[6 * (i + _data.Sides) + 1] = _data.Sides * 3 + 2 + i; mesh.Indices[6 * (i + _data.Sides) + 2] = _data.Sides * 2 + 2 + i; mesh.Indices[6 * (i + _data.Sides) + 3] = _data.Sides * 2 + tmp2; mesh.Indices[6 * (i + _data.Sides) + 4] = _data.Sides * 3 + tmp2; mesh.Indices[6 * (i + _data.Sides) + 5] = _data.Sides * 3 + 2 + i; } } //SetNormal(mesh.Vertices[0], &mesh.Indices[0], m_mesh.NumIndices()); // SetNormal only works for plane polygons Mesh.ComputeNormals(mesh.Vertices, mesh.Vertices.Length, mesh.Indices, mesh.Indices.Length); return(mesh); }
private Mesh GenerateTopMesh(Table.Table table) { var topMesh = new Mesh("Top"); var vVertex = DragPoint.GetRgVertex <RenderVertex2D, CatmullCurve2DCatmullCurveFactory>(_data.DragPoints); var numVertices = vVertex.Length; var rgNormal = new Vertex2D[numVertices]; for (var i = 0; i < numVertices; i++) { var pv1 = vVertex[i]; var pv2 = vVertex[i < numVertices - 1 ? i + 1 : 0]; var dx = pv1.X - pv2.X; var dy = pv1.Y - pv2.Y; if (dx != 0.0f || dy != 0.0f) { var invLen = 1.0f / MathF.Sqrt(dx * dx + dy * dy); rgNormal[i] = new Vertex2D { X = dy * invLen, Y = dx * invLen }; } else { rgNormal[i] = new Vertex2D { X = 0.0f, Y = 0.0f }; } } // draw top var vPoly = new List <int>(new int[numVertices]); for (var i = 0; i < numVertices; i++) { vPoly[i] = i; } topMesh.Indices = Mesh.PolygonToTriangles(vVertex, vPoly); var numPolys = topMesh.Indices.Length / 3; if (numPolys == 0) { // no polys to render leave vertex buffer undefined return(null); } var heightNotDropped = _data.HeightTop * table.GetScaleZ(); var heightDropped = _data.HeightBottom * table.GetScaleZ() + 0.1; var invTableWidth = 1.0f / table.Width; var invTableHeight = 1.0f / table.Height; Vertex3DNoTex2[][] vertsTop = { new Vertex3DNoTex2[numVertices], new Vertex3DNoTex2[numVertices], new Vertex3DNoTex2[numVertices] }; for (var i = 0; i < numVertices; i++) { var pv0 = vVertex[i]; vertsTop[0][i] = new Vertex3DNoTex2 { X = pv0.X, Y = pv0.Y, Z = heightNotDropped + table.TableHeight, Tu = pv0.X * invTableWidth, Tv = pv0.Y * invTableHeight, Nx = 0, Ny = 0, Nz = 1.0f }; vertsTop[1][i] = new Vertex3DNoTex2 { X = pv0.X, Y = pv0.Y, Z = (float)heightDropped, Tu = pv0.X * invTableWidth, Tv = pv0.Y * invTableHeight, Nx = 0, Ny = 0, Nz = 1.0f }; vertsTop[2][i] = new Vertex3DNoTex2 { X = pv0.X, Y = pv0.Y, Z = _data.HeightBottom, Tu = pv0.X * invTableWidth, Tv = pv0.Y * invTableHeight, Nx = 0, Ny = 0, Nz = -1.0f }; } topMesh.Vertices = vertsTop[0]; return(topMesh); }
public static Vector3 ToUnityUvVector2(this Vertex3DNoTex2 vertex) { return(new Vector2(vertex.Tu, -vertex.Tv)); }
public static Vector3 ToUnityNormalVector3(this Vertex3DNoTex2 vertex) { return(new Vector3(vertex.Nx, vertex.Ny, vertex.Nz)); }
public static Vector3 ToUnityVector3(this Vertex3DNoTex2 vertex) { return(new Vector3(vertex.X, vertex.Y, vertex.Z)); }
public Vertex3DNoTex2[] BuildRodVertices(int frame) { if (_lathePoints == 0) { CalculateArraySizes(); } var vertices = new Vertex3DNoTex2[_latheVts]; var yTip = _beginY + _dyPerFrame * frame; var tu = 0.51f; var stepU = 1.0f / _circlePoints; var i = 0; for (var l = 0; l < _circlePoints; l++, tu += stepU) { // Go down the long axis, adding a vertex for each point // in the descriptor list at the current lathe angle. if (tu > 1.0f) { tu -= 1.0f; } var angle = (float)(MathF.PI * 2.0) / _circlePoints * l; var sn = MathF.Sin(angle); var cs = MathF.Cos(angle); for (var m = 0; m < _lathePoints; m++) { ref var c = ref _desc.c[m]; // get the current point's coordinates var y = c.y + yTip; var r = c.r; var tv = c.tv; // the last coordinate is always the bottom of the rod if (m + 1 == _lathePoints) { // set the end point y = _rodY; // Figure the texture mapping for the rod position. This is // important because we draw the rod with varying length - // the part that's pulled back beyond the 'rodY' point is // hidden. We want the texture to maintain the same apparent // position and scale in each frame, so we need to figure the // proportional point of the texture at our cut-off point on // the object surface. var ratio = frame * _invScale; tv = vertices[m - 1].Tv + (tv - vertices[m - 1].Tv) * ratio; } vertices[i++] = new Vertex3DNoTex2 { X = r * (sn * _data.Width) + _data.Center.X, Y = y, Z = (r * (cs * _data.Width) + _data.Width + _zHeight) * _zScale, Nx = c.nx * sn, Ny = c.ny, Nz = -c.nx * cs, Tu = tu, Tv = tv }; } }
private Vertex3DNoTex2[] CreateWire(int numRings, int numSegments, IReadOnlyList <Vertex2D> midPoints, IReadOnlyList <float> initialHeights) { var vertices = new Vertex3DNoTex2[numRings * numSegments]; var prev = new Vertex3D(); var index = 0; for (var i = 0; i < numRings; i++) { var i2 = i == numRings - 1 ? i : i + 1; var height = initialHeights[i]; var tangent = new Vertex3D( midPoints[i2].X - midPoints[i].X, midPoints[i2].Y - midPoints[i].Y, initialHeights[i2] - initialHeights[i] ); if (i == numRings - 1) { // for the last spline point use the previous tangent again, otherwise we won't see the complete wire (it stops one control point too early) tangent.X = midPoints[i].X - midPoints[i - 1].X; tangent.Y = midPoints[i].Y - midPoints[i - 1].Y; } Vertex3D biNormal; Vertex3D normal; if (i == 0) { var up = new Vertex3D( midPoints[i2].X + midPoints[i].X, midPoints[i2].Y + midPoints[i].Y, initialHeights[i2] - height ); normal = Vertex3D.CrossProduct(tangent, up); //normal biNormal = Vertex3D.CrossProduct(tangent, normal); } else { normal = Vertex3D.CrossProduct(prev, tangent); biNormal = Vertex3D.CrossProduct(tangent, normal); } biNormal.Normalize(); normal.Normalize(); prev = biNormal; var invNumRings = 1.0f / numRings; var invNumSegments = 1.0f / numSegments; var u = i * invNumRings; for (var j = 0; j < numSegments; j++, index++) { var v = (j + u) * invNumSegments; var tmp = Vertex3D.GetRotatedAxis(j * (360.0f * invNumSegments), tangent, normal) * (_data.WireDiameter * 0.5f); vertices[index] = new Vertex3DNoTex2 { X = midPoints[i].X + tmp.X, Y = midPoints[i].Y + tmp.Y, Z = height + tmp.Z, Tu = u, Tv = v }; // normals var n = new Vertex3D( vertices[index].X - midPoints[i].X, vertices[index].Y - midPoints[i].Y, vertices[index].Z - height ); var len = 1.0f / MathF.Sqrt(n.X * n.X + n.Y * n.Y + n.Z * n.Z); vertices[index].Nx = n.X * len; vertices[index].Ny = n.Y * len; vertices[index].Nz = n.Z * len; } } return(vertices); }
private Mesh GenerateFlatFloorMesh(Table.Table table, RampVertex rv) { var invTableWidth = 1.0f / table.Width; var invTableHeight = 1.0f / table.Height; var numVertices = rv.VertexCount * 2; var numIndices = (rv.VertexCount - 1) * 6; var mesh = new Mesh("Floor") { Vertices = new Vertex3DNoTex2[numVertices], Indices = new int[numIndices] }; for (var i = 0; i < rv.VertexCount; i++) { var rgv3d1 = new Vertex3DNoTex2(); var rgv3d2 = new Vertex3DNoTex2(); rgv3d1.X = rv.RgvLocal[i].X; rgv3d1.Y = rv.RgvLocal[i].Y; rgv3d1.Z = rv.PointHeights[i] * table.GetScaleZ(); rgv3d2.X = rv.RgvLocal[rv.VertexCount * 2 - i - 1].X; rgv3d2.Y = rv.RgvLocal[rv.VertexCount * 2 - i - 1].Y; rgv3d2.Z = rgv3d1.Z; if (_data.Image != null) { if (_data.ImageAlignment == RampImageAlignment.ImageModeWorld) { rgv3d1.Tu = rgv3d1.X * invTableWidth; rgv3d1.Tv = rgv3d1.Y * invTableHeight; rgv3d2.Tu = rgv3d2.X * invTableWidth; rgv3d2.Tv = rgv3d2.Y * invTableHeight; } else { rgv3d1.Tu = 1.0f; rgv3d1.Tv = rv.PointRatios[i]; rgv3d2.Tu = 0.0f; rgv3d2.Tv = rv.PointRatios[i]; } } else { rgv3d1.Tu = 0.0f; rgv3d1.Tv = 0.0f; rgv3d2.Tu = 0.0f; rgv3d2.Tv = 0.0f; } mesh.Vertices[i * 2] = rgv3d1; mesh.Vertices[i * 2 + 1] = rgv3d2; if (i == rv.VertexCount - 1) { break; } mesh.Indices[i * 6] = i * 2; mesh.Indices[i * 6 + 1] = i * 2 + 1; mesh.Indices[i * 6 + 2] = i * 2 + 3; mesh.Indices[i * 6 + 3] = i * 2; mesh.Indices[i * 6 + 4] = i * 2 + 3; mesh.Indices[i * 6 + 5] = i * 2 + 2; } Mesh.ComputeNormals(mesh.Vertices, numVertices, mesh.Indices, (rv.VertexCount - 1) * 6); return(mesh); }
private Dictionary <string, Mesh> GenerateMeshes(Table.Table table) { var meshes = new Dictionary <string, Mesh>(); var topMesh = new Mesh("Top"); var sideMesh = new Mesh("Side"); var vVertex = DragPoint.GetRgVertex <RenderVertex2D, CatmullCurve2DCatmullCurveFactory>(_data.DragPoints); var rgTexCoord = DragPoint.GetTextureCoords(_data.DragPoints, vVertex); var numVertices = vVertex.Length; var rgNormal = new Vertex2D[numVertices]; for (var i = 0; i < numVertices; i++) { var pv1 = vVertex[i]; var pv2 = vVertex[i < numVertices - 1 ? i + 1 : 0]; var dx = pv1.X - pv2.X; var dy = pv1.Y - pv2.Y; var invLen = 1.0f / MathF.Sqrt(dx * dx + dy * dy); rgNormal[i] = new Vertex2D { X = dy * invLen, Y = dx * invLen }; } var bottom = _data.HeightBottom * table.GetScaleZ() + table.TableHeight; var top = _data.HeightTop * table.GetScaleZ() + table.TableHeight; var offset = 0; // Render side sideMesh.Vertices = new Vertex3DNoTex2[numVertices * 4]; for (var i = 0; i < numVertices; i++) { var pv1 = vVertex[i]; var pv2 = vVertex[i < numVertices - 1 ? i + 1 : 0]; var a = i == 0 ? numVertices - 1 : i - 1; var c = i < numVertices - 1 ? i + 1 : 0; var vNormal = new [] { new Vertex2D(), new Vertex2D() }; if (pv1.Smooth) { vNormal[0].X = (rgNormal[a].X + rgNormal[i].X) * 0.5f; vNormal[0].Y = (rgNormal[a].Y + rgNormal[i].Y) * 0.5f; } else { vNormal[0].X = rgNormal[i].X; vNormal[0].Y = rgNormal[i].Y; } if (pv2.Smooth) { vNormal[1].X = (rgNormal[i].X + rgNormal[c].X) * 0.5f; vNormal[1].Y = (rgNormal[i].Y + rgNormal[c].Y) * 0.5f; } else { vNormal[1].X = rgNormal[i].X; vNormal[1].Y = rgNormal[i].Y; } vNormal[0].Normalize(); vNormal[1].Normalize(); sideMesh.Vertices[offset] = new Vertex3DNoTex2(); sideMesh.Vertices[offset + 1] = new Vertex3DNoTex2(); sideMesh.Vertices[offset + 2] = new Vertex3DNoTex2(); sideMesh.Vertices[offset + 3] = new Vertex3DNoTex2(); sideMesh.Vertices[offset].X = pv1.X; sideMesh.Vertices[offset].Y = pv1.Y; sideMesh.Vertices[offset].Z = bottom; sideMesh.Vertices[offset + 1].X = pv1.X; sideMesh.Vertices[offset + 1].Y = pv1.Y; sideMesh.Vertices[offset + 1].Z = top; sideMesh.Vertices[offset + 2].X = pv2.X; sideMesh.Vertices[offset + 2].Y = pv2.Y; sideMesh.Vertices[offset + 2].Z = top; sideMesh.Vertices[offset + 3].X = pv2.X; sideMesh.Vertices[offset + 3].Y = pv2.Y; sideMesh.Vertices[offset + 3].Z = bottom; if (_data.SideImage != null) { sideMesh.Vertices[offset].Tu = rgTexCoord[i]; sideMesh.Vertices[offset].Tv = 1.0f; sideMesh.Vertices[offset + 1].Tu = rgTexCoord[i]; sideMesh.Vertices[offset + 1].Tv = 0f; sideMesh.Vertices[offset + 2].Tu = rgTexCoord[c]; sideMesh.Vertices[offset + 2].Tv = 0f; sideMesh.Vertices[offset + 3].Tu = rgTexCoord[c]; sideMesh.Vertices[offset + 3].Tv = 1.0f; } sideMesh.Vertices[offset].Nx = vNormal[0].X; sideMesh.Vertices[offset].Ny = -vNormal[0].Y; sideMesh.Vertices[offset].Nz = 0f; sideMesh.Vertices[offset + 1].Nx = vNormal[0].X; sideMesh.Vertices[offset + 1].Ny = -vNormal[0].Y; sideMesh.Vertices[offset + 1].Nz = 0f; sideMesh.Vertices[offset + 2].Nx = vNormal[1].X; sideMesh.Vertices[offset + 2].Ny = -vNormal[1].Y; sideMesh.Vertices[offset + 2].Nz = 0f; sideMesh.Vertices[offset + 3].Nx = vNormal[1].X; sideMesh.Vertices[offset + 3].Ny = -vNormal[1].Y; sideMesh.Vertices[offset + 3].Nz = 0f; offset += 4; } // prepare index buffer for sides var offset2 = 0; sideMesh.Indices = new int[numVertices * 6]; for (var i = 0; i < numVertices; i++) { sideMesh.Indices[i * 6] = offset2; sideMesh.Indices[i * 6 + 1] = offset2 + 1; sideMesh.Indices[i * 6 + 2] = offset2 + 2; sideMesh.Indices[i * 6 + 3] = offset2; sideMesh.Indices[i * 6 + 4] = offset2 + 2; sideMesh.Indices[i * 6 + 5] = offset2 + 3; offset2 += 4; } // draw top var vPoly = new List <int>(new int[numVertices]); for (var i = 0; i < numVertices; i++) { vPoly[i] = i; } topMesh.Indices = Mesh.PolygonToTriangles(vVertex, vPoly); var numPolys = topMesh.Indices.Length / 3; if (numPolys == 0) { // no polys to render leave vertex buffer undefined return(meshes); } var heightNotDropped = _data.HeightTop * table.GetScaleZ(); var heightDropped = _data.HeightBottom * table.GetScaleZ() + 0.1; var invTableWidth = 1.0f / table.Width; var invTableHeight = 1.0f / table.Height; Vertex3DNoTex2[][] vertsTop = { new Vertex3DNoTex2[numVertices], new Vertex3DNoTex2[numVertices], new Vertex3DNoTex2[numVertices] }; for (var i = 0; i < numVertices; i++) { var pv0 = vVertex[i]; vertsTop[0][i] = new Vertex3DNoTex2 { X = pv0.X, Y = pv0.Y, Z = heightNotDropped + table.TableHeight, Tu = pv0.X * invTableWidth, Tv = pv0.Y * invTableHeight, Nx = 0, Ny = 0, Nz = 1.0f }; vertsTop[1][i] = new Vertex3DNoTex2 { X = pv0.X, Y = pv0.Y, Z = (float)heightDropped, Tu = pv0.X * invTableWidth, Tv = pv0.Y * invTableHeight, Nx = 0, Ny = 0, Nz = 1.0f }; vertsTop[2][i] = new Vertex3DNoTex2 { X = pv0.X, Y = pv0.Y, Z = _data.HeightBottom, Tu = pv0.X * invTableWidth, Tv = pv0.Y * invTableHeight, Nx = 0, Ny = 0, Nz = -1.0f }; } topMesh.Vertices = vertsTop[0]; if (topMesh.Vertices.Length > 0) { meshes["Top"] = topMesh; } if (System.Math.Abs(top - bottom) > 0.00001f) { meshes["Side"] = sideMesh; } return(meshes); }
private Vertex3DNoTex2[] Find(IEnumerable <Vertex3DNoTex2> vertices, Vertex3DNoTex2 vertex, int precision) { return(vertices.Where(v => v.Equals(vertex, precision)).ToArray()); }
private static void AssertVerticesEqual(ObjVector4 expected, Vertex3DNoTex2 actual, float threshold) { actual.X.Should().BeApproximately(expected.X, threshold); actual.Y.Should().BeApproximately(expected.Y, threshold); actual.Z.Should().BeApproximately(expected.Z, threshold); }