private HitObject[] GenerateCurvedHitObjects(Table.Table table, IItem item)
        {
            var hitObjects = new List <HitObject>();
            var height     = table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y);
            var vVertex    = DragPoint.GetRgVertex <RenderVertex2D, CatmullCurve2DCatmullCurveFactory>(_data.DragPoints);

            var count = vVertex.Length;
            var rgv   = new RenderVertex2D[count];
            var rgv3D = new Vertex3D[count];

            for (var i = 0; i < count; i++)
            {
                rgv[i]   = vVertex[i];
                rgv3D[i] = new Vertex3D(rgv[i].X, rgv[i].Y, height + (float)(PhysicsConstants.PhysSkin * 2.0));
            }

            for (var i = 0; i < count; i++)
            {
                var pv2 = rgv[i < count - 1 ? i + 1 : 0];
                var pv3 = rgv[i < count - 2 ? i + 2 : i + 2 - count];
                hitObjects.Add(GetLineSeg(pv2, pv3, height, item));
            }

            hitObjects.AddRange(new Hit3DPoly(rgv3D, ItemType.Trigger, item).ConvertToTriangles());

            return(hitObjects.ToArray());
        }
        public RenderVertex3D[] GetCentralCurve(Table.Table table, float acc = -1.0f)
        {
            float accuracy;

            // as solid ramps are rendered into the static buffer, always use maximum precision
            if (acc != -1.0)
            {
                accuracy = acc;                 // used for hit shape calculation, always!
            }
            else
            {
                var mat = table.GetMaterial(_data.Material);
                if (mat == null || !mat.IsOpacityActive)
                {
                    accuracy = 10.0f;
                }
                else
                {
                    accuracy = table.GetDetailLevel();
                }
            }

            // min = 4 (highest accuracy/detail level), max = 4 * 10^(10/1.5) = ~18.000.000 (lowest accuracy/detail level)
            accuracy = 4.0f * MathF.Pow(10.0f, (10.0f - accuracy) * (1.0f / 1.5f));
            return(DragPoint.GetRgVertex <RenderVertex3D, CatmullCurve3DCatmullCurveFactory>(_data.DragPoints, false, accuracy));
        }
Example #3
0
        internal void GenerateColliders(float playfieldHeight, List <ICollider> colliders, float margin = 0f)
        {
            var vVertex = DragPoint.GetRgVertex <RenderVertex2D, CatmullCurve2DCatmullCurveFactory>(_component.DragPoints);

            var count  = vVertex.Length;
            var rgv3Dt = new float3[count];
            var rgv3Db = _colliderComponent.IsBottomSolid ? new float3[count] : null;

            var bottom = _component.HeightBottom + playfieldHeight - margin;
            var top    = _component.HeightTop + playfieldHeight + margin;

            for (var i = 0; i < count; ++i)
            {
                var pv1 = vVertex[i];
                rgv3Dt[i] = new float3(pv1.X, pv1.Y, top);

                if (rgv3Db != null)
                {
                    rgv3Db[count - 1 - i] = new float3(pv1.X, pv1.Y, bottom);
                }

                var pv2 = vVertex[(i + 1) % count];
                var pv3 = vVertex[(i + 2) % count];
                GenerateLinePolys(pv2, pv3, playfieldHeight, colliders);
            }

            ColliderUtils.Generate3DPolyColliders(in rgv3Dt, _api.GetColliderInfo(), colliders);

            if (rgv3Db != null)
            {
                ColliderUtils.Generate3DPolyColliders(in rgv3Db, _api.GetColliderInfo(), colliders);
            }
        }
Example #4
0
        private static RenderVertex2D[] GetCentralCurve(DragPointData[] dragPoints, int tableDetailLevel, float acc, bool staticRendering = true, bool loop = true)
        {
            float accuracy;

            // as solid rubbers are rendered into the static buffer, always use maximum precision
            if (acc != -1.0f)
            {
                accuracy = acc;                 // used for hit shape calculation, always!
            }
            else
            {
                accuracy = staticRendering ? 10.0f : tableDetailLevel;

                // min = 4 (highest accuracy/detail level), max = 4 * 10^(10/1.5) = ~18.000.000 (lowest accuracy/detail level)
                accuracy = 4.0f * MathF.Pow(10.0f, (10.0f - accuracy) * (float)(1.0 / 1.5));
            }

            return(DragPoint.GetRgVertex <RenderVertex2D, CatmullCurve2DCatmullCurveFactory>(dragPoints, loop, accuracy));
        }
        private void GenerateCurvedHitObjects(ICollection <ICollider> colliders)
        {
            var height  = _component.PositionZ;
            var vVertex = DragPoint.GetRgVertex <RenderVertex2D, CatmullCurve2DCatmullCurveFactory>(_component.DragPoints);

            var count = vVertex.Length;
            var rgv   = new RenderVertex2D[count];
            var rgv3D = new float3[count];

            for (var i = 0; i < count; i++)
            {
                rgv[i]   = vVertex[i];
                rgv3D[i] = new float3(rgv[i].X, rgv[i].Y, height + (float)(PhysicsConstants.PhysSkin * 2.0));
            }
            ColliderUtils.Generate3DPolyColliders(rgv3D, _api.GetColliderInfo(), colliders);

            for (var i = 0; i < count; i++)
            {
                var pv2 = rgv[i < count - 1 ? i + 1 : 0];
                var pv3 = rgv[i < count - 2 ? i + 2 : i + 2 - count];
                AddLineSeg(pv2.ToUnityFloat2(), pv3.ToUnityFloat2(), height, colliders);
            }
        }
        /// <summary>
        /// Returns all hit objects for the surface.
        /// </summary>
        private HitObject[] Generate3DPolys(Table.Table table, IItem item)
        {
            var hitObjects = new List <HitObject>();

            var vVertex = DragPoint.GetRgVertex <RenderVertex2D, CatmullCurve2DCatmullCurveFactory>(_data.DragPoints);

            var count  = vVertex.Length;
            var rgv3Dt = new Vertex3D[count];
            var rgv3Db = _data.IsBottomSolid ? new Vertex3D[count] : null;

            var bottom = _data.HeightBottom + table.TableHeight;
            var top    = _data.HeightTop + table.TableHeight;

            for (var i = 0; i < count; ++i)
            {
                var pv1 = vVertex[i];
                rgv3Dt[i] = new Vertex3D(pv1.X, pv1.Y, top);

                if (rgv3Db != null)
                {
                    rgv3Db[count - 1 - i] = new Vertex3D(pv1.X, pv1.Y, bottom);
                }

                var pv2 = vVertex[(i + 1) % count];
                var pv3 = vVertex[(i + 2) % count];
                hitObjects.AddRange(GenerateLinePolys(pv2, pv3, table, item));
            }

            hitObjects.AddRange(new Hit3DPoly(rgv3Dt, ItemType.Surface, item).ConvertToTriangles());

            if (rgv3Db != null)
            {
                hitObjects.AddRange(new Hit3DPoly(rgv3Db, ItemType.Surface, item).ConvertToTriangles());
            }

            return(hitObjects.ToArray());
        }
        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);
        }
        private Mesh GenerateSideMesh(Table.Table table)
        {
            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;

                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
                    };
                }
            }

            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;
            }

            return(sideMesh);
        }
        /// <summary>
        /// Construct & display the curve from DragPointsHandler control points
        /// Find the curve traveller position along the curve
        /// </summary>
        ///
        /// <remarks>
        /// Will use the DragPointExposure from the handler's item to display slingshot segments accordingly
        /// Will update handler's curve traveller position and control point base index for point insertion
        /// </remarks>
        private void DisplayCurve()
        {
            List <Vector3>[] controlPointsSegments = new List <Vector3> [_handler.ControlPoints.Count].Select(item => new List <Vector3>()).ToArray();

            // Display Curve & handle curve traveller
            if (_handler.ControlPoints.Count > 1)
            {
                var transformedDPoints = new List <DragPointData>();
                foreach (var controlPoint in _handler.ControlPoints)
                {
                    var newDp = new DragPointData(controlPoint.DragPoint)
                    {
                        Center = controlPoint.WorldPos.ToVertex3D()
                    };
                    transformedDPoints.Add(newDp);
                }

                var vAccuracy = Vector3.one;
                vAccuracy = _handler.Transform.localToWorldMatrix.MultiplyVector(vAccuracy);
                var accuracy = Mathf.Abs(vAccuracy.x * vAccuracy.y * vAccuracy.z);
                accuracy *= HandleUtility.GetHandleSize(_handler.CurveTravellerPosition) * ControlPoint.ScreenRadius;
                var vVertex = DragPoint.GetRgVertex <RenderVertex3D, CatmullCurve3DCatmullCurveFactory>(
                    transformedDPoints.ToArray(), _handler.DragPointInspector.PointsAreLooping, accuracy
                    );

                if (vVertex.Length > 0)
                {
                    // Fill Control points paths
                    ControlPoint currentControlPoint = null;
                    foreach (var v in vVertex)
                    {
                        if (v.IsControlPoint)
                        {
                            if (currentControlPoint != null)
                            {
                                controlPointsSegments[currentControlPoint.Index].Add(v.ToUnityVector3());
                            }
                            currentControlPoint = _handler.ControlPoints.Find(cp => cp.WorldPos == v.ToUnityVector3());
                        }
                        if (currentControlPoint != null)
                        {
                            controlPointsSegments[currentControlPoint.Index].Add(v.ToUnityVector3());
                        }
                    }

                    // close loop if needed
                    if (_handler.DragPointInspector.PointsAreLooping)
                    {
                        controlPointsSegments[_handler.ControlPoints.Count - 1].Add(controlPointsSegments[0][0]);
                    }

                    // construct full path
                    _pathPoints.Clear();
                    const float splitRatio = 0.1f;
                    foreach (var controlPoint in _handler.ControlPoints)
                    {
                        // Split straight segments to avoid HandleUtility.ClosestPointToPolyLine issues
                        ref var segments = ref controlPointsSegments[controlPoint.Index];
                        if (segments.Count == 2)
                        {
                            var dir  = segments[1] - segments[0];
                            var dist = dir.magnitude;
                            dir = Vector3.Normalize(dir);
                            var newPath = new List <Vector3> {
                                segments[0]
                            };
                            for (var splitDist = dist * splitRatio; splitDist < dist; splitDist += dist * splitRatio)
                            {
                                newPath.Add(newPath[0] + dir * splitDist);
                            }
                            newPath.Add(segments[1]);
                            segments = newPath;
                        }
                        _pathPoints.AddRange(segments);
                    }

                    _curveTravellerMoved = false;
                    if (_pathPoints.Count > 1)
                    {
                        var newPos = HandleUtility.ClosestPointToPolyLine(_pathPoints.ToArray());
                        if ((newPos - _handler.CurveTravellerPosition).magnitude >= HandleUtility.GetHandleSize(_handler.CurveTravellerPosition) * ControlPoint.ScreenRadius * CurveTravellerSizeRatio * 0.1f)
                        {
                            _handler.CurveTravellerPosition = newPos;
                            _curveTravellerMoved            = true;
                        }
                    }

                    // Render Curve with correct color regarding drag point properties & find curve section where the curve traveller is
                    _handler.CurveTravellerControlPointIdx = -1;
                    var minDist = float.MaxValue;
                    foreach (var controlPoint in _handler.ControlPoints)
                    {
                        var segments = controlPointsSegments[controlPoint.Index].ToArray();
                        if (segments.Length > 1)
                        {
                            Handles.color = _handler.DragPointInspector.DragPointExposition.Contains(DragPointExposure.SlingShot) && controlPoint.DragPoint.IsSlingshot ? CurveSlingShotColor : CurveColor;
                            Handles.DrawAAPolyLine(CurveWidth, segments);
                            var closestToPath = HandleUtility.ClosestPointToPolyLine(segments);
                            var dist          = (closestToPath - _handler.CurveTravellerPosition).magnitude;
                            if (dist < minDist)
                            {
                                minDist = dist;
                                _handler.CurveTravellerControlPointIdx = controlPoint.Index;
                            }
                        }
                    }
                }
            }
Example #10
0
        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);
        }