Example #1
0
		public void AddPoint(Vector3Df point)
		{
			points.Add(point);

			// add front line
			Vertex3D v1front = new Vertex3D(point, new Vector3Df(0), new Color(0));
			Vertex3D v2front = new Vertex3D((point - Center).Normalize() * height, new Vector3Df(0), FrontColor);
			vertFront.Add(v1front);
			vertFront.Add(v2front);

			// add back line
			Vertex3D v1back = v1front;
			Vertex3D v2back = new Vertex3D(v2front);
			v2back.Color = BackColor;
			vertBack.Add(v1back);
			vertBack.Add(v2back);

			// add connection line if possible (front and back)
			if (vertFront.Count >= 4)
			{
				vertFront.Add(vertFront.Get(vertFront.Count - 3));
				vertFront.Add(v2front);

				vertBack.Add(vertBack.Get(vertBack.Count - 3));
				vertBack.Add(v2back);
			}

			// update indices "used" count
			indBoth.SetCount(vertFront.Count);
		}
        public PrimitiveMesh(Device device, Mesh baseMesh)
        {
            BaseMesh = baseMesh;

            var vert3d = new Vertex3D[baseMesh.Vertices.Length];
            for (var i = 0; i < vert3d.Length; ++i)
                vert3d[i] = new Vertex3D(baseMesh.Vertices[i]);

            IndexBuffer = Buffer.Create<ushort>(device, BindFlags.IndexBuffer, baseMesh.Indices);
            VertexBuffer = Buffer.Create<Vertex3D>(device, BindFlags.VertexBuffer, vert3d);
            VertexBufferBinding = new VertexBufferBinding(VertexBuffer, VertexBuffer.Description.SizeInBytes / baseMesh.Vertices.Length, 0);
        }
Example #3
0
    // Runs once before first turn
    internal static void ReadStatic()
    {
        // Read the list of vertex locations.
        int n = int.Parse(IO.ReadLine());

        // List of points in the map.
        vertexList = new Vertex3D[n];
        //	vertexColors = new int[n];

        for (int i = 0; i < n; i++)
        {
            string[] tokens = IO.ReadLine().Split();
            vertexList[i] = new Vertex3D(i,int.Parse(tokens[0]), int.Parse(tokens[1]), int.Parse(tokens[2]));
        //			vertexList[i].adjacentColorMap  = 0;
        }
        //Console.Error.Write("VertexColors: ");
        //foreach (int x in vertexColors) Console.Error.Write(" " + x.ToString());
        //Console.Error.WriteLine();

        // Read the list of region outlines.
        n = int.Parse(IO.ReadLine());
        // List of regions in the map
        regionList = new Region[n];
        for (int regionNumber = 0; regionNumber < n; regionNumber++)
        {
            string[] tokens = IO.ReadLine().Split();
            int vertexCount = int.Parse(tokens[0]);
            regionList[regionNumber] = new Region(regionNumber);
          		regionList[regionNumber].vertexList = new int[vertexCount];
            for (int rVertextNumber = 0; rVertextNumber < vertexCount; rVertextNumber++)
            {
                int vertexNumber = int.Parse(tokens[rVertextNumber + 1]);
                regionList[regionNumber].vertexList[rVertextNumber] = vertexNumber;
                vertexList[vertexNumber].adjacentRegions.Add(regionNumber);
            }
        }

        // List of current region colors, pusher and marker locations.
        // These are updated on every turn snapshot from the game.
        //regionColors = new int[regionList.Length];
        pList = new Pusher[2 * PCOUNT];
        for (int i = 0; i < pList.Length; i++)
            pList[i] = new Pusher(i);
        mList = new Marker[MCOUNT];
        for (int i = 0; i < mList.Length; i++)
            mList[i] = new Marker(i);
    }
Example #4
0
        public LensflareSceneNode(SceneNode parent, SceneManager mgr, int id)
            : base(parent, mgr, id)
        {
            draw_flare = true;
            ign_geom = false;
            smgr = mgr;

            indices = new ushort[6];
            indices[0] = 0;
            indices[1] = 2;
            indices[2] = 1;
            indices[3] = 0;
            indices[4] = 3;
            indices[5] = 2;

            vertices = new Vertex3D[4];
            for (int i = 0; i < 4; i++)
            {
                vertices[i] = new Vertex3D();
            }
            vertices[0].TCoords = Vector2D.From(0.0f, 1.0f);
            vertices[0].Color = Color.White;
            vertices[1].TCoords = Vector2D.From(0.0f, 0.0f);
            vertices[1].Color = Color.White;
            vertices[2].TCoords = Vector2D.From(1.0f, 0.0f);
            vertices[2].Color = Color.White;
            vertices[3].TCoords = Vector2D.From(1.0f, 1.0f);
            vertices[3].Color = Color.White;

            material = new Material();

            material.Lighting = false;

            material.MaterialType = MaterialType.TransparentAddColor;

            material.ZBuffer = 0;

            material.ZWriteEnable = false;

            bbox = new Box3D();

            bbox.MinEdge = Vector3D.From(-2, -2, -2);

            bbox.MaxEdge = Vector3D.From(2, 2, 2);

        }
Example #5
0
    public MoveMarkerToVertexGoal(Pusher inMe, int turn)
        : base(inMe,turn)
    {
        me = inMe;

        //IO.ErrorWrite("MoveMarkerToVertexGoal P#" + me.num.ToString());
        // Find a marker to move
        myMarker = Map.mList[GoalUtility.FindNearest(me.pos, Map.RED)];
        myMarker.beingUsedBy = this;

        //IO.ErrorWrite(myMarker.Short());

        // Find a place to push it.
        targetVertextSeq = GoalUtility.PickAVertex(myMarker.pos);
        targetVertex = Map.vertexList[targetVertextSeq];
        //IO.ErrorWrite(targetVertex.Short2D());
        targetVertex.target = true;	 // we should fix this make me the user.
        dest = new Vector2D(targetVertex.x, targetVertex.y);
        //IO.ErrorWriteLine("");
    }
Example #6
0
		public CSampleSceneNode(SceneNode parent, SceneManager smgr, int id)
			: base(parent, smgr, id)
		{
			this.OnRegisterSceneNode += new RegisterSceneNodeEventHandler(CSampleSceneNode_OnRegisterSceneNode);
			this.OnRender += new RenderEventHandler(CSampleSceneNode_OnRender);
			this.OnGetBoundingBox += new GetBoundingBoxEventHandler(CSampleSceneNode_OnGetBoundingBox);
			this.OnGetMaterialCount += new GetMaterialCountEventHandler(CSampleSceneNode_OnGetMaterialCount);
			this.OnGetMaterial += new GetMaterialEventHandler(CSampleSceneNode_OnGetMaterial);

			material.Wireframe = false;
			material.Lighting = false;

			vertices = new Vertex3D[4];
			vertices[0] = new Vertex3D(0, 0, 10, 1, 1, 0, new Color(0, 255, 255), 0, 1);
			vertices[1] = new Vertex3D(10, 0, -10, 1, 0, 0, new Color(255, 0, 255), 1, 1);
			vertices[2] = new Vertex3D(0, 20, 0, 0, 1, 1, new Color(255, 255, 0), 1, 0);
			vertices[3] = new Vertex3D(-10, 0, -10, 0, 0, 1, new Color(0, 255, 0), 0, 0);

			bbox.Set(vertices[0].Position);
			for (int i = 1; i < vertices.Length; i++)
				bbox.AddInternalPoint(vertices[i].Position);
		}
 public HitPoint(Vertex3D p, ItemType itemType) : base(itemType)
 {
     P = p;
 }
    private void Run()
    {
        // Read the static parts of the map.

        // Read the list of vertex locations.
        int n = int.Parse( Console.ReadLine() );

        // List of points in the map.
        Vertex3D[] vertexList = new Vertex3D [ n ];
        for ( int i = 0; i < n; i++ ) {
          string[] tokens = Console.ReadLine().Split();
          vertexList[ i ] = new Vertex3D( int.Parse( tokens[ 0 ] ),
                                      int.Parse( tokens[ 1 ] ),
                                      int.Parse( tokens[ 2 ] ) );
        }

        // Read the list of region outlines.
        n = int.Parse( Console.ReadLine() );
        // List of regions in the map
        int[][] regionList = new int [ n ] [];
        for ( int i = 0; i < n; i++ ) {
          string[] tokens = Console.ReadLine().Split();
          int m = int.Parse( tokens[ 0 ] );
          regionList[ i ] = new int [ m ];
          for ( int j = 0; j < m; j++ )
        regionList[ i ][ j ] = int.Parse( tokens[ j + 1 ] );
        }

        // List of current region colors, pusher and marker locations.
        // These are updated on every turn snapshot from the game.
        int[] regionColors = new int [ regionList.Length ];
        Pusher[] pList = new Pusher [ 2 * PCOUNT ];
        for ( int i = 0; i < pList.Length; i++ )
          pList[ i ] = new Pusher();
        Marker[] mList = new Marker [ MCOUNT ];
        for ( int i = 0; i < mList.Length; i++ )
          mList[ i ] = new Marker();

        int turnNum = int.Parse( Console.ReadLine() );
        while ( turnNum >= 0 ) {
          string[] tokens = Console.ReadLine().Split();
          score[ RED ] = int.Parse( tokens[ 0 ] );
          score[ BLUE ] = int.Parse( tokens[ 1 ] );

          // Read all the region colors.
          tokens = Console.ReadLine().Split();
          n = int.Parse( tokens[ 0 ] );
          for ( int i = 0; i < regionList.Length; i++ )
        regionColors[ i ] = int.Parse( tokens[ i + 1 ] );

          // Read all the pusher locations.
          n = int.Parse( Console.ReadLine() );
          for ( int i = 0; i < pList.Length; i++ ) {
        tokens = Console.ReadLine().Split();
        pList[ i ].pos.x = double.Parse( tokens[ 0 ] );
        pList[ i ].pos.y = double.Parse( tokens[ 1 ] );
        pList[ i ].vel.x = double.Parse( tokens[ 2 ] );
        pList[ i ].vel.y = double.Parse( tokens[ 3 ] );
          }

          // Read all the marker locations.
          n = int.Parse( Console.ReadLine() );
          for ( int i = 0; i < n; i++ ) {
        tokens = Console.ReadLine().Split();
        mList[ i ].pos.x = double.Parse( tokens[ 0 ] );
        mList[ i ].pos.y = double.Parse( tokens[ 1 ] );
        mList[ i ].vel.x = double.Parse( tokens[ 2 ] );
        mList[ i ].vel.y = double.Parse( tokens[ 3 ] );
        mList[ i ].color = int.Parse( tokens[ 4 ] );
          }

          // Compute a bit vector for the region colors incident on each
          // vertex.
          int[] vertexColors = new int [ vertexList.Length ];
          for ( int i = 0; i < regionList.Length; i++ )
        for ( int j = 0; j < regionList[ i ].Length; j++ )
          vertexColors[ regionList[ i ][ j ] ] |= ( 1 << regionColors[ i ] );

          // Candidate vertices for putting a marker on, vertices that have
          // some red but are not all red.
          List< int > candidates = new List< int >();
          for ( int i = 0; i < vertexList.Length; i++ )
        if ( ( vertexColors[ i ] & 0x1 ) == 1 &&
             vertexColors[ i ] != 1  )
          candidates.Add( i );

          // Choose a next action for each pusher, each pusher is responsible
          // for the marker with the same index.
          for ( int pdex = 0; pdex < PCOUNT; pdex++ ) {
        Pusher p = pList[ pdex ];

        // See how long this pusher has been doing its job.
        if ( p.busy ) {
          // Go to idle if we work to long on the same job.
          p.jobTime++;
          if ( p.jobTime >= 60 )
            p.busy = false;
        }

        // If we lose our marker, then just sit idle.
        if ( mList[ pdex ].color != RED ) {
          p.busy = false;
        }

        // Otherwise, try to find a new place to push our marker.
        if ( mList[ pdex ].color == RED &&
             !p.busy ) {
          if ( candidates.Count > 0 ) {
            int choice = rnd.Next( candidates.Count );
            p.targetVertex = candidates[ choice ];
            candidates.RemoveAt( choice );
            p.busy = true;
          }
        }

        // Choose a move direction in support of our current goal.
        if ( p.busy ) {
          // Get behind our marker and push it toward its destination.
          Vertex3D v = vertexList[ p.targetVertex ];
          Vector2D dest = new Vector2D( v.x, v.y );
          if ( MoveAround( p, mList[ pdex ], dest ) ) {
            Vector2D mToD = ( dest - mList[ pdex ].pos ).Norm();
            MoveTo( p, mList[ pdex ].pos - mToD );
          }
        } else
          Console.Write( "0.0 0.0" );

        // Print a space or a newline depending on whether we're at
        // the last pusher.
        if ( pdex + 1 < PCOUNT )
          Console.Write( " " );
        else
          Console.WriteLine();
          }

          turnNum = int.Parse( Console.ReadLine() );
        }
    }
Example #9
0
		private void meshGeneratorThread_generateMesh(int layerIndex)
		{
			GridLayer l = layers[layerIndex];

			if (l.Mesh != null)
				l.Mesh.Drop();

			l.Mesh = Mesh.Create();

			if (gridCubeCount > 0)
			{
				Vertex3D[] cubeVerts = null;
				ushort[] cubeInds = null;
				int cubeIndex = maxCubesPerBuffer; // this way we force buffers to be recreated at next new cube
				int totalCubesAdded = 0;

				float baseX = -(CubeSize * GridDim) / 2;
				float baseZ = -(CubeSize * GridDim) / 2;

				for (int i = 0; i < GridDim; i++)
				{
					for (int j = 0; j < GridDim; j++)
					{
						if (grid[i, j] == 0)
							continue;

						// check if current buffer is out of room, if so make a mesh buffer and attach it to the gridMesh and init next cubeVerts&Inds

						if (cubeIndex == maxCubesPerBuffer)
						{
							if (cubeVerts != null && cubeInds != null)
							{
								MeshBuffer b = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit);
								b.Append(cubeVerts, cubeInds);
								l.Mesh.AddMeshBuffer(b);
								b.Drop();

								totalCubesAdded += cubeIndex;
							}

							int cubeCount = gridCubeCount - totalCubesAdded;
							if (cubeCount > maxCubesPerBuffer)
								cubeCount = maxCubesPerBuffer;

							cubeIndex = 0;
							cubeVerts = new Vertex3D[cubeCount * 8]; // 8 verts per cube
							cubeInds = new ushort[cubeCount * 3 * 2 * 6]; // 3 indices per triangle; 2 triangles per face; 6 faces per cube
						}

						// build the cube and add it
						// note: we build 8 vertices cube because we don't need to texture it; if you want to change that (to use texture instead of vertex colors) - you need to build 12 vertices cube and initialize UV coords

						float x = baseX + i * CubeSize;
						float y = 0;
						float z = baseZ + j * CubeSize;
						int iv = cubeIndex * 8;

						cubeVerts[iv + 0] = new Vertex3D(x, y, z);
						cubeVerts[iv + 1] = new Vertex3D(x + CubeSize, y, z);
						cubeVerts[iv + 2] = new Vertex3D(x + CubeSize, y + CubeSize, z);
						cubeVerts[iv + 3] = new Vertex3D(x, y + CubeSize, z);
						cubeVerts[iv + 4] = new Vertex3D(x, y, z + CubeSize);
						cubeVerts[iv + 5] = new Vertex3D(x + CubeSize, y, z + CubeSize);
						cubeVerts[iv + 6] = new Vertex3D(x + CubeSize, y + CubeSize, z + CubeSize);
						cubeVerts[iv + 7] = new Vertex3D(x, y + CubeSize, z + CubeSize);

						int ii = cubeIndex * 3 * 2 * 6;

						// top
						cubeInds[ii + 0] = (ushort)(iv + 3);
						cubeInds[ii + 1] = (ushort)(iv + 7);
						cubeInds[ii + 2] = (ushort)(iv + 6);
						cubeInds[ii + 3] = (ushort)(iv + 3);
						cubeInds[ii + 4] = (ushort)(iv + 6);
						cubeInds[ii + 5] = (ushort)(iv + 2);

						// front
						cubeInds[ii + 6] = (ushort)(iv + 0);
						cubeInds[ii + 7] = (ushort)(iv + 3);
						cubeInds[ii + 8] = (ushort)(iv + 2);
						cubeInds[ii + 9] = (ushort)(iv + 0);
						cubeInds[ii + 10] = (ushort)(iv + 2);
						cubeInds[ii + 11] = (ushort)(iv + 1);

						// right
						cubeInds[ii + 12] = (ushort)(iv + 1);
						cubeInds[ii + 13] = (ushort)(iv + 2);
						cubeInds[ii + 14] = (ushort)(iv + 6);
						cubeInds[ii + 15] = (ushort)(iv + 1);
						cubeInds[ii + 16] = (ushort)(iv + 6);
						cubeInds[ii + 17] = (ushort)(iv + 5);

						// left
						cubeInds[ii + 18] = (ushort)(iv + 0);
						cubeInds[ii + 19] = (ushort)(iv + 4);
						cubeInds[ii + 20] = (ushort)(iv + 7);
						cubeInds[ii + 21] = (ushort)(iv + 0);
						cubeInds[ii + 22] = (ushort)(iv + 7);
						cubeInds[ii + 23] = (ushort)(iv + 3);

						// back
						cubeInds[ii + 24] = (ushort)(iv + 4);
						cubeInds[ii + 25] = (ushort)(iv + 5);
						cubeInds[ii + 26] = (ushort)(iv + 6);
						cubeInds[ii + 27] = (ushort)(iv + 4);
						cubeInds[ii + 28] = (ushort)(iv + 6);
						cubeInds[ii + 29] = (ushort)(iv + 7);

						// bottom
						cubeInds[ii + 30] = (ushort)(iv + 0);
						cubeInds[ii + 31] = (ushort)(iv + 1);
						cubeInds[ii + 32] = (ushort)(iv + 5);
						cubeInds[ii + 33] = (ushort)(iv + 0);
						cubeInds[ii + 34] = (ushort)(iv + 5);
						cubeInds[ii + 35] = (ushort)(iv + 4);

						cubeIndex++;
					}
				}

				if (cubeIndex > 0)
				{
					MeshBuffer b = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit);
					b.Append(cubeVerts, cubeInds);
					l.Mesh.AddMeshBuffer(b);
					b.Drop();
				}

				device.SceneManager.MeshManipulator.SetVertexColors(l.Mesh, cubeColor);
			}

			l.Transform.Rotation = new Vector3Df(gridGeneration * 0.93f, gridGeneration * 0.81f, gridGeneration * 0.69f);

			l.Generation = gridGeneration;
			l.CubeCount = gridCubeCount;
			l.MeshIsReady = true;
		}
Example #10
0
 private void RenderTriangles()
 {
     for (int iTriangle = 0; iTriangle < triangleIndicesList.Count; iTriangle++)
     {
         TriangleIndices triangleIndices = triangleIndicesList[iTriangle];
         Vertex3D        vertex1         = vertexList[triangleIndices.Index1];
         Vertex3D        vertex2         = vertexList[triangleIndices.Index2];
         Vertex3D        vertex3         = vertexList[triangleIndices.Index3];
         Vector3D        normal1         = vertex1.NormalVector;
         Vector3D        normal2         = vertex2.NormalVector;
         Vector3D        normal3         = vertex3.NormalVector;
         Vector3D        triangeNormal   = triangleNormalVectorList[iTriangle];
         GL.Begin(PrimitiveType.Triangles);
         if (textureID > 0)
         {
             GL.BindTexture(TextureTarget.Texture2D, textureID);
         }
         if (shadingModel == ShadingModel.Flat)
         {
             GL.Normal3(triangeNormal.X, triangeNormal.Z, -triangeNormal.Y);
         }
         if (shadingModel == ShadingModel.Smooth)
         {
             GL.Normal3(normal1.X, normal1.Z, -normal1.Y);
         }
         if (!useLight)
         {
             GL.Color4(vertex1.Color.R, vertex1.Color.G, vertex1.Color.B, vertex1.Color.A);
         }
         if (textureID > 0)
         {
             GL.TexCoord2(vertex1.TextureCoordinates.X, vertex1.TextureCoordinates.Y);
         }
         GL.Vertex3(vertex1.Position.X, vertex1.Position.Z, -vertex1.Position.Y);
         if (shadingModel == ShadingModel.Smooth)
         {
             GL.Normal3(normal2.X, normal2.Z, -normal2.Y);
         }
         if (!useLight)
         {
             GL.Color4(vertex2.Color.R, vertex2.Color.G, vertex2.Color.B, vertex2.Color.A);
         }
         if (textureID > 0)
         {
             if (vertex2.TextureCoordinates.X < vertex1.TextureCoordinates.X)
             {
                 GL.TexCoord2(vertex2.TextureCoordinates.X + 1, vertex2.TextureCoordinates.Y);
             }
             else
             {
                 GL.TexCoord2(vertex2.TextureCoordinates.X, vertex2.TextureCoordinates.Y);
             }
         }
         GL.Vertex3(vertex2.Position.X, vertex2.Position.Z, -vertex2.Position.Y);
         if (shadingModel == ShadingModel.Smooth)
         {
             GL.Normal3(normal3.X, normal3.Z, -normal3.Y);
         }
         if (!useLight)
         {
             GL.Color4(vertex3.Color.R, vertex3.Color.G, vertex3.Color.B, vertex3.Color.A);
         }
         if (textureID > 0)
         {
             if (vertex3.TextureCoordinates.X < vertex1.TextureCoordinates.X)
             {
                 GL.TexCoord2(vertex3.TextureCoordinates.X + 1, vertex3.TextureCoordinates.Y);
             }
             else
             {
                 GL.TexCoord2(vertex3.TextureCoordinates.X, vertex3.TextureCoordinates.Y);
             }
         }
         GL.Vertex3(vertex3.Position.X, vertex3.Position.Z, -vertex3.Position.Y);
         GL.End();
     }
 }
        private HitObject[] GenerateHitTargetHits(Table.Table table, IItem item)
        {
            var addedEdges = new EdgeSet();
            var hitMesh    = _meshGenerator.GetRenderObjects(table, Origin.Original, false).RenderObjects[0].Mesh;
            var hitObjects = GenerateCollidables(hitMesh, addedEdges, _data.IsLegacy, table, item).ToList();

            var tempMatrix = new Matrix3D().RotateZMatrix(MathF.DegToRad(_data.RotZ));
            var fullMatrix = new Matrix3D().Multiply(tempMatrix);

            if (!_data.IsLegacy)
            {
                var rgv3D          = new Vertex3D[DropTargetHitPlaneVertices.Length];
                var hitShapeOffset = 0.18f;
                if (_data.TargetType == TargetType.DropTargetBeveled)
                {
                    hitShapeOffset = 0.25f;
                }
                if (_data.TargetType == TargetType.DropTargetFlatSimple)
                {
                    hitShapeOffset = 0.13f;
                }

                // now create a special hit shape with hit event enabled to prevent a hit event when hit from behind
                for (var i = 0; i < DropTargetHitPlaneVertices.Length; i++)
                {
                    var dropTargetHitPlaneVertex = DropTargetHitPlaneVertices[i];
                    var vert = new Vertex3D(
                        dropTargetHitPlaneVertex.X,
                        dropTargetHitPlaneVertex.Y + hitShapeOffset,
                        dropTargetHitPlaneVertex.Z
                        );

                    vert.X *= _data.Size.X;
                    vert.Y *= _data.Size.Y;
                    vert.Z *= _data.Size.Z;
                    vert.MultiplyMatrix(fullMatrix);
                    rgv3D[i] = new Vertex3D(
                        vert.X + _data.Position.X,
                        vert.Y + _data.Position.Y,
                        vert.Z * table.GetScaleZ() + _data.Position.Z + table.TableHeight
                        );
                }

                for (var i = 0; i < DropTargetHitPlaneIndices.Length; i += 3)
                {
                    var i0 = DropTargetHitPlaneIndices[i];
                    var i1 = DropTargetHitPlaneIndices[i + 1];
                    var i2 = DropTargetHitPlaneIndices[i + 2];

                    // NB: HitTriangle wants CCW vertices, but for rendering we have them in CW order
                    var rgv3D2 = new[] { rgv3D[i0], rgv3D[i2], rgv3D[i1] };

                    hitObjects.Add(SetupHitObject(new HitTriangle(rgv3D2, ItemType.HitTarget, item), true, table));
                    hitObjects.AddRange(addedEdges.AddHitEdge(i0, i1, rgv3D2[0], rgv3D2[2], ItemType.HitTarget, item).Select(obj => SetupHitObject(obj, true, table)));
                    hitObjects.AddRange(addedEdges.AddHitEdge(i1, i2, rgv3D2[2], rgv3D2[1], ItemType.HitTarget, item).Select(obj => SetupHitObject(obj, true, table)));
                    hitObjects.AddRange(addedEdges.AddHitEdge(i2, i0, rgv3D2[1], rgv3D2[0], ItemType.HitTarget, item).Select(obj => SetupHitObject(obj, true, table)));
                }

                // add collision vertices
                for (var i = 0; i < DropTargetHitPlaneVertices.Length; ++i)
                {
                    hitObjects.Add(SetupHitObject(new HitPoint(rgv3D[i], ItemType.HitTarget, item), true, table));
                }
            }
            return(hitObjects.ToArray());
        }
Example #12
0
 public static float EuclidianDistance(Vertex3D v1, Vertex3D v2)
 {
     return((float)Math.Sqrt(Math.Pow(v1.x - v2.x, 2.0) + Math.Pow(v1.y - v2.y, 2.0) + Math.Pow(v1.z - v2.z, 2.0)));
 }
Example #13
0
        /*private void DoParticleSystem(uint time)
        {
        }*/
        private void ReallocateBuffers()
        {
            if (Particles.Length * 4 > Vertices.Length || Particles.Length * 6 > Indices.Length)
            {
                int oldSize = Vertices.Length;
                ArrayList newvert = new ArrayList();

                int i;
                newvert.AddRange(Vertices);
                for (i = oldSize; i < (Particles.Length * 4); i++)
                {
                    Vertex3D temp = new Vertex3D();
                    temp.Normal = new Vector3D(0, 1, 0);
                    newvert.Add(temp);
                }
                Vertices = (Vertex3D[])newvert.ToArray(typeof(Vertex3D));


                newvert.Clear();

                int oldIdxSize = Indices.Length;
                int oldvertices = oldSize;

                newvert.AddRange(Indices);

                for (i = oldIdxSize; i < (Particles.Length * 12); i += 12)
                {
                    newvert.Add((ushort)(0 + oldvertices));
                    newvert.Add((ushort)(2 + oldvertices));
                    newvert.Add((ushort)(1 + oldvertices));
                    newvert.Add((ushort)(0 + oldvertices));
                    newvert.Add((ushort)(3 + oldvertices));
                    newvert.Add((ushort)(2 + oldvertices));

                    newvert.Add((ushort)(1 + oldvertices));
                    newvert.Add((ushort)(2 + oldvertices));
                    newvert.Add((ushort)(0 + oldvertices));
                    newvert.Add((ushort)(2 + oldvertices));
                    newvert.Add((ushort)(3 + oldvertices));
                    newvert.Add((ushort)(0 + oldvertices));

                    oldvertices += 4;
                }
                Indices = (ushort[])newvert.ToArray(typeof(ushort));
                newvert.Clear();
            }
        }
Example #14
0
        private Vertex3D[] GenerateSphere(Vector3 position, float width, float height, float depth, float radians, uint numHorizontalDivisions, uint numVerticalDivisions)
        {
            /*
             *          Coordinate System Here is RHS, Y Vertical.
             *          V = Vertical Angle [inclination] .. (around horizontal X axis, 0 is pointing straight up)
             *          H = Horizontal Angle [azimuth] .. (around vertical Y axis, positive is clockwise from positive x direction towards positive z)
             *
             *          z = R.Sin(V).Sin(H)
             *          x = R.Sin(V).Cos(H)
             *          y = R.Cos(V)
             */

            var verts = new Vertex3D[numHorizontalDivisions * numVerticalDivisions];

            var divFracH = 1.0f / (1.0f * (numHorizontalDivisions - 1));
            var divFracV = 1.0f / (1.0f * (numVerticalDivisions - 1));

            var hw = 0.5f * width;
            var hh = 0.5f * height;
            var hd = 0.5f * depth;

            float fracX, fracY;

            for (var ny = 0; ny < numVerticalDivisions; ny++)
            {
                fracY = ny * divFracV;

                for (var nx = 0; nx < numHorizontalDivisions; nx++)
                {
                    fracX = nx * divFracH;

                    var horizontalAngle = (-0.5f + (-fracX * 2.0f)) * (float)Math.PI; //Rotate 90 degress CCW (negative direction) to pointing along negative z. then wrap around in CCW direction from there
                    var verticalAngle   = fracY * (float)Math.PI;

                    var H = horizontalAngle;
                    var V = verticalAngle;

                    var sinH = (float)Math.Sin(H);
                    var cosH = (float)Math.Cos(H);

                    var sinV = (float)Math.Sin(V);
                    var cosV = (float)Math.Cos(V);

                    var x = sinV * cosH;
                    var y = cosV;
                    var z = sinV * sinH;

                    var index = (numHorizontalDivisions * ny) + nx;

                    var positionScaled  = new Vector3(x * hw, y * hh, z * hd);
                    var positionRotated = Vector3.Transform(positionScaled, Matrix4x4.CreateRotationY(-radians));

                    verts[index] = new Vertex3D
                    {
                        Position = positionRotated + position,
                        TexCoord = new Vector2(fracX, fracY),
                    };
                }
            }

            /*Calculate Normals
             *
             *  Given the user has the option to distort the sphere by arbitary width, height and depth
             *  The per vertex normals are not guaranteed to be just normalised vectors of it's position
             *  (as is the case for a uniform sphere of constant radius around the origin)
             *  We therefore need to employ the standard vertex normal calculation technique:
             *
             *  Sum all Face Normals of the faces surrounding each vertex and normalise
             *
             *  Note: although in this mesh each face will be the same size, this technique does
             *  account for the different weighting that differently sized faces should have on a vertex
             *  normal. This is because a face normal is calculated using the cross product of two sides
             *  of a triangle. The length of the resulting vector is proportional the area of the face
             *  and it's direction is naturally in the direction of the face normal
             *
             *  Finally, care must be taken to ensure the face-out normals are calculated rather than face-in.
             *
             *  There are a select number of normals we already know. namely that those in the top and bottom
             *  Vertical row are +/- UnitY
             */

            for (var ny = 0; ny < numVerticalDivisions; ny++)
            {
                for (var nx = 0; nx < numHorizontalDivisions; nx++)
                {
                    var index = (numHorizontalDivisions * ny) + nx;

                    if (ny == 0)
                    {
                        //Top row points straight up
                        verts[index].Normal = Vector3.UnitY;
                        continue;
                    }

                    if (ny == numVerticalDivisions - 1)
                    {
                        //Bottom row points straight down
                        verts[index].Normal = -Vector3.UnitY;
                        continue;
                    }

                    //Vector3.Cross -> Positive Unit X crossed with Positive Unit Y == Unit Positive Z
                    //To get an outward facing normal, I will use those vectors along azimuth/inclination
                    //directions (psuedo vertical and horizontal lines in the reference frame of the vertex)
                    //and i will each one with the next in the counter clockwise direction if facing straight on

                    /*
                     *  x and Letter = Vertex
                     *
                     *  x   x  /C\  x   x
                     *        / | \
                     *  x   D---A---B   x
                     \  | /
                     \  x   x  \E/  x   x
                     \
                     \
                     \  Vertex Normal of A == Normalise(ABxAC + ACxAD + ADxAE + AExAB)
                     */

                    var indexMinusOne = index - 1;
                    if (nx == 0)
                    {
                        indexMinusOne = (numHorizontalDivisions * (ny + 1)) - 2; //-2 not -1 NOTE
                    }

                    var indexPlusOne = index + 1;
                    if (nx == numHorizontalDivisions - 1)
                    {
                        indexPlusOne -= numHorizontalDivisions;
                        indexPlusOne++; //Adding an extra 1 NOTE
                    }

                    //Why NOTE.. because the edge azimuth / horizontal points actually overlap at 0 and max azimuth. wrap points are not shared
                    //There is a seem at the back with overlapping points

                    var A = verts[index].Position;
                    var B = verts[indexPlusOne].Position;
                    var C = verts[index - numHorizontalDivisions].Position;
                    var D = verts[indexMinusOne].Position;
                    var E = verts[index + numHorizontalDivisions].Position;

                    var sum = Vector3.Cross(B - A, C - A) + Vector3.Cross(C - A, D - A) + Vector3.Cross(D - A, E - A) + Vector3.Cross(E - A, B - A);

                    verts[index].Normal = Vector3.Normalize(sum);
                }
            }

            return(_vertexGridToTriangleListTool.Convert(numHorizontalDivisions, numVerticalDivisions, verts));
        }
Example #15
0
        private void GetRelativeVelocity(Vertex3D normal, Ball.Ball ball, Vertex3D vRel, Vertex3D rB, Vertex3D rF)
        {
            rB.Set(normal.Clone().MultiplyScalar(-ball.Data.Radius));
            var hitPos = ball.State.Pos.Clone().Add(rB);

            var cF = new Vertex3D(
                _mover.HitCircleBase.Center.X,
                _mover.HitCircleBase.Center.Y,
                ball.State.Pos.Z                 // make sure collision happens in same z plane where ball is
                );

            rF.Set(hitPos.Clone().Sub(cF));             // displacement relative to flipper center
            var vB = ball.Hit.SurfaceVelocity(rB);
            var vF = _mover.SurfaceVelocity(rF);

            vRel.Set(vB.Clone().Sub(vF));
        }
Example #16
0
 public Ball(BallData data, Vertex3D initialVelocity, Table.Table table)
 {
     Data = data;
 }
Example #17
0
        public override void Collide(CollisionEvent coll, PlayerPhysics physics)
        {
            var ball   = coll.Ball;
            var normal = coll.HitNormal;
            var vRel   = new Vertex3D();
            var rB     = new Vertex3D();
            var rF     = new Vertex3D();

            GetRelativeVelocity(normal, ball, vRel, rB, rF);

            var bnv = normal.Dot(vRel);             // relative normal velocity

            if (bnv >= -PhysicsConstants.LowNormVel)
            {
                // nearly receding ... make sure of conditions
                if (bnv > PhysicsConstants.LowNormVel)
                {
                    // otherwise if clearly approaching .. process the collision
                    // is this velocity clearly receding (i.E must > a minimum)
                    return;
                }

                //#ifdef PhysicsConstants.EMBEDDED
                if (coll.HitDistance < -PhysicsConstants.Embedded)
                {
                    bnv = -PhysicsConstants.EmbedShot;                     // has ball become embedded???, give it a kick
                }
                else
                {
                    return;
                }

                //#endif
            }

            //#ifdef PhysicsConstants.DISP_GAIN
            // correct displacements, mostly from low velocity blindness, an alternative to true acceleration processing
            var hitDist = -PhysicsConstants.DispGain * coll.HitDistance;             // distance found in hit detection

            if (hitDist > 1.0e-4)
            {
                if (hitDist > PhysicsConstants.DispLimit)
                {
                    hitDist = PhysicsConstants.DispLimit;                     // crossing ramps, delta noise
                }

                // push along norm, back to free area; use the norm, but is not correct
                ball.State.Pos.Add(coll.HitNormal.Clone().MultiplyScalar(hitDist));
            }
            //#endif

            // angular response to impulse in normal direction
            var angResp = Vertex3D.CrossProduct(rF, normal);

            /*
             * Check if flipper is in contact with its stopper and the collision impulse
             * would push it beyond the stopper. In that case, don"t allow any transfer
             * of kinetic energy from ball to flipper. This avoids overly dead bounces
             * in that case.
             */
            var angImp = -angResp.Z;             // minus because impulse will apply in -normal direction
            var flipperResponseScaling = 1.0f;

            if (_mover.IsInContact && _mover.ContactTorque * angImp >= 0f)
            {
                // if impulse pushes against stopper, allow no loss of kinetic energy to flipper
                // (still allow flipper recoil, but a diminished amount)
                angResp.SetZero();
                flipperResponseScaling = 0.5f;
            }

            /*
             * Rubber has a coefficient of restitution which decreases with the impact velocity.
             * We use a heuristic model which decreases the COR according to a falloff parameter:
             * 0 = no falloff, 1 = half the COR at 1 m/s (18.53 speed units)
             */
            var epsilon = Functions.ElasticityWithFalloff(Elasticity, ElasticityFalloff, bnv);

            var pv1        = angResp.Clone().DivideScalar(_mover.Inertia);
            var impulse    = -(1.0f + epsilon) * bnv / (ball.Hit.InvMass + normal.Dot(Vertex3D.CrossProduct(pv1, rF)));
            var flipperImp = normal.Clone().MultiplyScalar(-(impulse * flipperResponseScaling));

            var rotI = Vertex3D.CrossProduct(rF, flipperImp);

            if (_mover.IsInContact)
            {
                if (rotI.Z * _mover.ContactTorque < 0)
                {
                    // pushing against the solenoid?

                    // Get a bound on the time the flipper needs to return to static conditions.
                    // If it"s too short, we treat the flipper as static during the whole collision.
                    var recoilTime = -rotI.Z / _mover.ContactTorque;                     // time flipper needs to eliminate this impulse, in 10ms

                    // Check ball normal velocity after collision. If the ball rebounded
                    // off the flipper, we need to make sure it does so with full
                    // reflection, i.E., treat the flipper as static, otherwise
                    // we get overly dead bounces.
                    var bnvAfter = bnv + impulse * ball.Hit.InvMass;

                    if (recoilTime <= 0.5 || bnvAfter > 0)
                    {
                        // treat flipper as static for this impact
                        impulse = -(1.0f + epsilon) * bnv * ball.Data.Mass;
                        flipperImp.SetZero();
                        rotI.SetZero();
                    }
                }
            }

            ball.Hit.Vel.Add(normal.Clone().MultiplyScalar(impulse * ball.Hit.InvMass));             // new velocity for ball after impact
            _mover.ApplyImpulse(rotI);

            // apply friction
            var tangent = vRel.Clone().Sub(normal.Clone().MultiplyScalar(vRel.Dot(normal)));             // calc the tangential velocity

            var tangentSpSq = tangent.LengthSq();

            if (tangentSpSq > 1e-6)
            {
                tangent.DivideScalar(MathF.Sqrt(tangentSpSq)); // normalize to get tangent direction
                var vt = vRel.Dot(tangent);                    // get speed in tangential direction

                // compute friction impulse
                var crossB = Vertex3D.CrossProduct(rB, tangent);
                var pv12   = crossB.Clone().DivideScalar(ball.Hit.Inertia);
                var kt     = ball.Hit.InvMass + tangent.Dot(Vertex3D.CrossProduct(pv12, rB));

                var crossF = Vertex3D.CrossProduct(rF, tangent);
                var pv13   = crossF.Clone().DivideScalar(_mover.Inertia);
                kt += tangent.Dot(Vertex3D.CrossProduct(pv13, rF));                 // flipper only has angular response

                // friction impulse can't be greater than coefficient of friction times collision impulse (Coulomb friction cone)
                var maxFriction = Friction * impulse;
                var jt          = Functions.Clamp(-vt / kt, -maxFriction, maxFriction);

                ball.Hit.ApplySurfaceImpulse(
                    crossB.Clone().MultiplyScalar(jt),
                    tangent.Clone().MultiplyScalar(jt)
                    );
                _mover.ApplyImpulse(crossF.Clone().MultiplyScalar(-jt));
            }

            if (bnv < -0.25 && physics.TimeMsec - _lastHitTime > 250)
            {
                // limit rate to 250 milliseconds per event
                var flipperHit =
                    coll.HitMomentBit ? -1.0 : -bnv;                     // move event processing to end of collision handler...
                if (flipperHit < 0)
                {
                    _events.FireGroupEvent(EventId.HitEventsHit);                     // simple hit event
                }
                else
                {
                    // collision velocity (normal to face)
                    _events.FireVoidEventParam(EventId.FlipperEventsCollide, flipperHit);
                }
            }

            _lastHitTime = physics.TimeMsec;             // keep resetting until idle for 250 milliseconds
        }
Example #18
0
        public override void Contact(CollisionEvent coll, float dTime, PlayerPhysics physics)
        {
            var ball   = coll.Ball;
            var normal = coll.HitNormal;

            //#ifdef PhysicsConstants.EMBEDDED
            if (coll.HitDistance < -PhysicsConstants.Embedded)
            {
                // magic to avoid balls being pushed by each other through resting flippers!
                ball.Hit.Vel.Add(normal.Clone().MultiplyScalar(0.1f));
            }
            //#endif

            var vRel = new Vertex3D();
            var rB   = new Vertex3D();
            var rF   = new Vertex3D();

            GetRelativeVelocity(normal, ball, vRel, rB, rF);

            // this should be zero, but only up to +/- C_CONTACTVEL
            var normVel = vRel.Dot(normal);

            // If some collision has changed the ball's velocity, we may not have to do anything.
            if (normVel <= PhysicsConstants.ContactVel)
            {
                // compute accelerations of point on ball and flipper
                var aB   = ball.Hit.SurfaceAcceleration(rB, physics);
                var aF   = _mover.SurfaceAcceleration(rF);
                var aRel = aB.Clone().Sub(aF);

                // time derivative of the normal vector
                var normalDeriv = Vertex3D.CrossZ(_mover.AngleSpeed, normal);

                // relative acceleration in the normal direction
                var normAcc = aRel.Dot(normal) + 2.0f * normalDeriv.Dot(vRel);

                if (normAcc >= 0)
                {
                    return;                     // objects accelerating away from each other, nothing to do
                }

                // hypothetical accelerations arising from a unit contact force in normal direction
                var aBc             = normal.Clone().MultiplyScalar(ball.Hit.InvMass);
                var pv2             = normal.Clone().MultiplyScalar(-1);
                var cross           = Vertex3D.CrossProduct(rF, pv2);
                var pv1             = cross.Clone().DivideScalar(_mover.Inertia);
                var aFc             = Vertex3D.CrossProduct(pv1, rF);
                var contactForceAcc = normal.Dot(aBc.Clone().Sub(aFc));

                // find j >= 0 such that normAcc + j * contactForceAcc >= 0  (bodies should not accelerate towards each other)
                var j = -normAcc / contactForceAcc;

                // kill any existing normal velocity
                ball.Hit.Vel.Add(normal.Clone().MultiplyScalar(j * dTime * ball.Hit.InvMass - coll.HitOrgNormalVelocity));
                _mover.ApplyImpulse(cross.Clone().MultiplyScalar(j * dTime));

                // apply friction

                // first check for slippage
                var      slip        = vRel.Clone().Sub(normal.Clone().MultiplyScalar(normVel));     // calc the tangential slip velocity
                var      maxFriction = j * Friction;
                var      slipSpeed   = slip.Length();
                Vertex3D slipDir;
                Vertex3D crossF;
                float    numer;
                float    denomF;
                Vertex3D pv13;

                if (slipSpeed < PhysicsConstants.Precision)
                {
                    // slip speed zero - static friction case
                    var slipAcc = aRel.Clone().Sub(normal.Clone().MultiplyScalar(aRel.Dot(normal)));                     // calc the tangential slip acceleration

                    // neither slip velocity nor slip acceleration? nothing to do here
                    if (slipAcc.LengthSq() < 1e-6)
                    {
                        return;
                    }

                    slipDir = slipAcc.Normalize();
                    numer   = -slipDir.Dot(aRel);
                    crossF  = Vertex3D.CrossProduct(rF, slipDir);
                    pv13    = crossF.Clone().DivideScalar(-_mover.Inertia);
                    denomF  = slipDir.Dot(Vertex3D.CrossProduct(pv13, rF));
                }
                else
                {
                    // nonzero slip speed - dynamic friction case
                    slipDir = slip.Clone().DivideScalar(slipSpeed);

                    numer  = -slipDir.Dot(vRel);
                    crossF = Vertex3D.CrossProduct(rF, slipDir);
                    pv13   = crossF.Clone().DivideScalar(_mover.Inertia);
                    denomF = slipDir.Dot(Vertex3D.CrossProduct(pv13, rF));
                }

                var crossB   = Vertex3D.CrossProduct(rB, slipDir);
                var pv12     = crossB.Clone().DivideScalar(ball.Hit.Inertia);
                var denomB   = ball.Hit.InvMass + slipDir.Dot(Vertex3D.CrossProduct(pv12, rB));
                var friction = Functions.Clamp(numer / (denomB + denomF), -maxFriction, maxFriction);

                ball.Hit.ApplySurfaceImpulse(
                    crossB.Clone().MultiplyScalar(dTime * friction),
                    slipDir.Clone().MultiplyScalar(dTime * friction)
                    );
                _mover.ApplyImpulse(crossF.Clone().MultiplyScalar(-dTime * friction));
            }
        }
Example #19
0
        public void Draw(uint time)
        {
            removeDead(time);

            Material mat = new Material();

            mat.Type     = MaterialType.TransparentVertexAlpha;
            mat.Lighting = false;
            sceneManager.VideoDriver.SetMaterial(mat);
            sceneManager.VideoDriver.SetTransform(TransformationState.World, Matrix.Identity);

            Random random = new Random();

            Color[] colors = new Color[11];             // 11 colors (line count + 1, since each line has 2 points)
            for (int i = 0; i < colors.Length; i++)
            {
                colors[i] = new Color(255, 255, 255, 255 - (10 - i) * 25);
            }

            vertexBuffer.SetCount(0);

            foreach (var shot in shots)
            {
                Vector3Df pos = shot.node.Position;
                AABBox    box = new AABBox(pos - new Vector3Df(shotRadius), pos + new Vector3Df(shotRadius));

                List <Triangle3Df> tris = worldTriangles.GetTriangles(box, 1000);
                if (tris.Count == 0)
                {
                    continue;
                }

                Dictionary <float, Vector3Df> uniquePoints = new Dictionary <float, Vector3Df>();
                foreach (var t in tris)
                {
                    Vector3Df p = t.GetClosestPointOnTriangle(pos);
                    float     k = p.X + p.Y * 1000 + p.Z * 1000000;
                    uniquePoints[k] = p;
                }

                foreach (var point in uniquePoints.Values)
                {
                    BillboardSceneNode n = sceneManager.AddBillboardSceneNode(null, new Dimension2Df(7.5f));
                    n.SetMaterialFlag(MaterialFlag.Lighting, false);
                    n.SetMaterialType(MaterialType.TransparentAddColor);
                    n.SetMaterialTexture(0, sceneManager.VideoDriver.GetTexture("../../media/particlewhite.bmp"));
                    n.Position = point;

                    var animator = sceneManager.CreateDeleteAnimator(0.1f);
                    n.AddAnimator(animator);
                    animator.Drop();

                    Vertex3D v1 = new Vertex3D(point);
                    Vertex3D v2 = new Vertex3D();

                    for (int i = 0; i < 10; i++)
                    {
                        v1.Color = colors[i];
                        v2.Color = colors[i + 1];

                        v2.Position = pos.GetInterpolated(point, i * 0.111);

                        if (i != 0 && i != 9)                         // do not displace first and last points
                        {
                            v2.Position += new Vector3Df((random.Next() % 10) - 5, (random.Next() % 10) - 5, (random.Next() % 10) - 5);
                        }

                        vertexBuffer.Add(v1);
                        vertexBuffer.Add(v2);

                        v1.Position = v2.Position;
                    }
                }
            }

            indexBuffer.SetCount(vertexBuffer.Count);
            sceneManager.VideoDriver.DrawVertexPrimitiveList(vertexBuffer, indexBuffer, PrimitiveType.Lines);
        }
Example #20
0
        public P3DSimplexNoiseTerrain(SceneNode parent, SceneManager mgr, int id, int vertsPerRow, int vertsPerCol, int cellSpacing, float heightScale)
            : base(parent, mgr, id)
        {
            _mgr = mgr;
            _driver = _mgr.VideoDriver;

            Material = new Material();
            Material.Lighting = false;

            _numVertsPerRow = vertsPerRow;
            _numVertsPerCol = vertsPerCol;
            _cellSpacing = cellSpacing;
            _heightScale = heightScale;

            _numCellsPerRow = _numVertsPerRow - 1;
            _numCellsPerCol = _numVertsPerCol - 1;
            _width = _numCellsPerRow * _cellSpacing;
            _depth = _numCellsPerCol * _cellSpacing;
            NumVertices = _numVertsPerRow * _numVertsPerCol;
            _numIndices = (_numCellsPerRow * _numCellsPerCol) * 6;
            _numTriangles = (_numCellsPerRow * _numCellsPerCol) * 2;
            _indices = new ushort[_numIndices];

            int startX = -_width / 2;
            int startZ = _depth / 2;

            int endX = _width / 2;
            int endZ = -_depth / 2;

            Box3D = new Box3D(new Vector3D(startX, -_heightScale, startZ), new Vector3D(endX, _heightScale, endZ));

            const float uCoordIncrementSize = 1.0f;
            const float vCoordIncrementSize = 1.0f;

            _heights = new float[NumVertices];

            int i = 0;
            for (int z = startZ; z >= endZ; z -= _cellSpacing)
            {
                int j = 0;
                for (int x = startX; x <= endX; x += _cellSpacing)
                {

                    int index = i * _numVertsPerRow + j;
                    // large noise.
                    float height = PerlinSimplexNoise.noise(x * 0.0001f, z * 0.0001f) * _heightScale;
                    // detail noise.
                    height += PerlinSimplexNoise.noise(x * 0.001f, z * 0.001f) * _heightScale / 10;
                    Vertex3D v = new Vertex3D(
                        new Vector3D(x, height, z),
                        new Vector3D(0, 1, 0),
                        Color.Black,
                        new Vector2D(j * uCoordIncrementSize, i * vCoordIncrementSize)
                        );
                    _buffer.SetVertex((uint)index, v);
                    j++;
                }
                i++;
            }

            uint baseIndex = 0;

            for (uint k = 0; k < _numCellsPerRow; k++)
            {
                for (uint j = 0; j < _numCellsPerCol; j++)
                {
                    _buffer.SetIndex(baseIndex + 0, (ushort)(k * _numVertsPerRow + j));
                    _buffer.SetIndex(baseIndex + 1, (ushort)(k * _numVertsPerRow + j + 1));
                    _buffer.SetIndex(baseIndex + 2, (ushort)((k + 1) * _numVertsPerRow + j));
                    _buffer.SetIndex(baseIndex + 3, (ushort)((k + 1) * _numVertsPerRow + j));
                    _buffer.SetIndex(baseIndex + 4, (ushort)(k * _numVertsPerRow + j + 1));
                    _buffer.SetIndex(baseIndex + 5, (ushort)((k + 1) * _numVertsPerRow + j + 1));

                    baseIndex += 6;
                }
            }
        }
Example #21
0
 public HitPoint(Vertex3D p, ItemType itemType, IItem item) : base(itemType, item)
 {
     P = p;
 }
Example #22
0
		public void Draw(uint time)
		{
			removeDead(time);

			Material mat = new Material();
			mat.Type = MaterialType.TransparentVertexAlpha;
			mat.Lighting = false;
			sceneManager.VideoDriver.SetMaterial(mat);
			sceneManager.VideoDriver.SetTransform(TransformationState.World, Matrix.Identity);

			Random random = new Random();

			Color[] colors = new Color[11]; // 11 colors (line count + 1, since each line has 2 points)
			for (int i = 0; i < colors.Length; i++)
				colors[i] = new Color(255, 255, 255, 255 - (10 - i) * 25);

			vertexBuffer.SetCount(0);

			foreach (var shot in shots)
			{
				Vector3Df pos = shot.node.Position;
				AABBox box = new AABBox(pos - new Vector3Df(shotRadius), pos + new Vector3Df(shotRadius));

				List<Triangle3Df> tris = worldTriangles.GetTriangles(box, 1000);
				if (tris.Count == 0)
					continue;

				Dictionary<float, Vector3Df> uniquePoints = new Dictionary<float, Vector3Df>();
				foreach (var t in tris)
				{
					Vector3Df p = t.GetClosestPointOnTriangle(pos);
					float k = p.X + p.Y * 1000 + p.Z * 1000000;
					uniquePoints[k] = p;
				}

				foreach (var point in uniquePoints.Values)
				{
					BillboardSceneNode n = sceneManager.AddBillboardSceneNode(null, new Dimension2Df(7.5f));
					n.SetMaterialFlag(MaterialFlag.Lighting, false);
					n.SetMaterialType(MaterialType.TransparentAddColor);
					n.SetMaterialTexture(0, sceneManager.VideoDriver.GetTexture("../../media/particlewhite.bmp"));
					n.Position = point;

					n.AddAnimator(sceneManager.CreateDeleteAnimator(0.1f));
					n.AnimatorList[0].Drop();

					Vertex3D v1 = new Vertex3D(point);
					Vertex3D v2 = new Vertex3D();

					for (int i = 0; i < 10; i++)
					{
						v1.Color = colors[i];
						v2.Color = colors[i + 1];

						v2.Position = pos.GetInterpolated(point, i * 0.111);

						if (i != 0 && i != 9) // do not displace first and last points
							v2.Position += new Vector3Df((random.Next() % 10) - 5, (random.Next() % 10) - 5, (random.Next() % 10) - 5);

						vertexBuffer.Add(v1);
						vertexBuffer.Add(v2);

						v1.Position = v2.Position;
					}
				}
			}

			indexBuffer.SetCount(vertexBuffer.Count);
			sceneManager.VideoDriver.DrawVertexPrimitiveList(vertexBuffer, indexBuffer, PrimitiveType.Lines);
		}
        internal void GenerateColliders(float playfieldHeight, ICollection <ICollider> colliders)
        {
            var localToPlayfield = MeshGenerator.GetTransformationMatrix();

            // QUICK FIX and TODO for Cupiii

            /* hitmesh should not be generated by the Mesh generator. Drop Targets need special Hitshapes, that shoujld be very simple and cannot be activated from behind.
             * var hitMesh = MeshGenerator.GetMesh();
             * for (var i = 0; i < hitMesh.Vertices.Length; i++) {
             *      hitMesh.Vertices[i].MultiplyMatrix(localToPlayfield);
             * }
             *
             * var addedEdges = EdgeSet.Get();
             *
             * GenerateCollidables(hitMesh, addedEdges, Data.IsLegacy, colliders);
             */
            var addedEdges = EdgeSet.Get();

            var tempMatrix = new Matrix3D().RotateZMatrix(MathF.DegToRad(Data.RotZ));
            var fullMatrix = new Matrix3D().Multiply(tempMatrix);

            //if (!Data.IsLegacy)    // Always generate special hitshapes (QUICKFIX)
            {
                var rgv3D          = new Vertex3D[DropTargetHitPlaneVertices.Length];
                var hitShapeOffset = 0.18f;
                if (Data.TargetType == TargetType.DropTargetBeveled)
                {
                    hitShapeOffset = 0.25f;
                }
                if (Data.TargetType == TargetType.DropTargetFlatSimple)
                {
                    hitShapeOffset = 0.13f;
                }

                // now create a special hit shape with hit event enabled to prevent a hit event when hit from behind
                for (var i = 0; i < DropTargetHitPlaneVertices.Length; i++)
                {
                    var dropTargetHitPlaneVertex = DropTargetHitPlaneVertices[i];
                    var vert = new Vertex3D(
                        dropTargetHitPlaneVertex.x,
                        dropTargetHitPlaneVertex.y + hitShapeOffset,
                        dropTargetHitPlaneVertex.z
                        );

                    vert.X  *= Data.ScaleX;
                    vert.Y  *= Data.ScaleY;
                    vert.Z  *= Data.ScaleZ;
                    vert     = vert.MultiplyMatrix(fullMatrix);
                    rgv3D[i] = new Vertex3D(
                        vert.X + Data.PositionX,
                        vert.Y + Data.PositionY,
                        vert.Z + Data.PositionZ + playfieldHeight
                        );
                }

                for (var i = 0; i < DropTargetHitPlaneIndices.Length; i += 3)
                {
                    var i0 = DropTargetHitPlaneIndices[i];
                    var i1 = DropTargetHitPlaneIndices[i + 1];
                    var i2 = DropTargetHitPlaneIndices[i + 2];

                    // NB: HitTriangle wants CCW vertices, but for rendering we have them in CW order
                    var rgv0 = rgv3D[i0].ToUnityFloat3();
                    var rgv1 = rgv3D[i1].ToUnityFloat3();
                    var rgv2 = rgv3D[i2].ToUnityFloat3();

                    colliders.Add(new TriangleCollider(rgv0, rgv2, rgv1, GetColliderInfo(true)));

                    if (addedEdges.ShouldAddHitEdge(i0, i1))
                    {
                        colliders.Add(new Line3DCollider(rgv0, rgv2, GetColliderInfo(true)));
                    }
                    if (addedEdges.ShouldAddHitEdge(i1, i2))
                    {
                        colliders.Add(new Line3DCollider(rgv2, rgv1, GetColliderInfo(true)));
                    }
                    if (addedEdges.ShouldAddHitEdge(i2, i0))
                    {
                        colliders.Add(new Line3DCollider(rgv1, rgv0, GetColliderInfo(true)));
                    }
                }

                // add collision vertices
                for (var i = 0; i < DropTargetHitPlaneVertices.Length; ++i)
                {
                    colliders.Add(new PointCollider(rgv3D[i].ToUnityFloat3(), GetColliderInfo(true)));
                }
            }
        }
        protected float HitTestBasicRadius(Ball ball, float dTime, CollisionEvent coll, bool direction, bool lateral, bool rigid)
        {
            if (!IsEnabled || ball.State.IsFrozen)
            {
                return(-1.0f);
            }

            var c    = new Vertex3D(Center.X, Center.Y, 0.0f);
            var dist = ball.State.Pos.Clone().Sub(c);             // relative ball position
            var dv   = ball.Hit.Vel.Clone();

            var capsule3D         = !lateral && ball.State.Pos.Z > HitBBox.ZHigh;
            var isKicker          = ObjType == ItemType.Kicker;
            var isKickerOrTrigger = ObjType == ItemType.Trigger || ObjType == ItemType.Kicker;

            float targetRadius;

            if (capsule3D)
            {
                targetRadius = Radius * (float)(13.0 / 5.0);
                c.Z          = HitBBox.ZHigh - Radius * (float)(12.0 / 5.0);
                dist.Z       = ball.State.Pos.Z - c.Z;           // ball rolling point - capsule center height
            }
            else
            {
                targetRadius = Radius;
                if (lateral)
                {
                    targetRadius += ball.Data.Radius;
                }

                dist.Z = 0.0f;
                dv.Z   = 0.0f;
            }

            var bcddsq = dist.LengthSq();                    // ball center to circle center distance ... squared
            var bcdd   = MathF.Sqrt(bcddsq);                 // distance center to center

            if (bcdd <= 1.0e-6)
            {
                // no hit on exact center
                return(-1.0f);
            }

            var b   = dist.Dot(dv);
            var bnv = b / bcdd;                              // ball normal velocity

            if (direction && bnv > PhysicsConstants.LowNormVel)
            {
                // clearly receding from radius
                return(-1.0f);
            }

            var bnd = bcdd - targetRadius;                   // ball normal distance to

            var a = dv.LengthSq();

            var hitTime   = 0f;
            var isUnhit   = false;
            var isContact = false;

            // Kicker is special.. handle ball stalled on kicker, commonly hit while receding, knocking back into kicker pocket
            if (isKicker && bnd <= 0 && bnd >= -Radius &&
                a < PhysicsConstants.ContactVel * PhysicsConstants.ContactVel && ball.Hit.IsRealBall())
            {
                if (ball.Hit.VpVolObjs.Contains(Obj))
                {
                    ball.Hit.VpVolObjs.Remove(Obj);                     // cause capture
                }
            }

            // contact positive possible in future ... objects Negative in contact now
            if (rigid && bnd < PhysicsConstants.PhysTouch)
            {
                if (bnd < -ball.Data.Radius)
                {
                    return(-1.0f);
                }

                if (MathF.Abs(bnv) <= PhysicsConstants.ContactVel)
                {
                    isContact = true;
                }
                else
                {
                    // estimate based on distance and speed along distance
                    // the ball can be that fast that in the next hit cycle the ball will be inside the hit shape of a bumper or other element.
                    // if that happens bnd is negative and greater than the negative bnv value that results in a negative hittime
                    // below the "if (infNan(hittime) || hittime <0.F...)" will then be true and the hit function will return -1.0f = no hit
                    hitTime = MathF.Max(0.0f, (float)(-bnd / bnv));
                }
            }
            else if (isKickerOrTrigger && ball.Hit.IsRealBall() && bnd < 0 == ball.Hit.VpVolObjs.IndexOf(Obj) < 0)
            {
                // triggers & kickers

                // here if ... ball inside and no hit set .... or ... ball outside and hit set
                if (MathF.Abs(bnd - Radius) < 0.05)
                {
                    // if ball appears in center of trigger, then assumed it was gen"ed there
                    ball.Hit.VpVolObjs.Add(Obj);                     // special case for trigger overlaying a kicker
                }
                else
                {
                    // this will add the ball to the trigger space without a Hit
                    isUnhit = bnd > 0;                     // ball on outside is UnHit, otherwise it"s a Hit
                }
            }
            else
            {
                if (!rigid && bnd * bnv > 0 || a < 1.0e-8)
                {
                    // (outside and receding) or (inside and approaching)
                    // no hit ... ball not moving relative to object
                    return(-1.0f);
                }

                var sol = Functions.SolveQuadraticEq(a, 2.0f * b, bcddsq - targetRadius * targetRadius);
                if (sol == null)
                {
                    return(-1.0f);
                }

                var(time1, time2) = sol;
                isUnhit           = time1 * time2 < 0;
                hitTime           = isUnhit ? MathF.Max(time1, time2) : MathF.Min(time1, time2);       // ball is inside the circle
            }

            if (float.IsNaN(hitTime) || float.IsInfinity(hitTime) || hitTime < 0 || hitTime > dTime)
            {
                // contact out of physics frame
                return(-1.0f);
            }

            var hitZ = ball.State.Pos.Z + ball.Hit.Vel.Z * hitTime;             // rolling point

            if (hitZ + ball.Data.Radius * 0.5 < HitBBox.ZLow ||
                !capsule3D && hitZ - ball.Data.Radius * 0.5 > HitBBox.ZHigh ||
                capsule3D && hitZ < HitBBox.ZHigh)
            {
                return(-1.0f);
            }

            var hitX   = ball.State.Pos.X + ball.Hit.Vel.X * hitTime;
            var hitY   = ball.State.Pos.Y + ball.Hit.Vel.Y * hitTime;
            var sqrLen = (hitX - c.X) * (hitX - c.X) + (hitY - c.Y) * (hitY - c.Y);

            coll.HitNormal.SetZero();

            // over center?
            if (sqrLen > 1.0e-8)
            {
                // no
                var invLen = 1.0f / MathF.Sqrt(sqrLen);
                coll.HitNormal.X = (hitX - c.X) * invLen;
                coll.HitNormal.Y = (hitY - c.Y) * invLen;
            }
            else
            {
                // yes, over center
                coll.HitNormal.X = 0.0f;                 // make up a value, any direction is ok
                coll.HitNormal.Y = 1.0f;
                coll.HitNormal.Z = 0.0f;
            }

            if (!rigid)
            {
                // non rigid body collision? return direction
                coll.HitFlag = isUnhit;                 // UnHit signal is receding from target
            }

            coll.IsContact = isContact;
            if (isContact)
            {
                coll.HitOrgNormalVelocity = bnv;
            }

            coll.HitDistance = bnd;             // actual contact distance ...
            //coll.M_hitRigid = rigid;                         // collision type

            return(hitTime);
        }
Example #25
0
        public ATMOSkySceneNode(Texture tex, SceneNode parent, SceneManager mgr, int faces, int id)
            : base(parent, mgr, id)
        {
            smgr = mgr;
            AutomaticCulling = CullingType.Off;
            material = new Material();
            material.Lighting = false;
            material.ZBuffer = 0;
            material.Texture1 = tex;

            face = faces;
            vertices = new Vertex3D[face + 1];
            indices = new ushort[face * 3];

            double angle = 0.0f;
            double angle2 = 360.0f / face;
            vert = 0;                          //vertice nr
            int nr = -3;                     //indices nr

            vertices[0] = new Vertex3D(Vector3D.From(0.0f, 100.0f, 0.0f),
                                       Vector3D.From(0.0568988f, 0.688538f, -0.722965f),
                                       Color.White,
                                       Vector2D.From(0.0f, 0.1f)
                                      );

            for (ushort n = 1; n < face + 1; n++)
            {
                vert++;
                nr += 3;
                double x = Math.Cos(angle * 0.017453292519943295769236907684886f) * 100;
                double z = Math.Sin(angle * 0.017453292519943295769236907684886f) * 100;

                vertices[vert] = new Vertex3D(Vector3D.From((float)x, -5.0f, (float)z),
                                       Vector3D.From(0.0568988f, 0.688538f, -0.722965f),
                                       Color.White,
                                       Vector2D.From(0.0f, 0.9f)
                                      );

                angle = angle + angle2;
                indices[nr] = 0;
                indices[nr + 1] = (ushort)vert;
                indices[nr + 2] = (ushort)(vert + 1);
            }
            indices[nr + 2] = 1;

        }
        public HitObject[] GenerateHitObjects(Table.Table table, IItem item)
        {
            var hitObjects  = new List <HitObject>();
            var rv          = _meshGenerator.GetRampVertex(table, PhysicsConstants.HitShapeDetailLevel, true);
            var rgvLocal    = rv.RgvLocal;
            var rgHeight1   = rv.PointHeights;
            var vertexCount = rv.VertexCount;

            var(wallHeightRight, wallHeightLeft) = GetWallHeights();

            Vertex2D pv1, pv2, pv3 = new Vertex2D(), pv4 = new Vertex2D();

            // Add line segments for right ramp wall.
            if (wallHeightRight > 0.0f)
            {
                for (var i = 0; i < vertexCount - 1; i++)
                {
                    pv2 = rgvLocal[i];
                    pv3 = rgvLocal[i + 1];

                    hitObjects.AddRange(GenerateWallLineSeg(pv2, pv3, i > 0,
                                                            rgHeight1[i], rgHeight1[i + 1], wallHeightRight, item));
                    hitObjects.AddRange(GenerateWallLineSeg(pv3, pv2, i < vertexCount - 2,
                                                            rgHeight1[i], rgHeight1[i + 1], wallHeightRight, item));

                    // add joints at start and end of right wall
                    if (i == 0)
                    {
                        hitObjects.Add(GenerateJoint2D(pv2, rgHeight1[0], rgHeight1[0] + wallHeightRight, item));
                    }

                    if (i == vertexCount - 2)
                    {
                        hitObjects.Add(GenerateJoint2D(pv3, rgHeight1[vertexCount - 1],
                                                       rgHeight1[vertexCount - 1] + wallHeightRight, item));
                    }
                }
            }

            // Add line segments for left ramp wall.
            if (wallHeightLeft > 0.0f)
            {
                for (var i = 0; i < vertexCount - 1; i++)
                {
                    pv2 = rgvLocal[vertexCount + i];
                    pv3 = rgvLocal[vertexCount + i + 1];

                    hitObjects.AddRange(GenerateWallLineSeg(pv2, pv3, i > 0,
                                                            rgHeight1[vertexCount - i - 2], rgHeight1[vertexCount - i - 1], wallHeightLeft, item));
                    hitObjects.AddRange(GenerateWallLineSeg(pv3, pv2, i < vertexCount - 2,
                                                            rgHeight1[vertexCount - i - 2], rgHeight1[vertexCount - i - 1], wallHeightLeft, item));

                    // add joints at start and end of left wall
                    if (i == 0)
                    {
                        hitObjects.Add(GenerateJoint2D(pv2, rgHeight1[vertexCount - 1],
                                                       rgHeight1[vertexCount - 1] + wallHeightLeft, item));
                    }

                    if (i == vertexCount - 2)
                    {
                        hitObjects.Add(GenerateJoint2D(pv3, rgHeight1[0], rgHeight1[0] + wallHeightLeft, item));
                    }
                }
            }

            // Add hit triangles for the ramp floor.
            HitTriangle ph3dpoly, ph3dpolyOld = null;

            Vertex3D[] rgv3D;

            for (var i = 0; i < vertexCount - 1; i++)
            {
                /*
                 * Layout of one ramp quad seen from above, ramp direction is bottom to top:
                 *
                 *    3 - - 4
                 *    | \   |
                 *    |   \ |
                 *    2 - - 1
                 */
                pv1 = rgvLocal[i];                       // i-th right
                pv2 = rgvLocal[vertexCount * 2 - i - 1]; // i-th left
                pv3 = rgvLocal[vertexCount * 2 - i - 2]; // (i+1)-th left
                pv4 = rgvLocal[i + 1];                   // (i+1)-th right

                // left ramp floor triangle, CCW order
                rgv3D = new [] {
                    new Vertex3D(pv2.X, pv2.Y, rgHeight1[i]),
                    new Vertex3D(pv1.X, pv1.Y, rgHeight1[i]),
                    new Vertex3D(pv3.X, pv3.Y, rgHeight1[i + 1])
                };

                // add joint for starting edge of ramp
                if (i == 0)
                {
                    hitObjects.Add(GenerateJoint(rgv3D[0], rgv3D[1], item));
                }

                // add joint for left edge
                hitObjects.Add(GenerateJoint(rgv3D[0], rgv3D[2], item));

                //!! this is not efficient at all, use native triangle-soup directly somehow
                ph3dpoly = new HitTriangle(rgv3D, ItemType.Ramp, item);

                if (!ph3dpoly.IsDegenerate)                   // degenerate triangles happen if width is 0 at some point
                {
                    hitObjects.Add(ph3dpoly);
                    hitObjects.AddRange(CheckJoint(ph3dpolyOld, ph3dpoly, item));
                    ph3dpolyOld = ph3dpoly;
                }

                // right ramp floor triangle, CCW order
                rgv3D = new [] {
                    new Vertex3D(pv3.X, pv3.Y, rgHeight1[i + 1]),
                    new Vertex3D(pv1.X, pv1.Y, rgHeight1[i]),
                    new Vertex3D(pv4.X, pv4.Y, rgHeight1[i + 1])
                };

                // add joint for right edge
                hitObjects.Add(GenerateJoint(rgv3D[1], rgv3D[2], item));

                ph3dpoly = new HitTriangle(rgv3D, ItemType.Ramp, item);
                if (!ph3dpoly.IsDegenerate)
                {
                    hitObjects.Add(ph3dpoly);
                }

                hitObjects.AddRange(CheckJoint(ph3dpolyOld, ph3dpoly, item));
                ph3dpolyOld = ph3dpoly;
            }

            if (vertexCount >= 2)
            {
                // add joint for final edge of ramp
                var v1 = new Vertex3D(pv4.X, pv4.Y, rgHeight1[vertexCount - 1]);
                var v2 = new Vertex3D(pv3.X, pv3.Y, rgHeight1[vertexCount - 1]);
                hitObjects.Add(GenerateJoint(v1, v2, item));
            }

            // add outside bottom,
            // joints at the intersections are not needed since the inner surface has them
            // this surface is identical... except for the direction of the normal face.
            // hence the joints protect both surface edges from having a fall through

            for (var i = 0; i < vertexCount - 1; i++)
            {
                // see sketch above
                pv1 = rgvLocal[i];
                pv2 = rgvLocal[vertexCount * 2 - i - 1];
                pv3 = rgvLocal[vertexCount * 2 - i - 2];
                pv4 = rgvLocal[i + 1];

                // left ramp triangle, order CW
                rgv3D = new[] {
                    new Vertex3D(pv1.X, pv1.Y, rgHeight1[i]),
                    new Vertex3D(pv2.X, pv2.Y, rgHeight1[i]),
                    new Vertex3D(pv3.X, pv3.Y, rgHeight1[i + 1])
                };

                ph3dpoly = new HitTriangle(rgv3D, ItemType.Ramp, item);
                if (!ph3dpoly.IsDegenerate)
                {
                    hitObjects.Add(ph3dpoly);
                }

                // right ramp triangle, order CW
                rgv3D = new[] {
                    new Vertex3D(pv3.X, pv3.Y, rgHeight1[i + 1]),
                    new Vertex3D(pv4.X, pv4.Y, rgHeight1[i + 1]),
                    new Vertex3D(pv1.X, pv1.Y, rgHeight1[i])
                };

                ph3dpoly = new HitTriangle(rgv3D, ItemType.Ramp, item);
                if (!ph3dpoly.IsDegenerate)
                {
                    hitObjects.Add(ph3dpoly);
                }
            }

            return(hitObjects
                   .Select(obj => SetupHitObject(obj, table))
                   .ToArray());
        }
Example #27
0
 public new IRenderVertex Set(Vertex3D v)
 {
     base.Set(v);
     return(this);
 }
Example #28
0
        private void meshGeneratorThread_generateMesh(int layerIndex)
        {
            GridLayer l = layers[layerIndex];

            if (l.Mesh != null)
            {
                l.Mesh.Drop();
            }

            l.Mesh = Mesh.Create();

            if (gridCubeCount > 0)
            {
                Vertex3D[] cubeVerts       = null;
                ushort[]   cubeInds        = null;
                int        cubeIndex       = maxCubesPerBuffer;    // this way we force buffers to be recreated at next new cube
                int        totalCubesAdded = 0;

                float baseX = -(CubeSize * GridDim) / 2;
                float baseZ = -(CubeSize * GridDim) / 2;

                for (int i = 0; i < GridDim; i++)
                {
                    for (int j = 0; j < GridDim; j++)
                    {
                        if (grid[i, j] == 0)
                        {
                            continue;
                        }

                        // check if current buffer is out of room, if so make a mesh buffer and attach it to the gridMesh and init next cubeVerts&Inds

                        if (cubeIndex == maxCubesPerBuffer)
                        {
                            if (cubeVerts != null && cubeInds != null)
                            {
                                MeshBuffer b = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit);
                                b.Append(cubeVerts, cubeInds);
                                l.Mesh.AddMeshBuffer(b);
                                b.Drop();

                                totalCubesAdded += cubeIndex;
                            }

                            int cubeCount = gridCubeCount - totalCubesAdded;
                            if (cubeCount > maxCubesPerBuffer)
                            {
                                cubeCount = maxCubesPerBuffer;
                            }

                            cubeIndex = 0;
                            cubeVerts = new Vertex3D[cubeCount * 8];                             // 8 verts per cube
                            cubeInds  = new ushort[cubeCount * 3 * 2 * 6];                       // 3 indices per triangle; 2 triangles per face; 6 faces per cube
                        }

                        // build the cube and add it
                        // note: we build 8 vertices cube because we don't need to texture it; if you want to change that (to use texture instead of vertex colors) - you need to build 12 vertices cube and initialize UV coords

                        float x  = baseX + i * CubeSize;
                        float y  = 0;
                        float z  = baseZ + j * CubeSize;
                        int   iv = cubeIndex * 8;

                        cubeVerts[iv + 0] = new Vertex3D(x, y, z);
                        cubeVerts[iv + 1] = new Vertex3D(x + CubeSize, y, z);
                        cubeVerts[iv + 2] = new Vertex3D(x + CubeSize, y + CubeSize, z);
                        cubeVerts[iv + 3] = new Vertex3D(x, y + CubeSize, z);
                        cubeVerts[iv + 4] = new Vertex3D(x, y, z + CubeSize);
                        cubeVerts[iv + 5] = new Vertex3D(x + CubeSize, y, z + CubeSize);
                        cubeVerts[iv + 6] = new Vertex3D(x + CubeSize, y + CubeSize, z + CubeSize);
                        cubeVerts[iv + 7] = new Vertex3D(x, y + CubeSize, z + CubeSize);

                        int ii = cubeIndex * 3 * 2 * 6;

                        // top
                        cubeInds[ii + 0] = (ushort)(iv + 3);
                        cubeInds[ii + 1] = (ushort)(iv + 7);
                        cubeInds[ii + 2] = (ushort)(iv + 6);
                        cubeInds[ii + 3] = (ushort)(iv + 3);
                        cubeInds[ii + 4] = (ushort)(iv + 6);
                        cubeInds[ii + 5] = (ushort)(iv + 2);

                        // front
                        cubeInds[ii + 6]  = (ushort)(iv + 0);
                        cubeInds[ii + 7]  = (ushort)(iv + 3);
                        cubeInds[ii + 8]  = (ushort)(iv + 2);
                        cubeInds[ii + 9]  = (ushort)(iv + 0);
                        cubeInds[ii + 10] = (ushort)(iv + 2);
                        cubeInds[ii + 11] = (ushort)(iv + 1);

                        // right
                        cubeInds[ii + 12] = (ushort)(iv + 1);
                        cubeInds[ii + 13] = (ushort)(iv + 2);
                        cubeInds[ii + 14] = (ushort)(iv + 6);
                        cubeInds[ii + 15] = (ushort)(iv + 1);
                        cubeInds[ii + 16] = (ushort)(iv + 6);
                        cubeInds[ii + 17] = (ushort)(iv + 5);

                        // left
                        cubeInds[ii + 18] = (ushort)(iv + 0);
                        cubeInds[ii + 19] = (ushort)(iv + 4);
                        cubeInds[ii + 20] = (ushort)(iv + 7);
                        cubeInds[ii + 21] = (ushort)(iv + 0);
                        cubeInds[ii + 22] = (ushort)(iv + 7);
                        cubeInds[ii + 23] = (ushort)(iv + 3);

                        // back
                        cubeInds[ii + 24] = (ushort)(iv + 4);
                        cubeInds[ii + 25] = (ushort)(iv + 5);
                        cubeInds[ii + 26] = (ushort)(iv + 6);
                        cubeInds[ii + 27] = (ushort)(iv + 4);
                        cubeInds[ii + 28] = (ushort)(iv + 6);
                        cubeInds[ii + 29] = (ushort)(iv + 7);

                        // bottom
                        cubeInds[ii + 30] = (ushort)(iv + 0);
                        cubeInds[ii + 31] = (ushort)(iv + 1);
                        cubeInds[ii + 32] = (ushort)(iv + 5);
                        cubeInds[ii + 33] = (ushort)(iv + 0);
                        cubeInds[ii + 34] = (ushort)(iv + 5);
                        cubeInds[ii + 35] = (ushort)(iv + 4);

                        cubeIndex++;
                    }
                }

                if (cubeIndex > 0)
                {
                    MeshBuffer b = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit);
                    b.Append(cubeVerts, cubeInds);
                    l.Mesh.AddMeshBuffer(b);
                    b.Drop();
                }

                device.SceneManager.MeshManipulator.SetVertexColors(l.Mesh, cubeColor);
            }

            l.Transform.Rotation = new Vector3Df(gridGeneration * 0.93f, gridGeneration * 0.81f, gridGeneration * 0.69f);

            l.Generation  = gridGeneration;
            l.CubeCount   = gridCubeCount;
            l.MeshIsReady = true;
        }
Example #29
0
        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);
        }
Example #30
0
        /* istanbul ignore never next executed below the "magic" check (https://www.vpforums.org/index.php?showtopic=42690) */
        public void CreateNextLevel(int level, int levelEmpty)
        {
            var orgItems = Items & 0x3FFFFFFF;

            // !! magic
            if (orgItems <= 4 || level >= 128 / 2)
            {
                return;
            }

            var vDiag = new Vertex3D(
                RectBounds.Right - RectBounds.Left,
                RectBounds.Bottom - RectBounds.Top,
                RectBounds.ZHigh - RectBounds.ZLow
                );

            int axis;

            if (vDiag.X > vDiag.Y && vDiag.X > vDiag.Z)
            {
                if (vDiag.X < 0.0001)
                {
                    return;
                }
                axis = 0;
            }
            else if (vDiag.Y > vDiag.Z)
            {
                if (vDiag.Y < 0.0001)
                {
                    return;
                }
                axis = 1;
            }
            else
            {
                if (vDiag.Z < 0.0001)
                {
                    return;
                }

                axis = 2;
            }

            //!! weight this with ratio of elements going to middle vs left&right! (avoids volume split that goes directly through object)

            // create children, calc bboxes
            _children = _hitOct.AllocTwoNodes();
            if (_children.Length == 0)
            {
                // ran out of nodes - abort
                return;
            }

            _children[0].RectBounds = RectBounds;
            _children[1].RectBounds = RectBounds;

            var vCenter = new Vertex3D(
                (RectBounds.Left + RectBounds.Right) * 0.5f,
                (RectBounds.Top + RectBounds.Bottom) * 0.5f,
                (RectBounds.ZLow + RectBounds.ZHigh) * 0.5f
                );

            if (axis == 0)
            {
                _children[0].RectBounds.Right = vCenter.X;
                _children[1].RectBounds.Left  = vCenter.X;
            }
            else if (axis == 1)
            {
                _children[0].RectBounds.Bottom = vCenter.Y;
                _children[1].RectBounds.Top    = vCenter.Y;
            }
            else
            {
                _children[0].RectBounds.ZHigh = vCenter.Z;
                _children[1].RectBounds.ZLow  = vCenter.Z;
            }

            _children[0]._hitOct   = _hitOct;           //!! meh
            _children[0].Items     = 0;
            _children[0]._children = null;
            _children[1]._hitOct   = _hitOct;           //!! meh
            _children[1].Items     = 0;
            _children[1]._children = null;

            // determine amount of items that cross splitplane, or are passed on to the children
            if (axis == 0)
            {
                for (var i = Start; i < Start + orgItems; ++i)
                {
                    var pho = _hitOct.GetItemAt(i);

                    if (pho.HitBBox.Right < vCenter.X)
                    {
                        _children[0].Items++;
                    }
                    else if (pho.HitBBox.Left > vCenter.X)
                    {
                        _children[1].Items++;
                    }
                }
            }
            else if (axis == 1)
            {
                for (var i = Start; i < Start + orgItems; ++i)
                {
                    var pho = _hitOct.GetItemAt(i);

                    if (pho.HitBBox.Bottom < vCenter.Y)
                    {
                        _children[0].Items++;
                    }
                    else if (pho.HitBBox.Top > vCenter.Y)
                    {
                        _children[1].Items++;
                    }
                }
            }
            else
            {
                // axis == 2
                for (var i = Start; i < Start + orgItems; ++i)
                {
                    var pho = _hitOct.GetItemAt(i);

                    if (pho.HitBBox.ZHigh < vCenter.Z)
                    {
                        _children[0].Items++;
                    }
                    else if (pho.HitBBox.ZLow > vCenter.Z)
                    {
                        _children[1].Items++;
                    }
                }
            }

            // check if at least two nodes feature objects, otherwise don"t bother subdividing further
            var countEmpty = 0;

            if (_children[0].Items == 0)
            {
                countEmpty = 1;
            }

            if (_children[1].Items == 0)
            {
                ++countEmpty;
            }

            if (orgItems - _children[0].Items - _children[1].Items == 0)
            {
                ++countEmpty;
            }

            if (countEmpty >= 2)
            {
                ++levelEmpty;
            }
            else
            {
                levelEmpty = 0;
            }

            if (levelEmpty > 8)
            {
                // If 8 levels were all just subdividing the same objects without luck, exit & Free the nodes again (but at least empty space was cut off)
                _hitOct.NumNodes -= 2;
                _children         = null;
                return;
            }

            _children[0].Start = Start + orgItems - _children[0].Items - _children[1].Items;
            _children[1].Start = _children[0].Start + _children[0].Items;

            var items = 0;

            _children[0].Items = 0;
            _children[1].Items = 0;

            switch (axis)
            {
            // sort items that cross splitplane in-place, the others are sorted into a temporary
            case 0: {
                for (var i = Start; i < Start + orgItems; ++i)
                {
                    var pho = _hitOct.GetItemAt(i);

                    if (pho.HitBBox.Right < vCenter.X)
                    {
                        _hitOct.Indices[_children[0].Start + _children[0].Items++] = _hitOct.OrgIdx[i];
                    }
                    else if (pho.HitBBox.Left > vCenter.X)
                    {
                        _hitOct.Indices[_children[1].Start + _children[1].Items++] = _hitOct.OrgIdx[i];
                    }
                    else
                    {
                        _hitOct.OrgIdx[Start + items++] = _hitOct.OrgIdx[i];
                    }
                }

                break;
            }

            case 1: {
                for (var i = Start; i < Start + orgItems; ++i)
                {
                    var pho = _hitOct.GetItemAt(i);

                    if (pho.HitBBox.Bottom < vCenter.Y)
                    {
                        _hitOct.Indices[_children[0].Start + _children[0].Items++] = _hitOct.OrgIdx[i];
                    }
                    else if (pho.HitBBox.Top > vCenter.Y)
                    {
                        _hitOct.Indices[_children[1].Start + _children[1].Items++] = _hitOct.OrgIdx[i];
                    }
                    else
                    {
                        _hitOct.OrgIdx[Start + items++] = _hitOct.OrgIdx[i];
                    }
                }

                break;
            }

            default: {                     // axis == 2
                for (var i = Start; i < Start + orgItems; ++i)
                {
                    var pho = _hitOct.GetItemAt(i);

                    if (pho.HitBBox.ZHigh < vCenter.Z)
                    {
                        _hitOct.Indices[_children[0].Start + _children[0].Items++] = _hitOct.OrgIdx[i];
                    }
                    else if (pho.HitBBox.ZLow > vCenter.Z)
                    {
                        _hitOct.Indices[_children[1].Start + _children[1].Items++] = _hitOct.OrgIdx[i];
                    }
                    else
                    {
                        _hitOct.OrgIdx[Start + items++] = _hitOct.OrgIdx[i];
                    }
                }

                break;
            }
            }

            // The following assertions hold after this step:
            //assert( this.Start + items == this.Children[0].This.Start );
            //assert( this.Children[0].This.Start + this.Children[0].This.Items == this.Children[1].This.Start );
            //assert( this.Children[1].This.Start + this.Children[1].This.Items == this.Start + org_items );
            //assert( this.Start + org_items <= this.HitOct->tmp.Size() );

            Items = items | (axis << 30);

            // copy temporary back //!! could omit this by doing everything inplace
            for (var i = 0; i < _children[0].Items; i++)
            {
                _hitOct.OrgIdx[_children[0].Start + i] = _hitOct.Indices[_children[0].Start + i];
            }

            for (var i = 0; i < _children[1].Items; i++)
            {
                _hitOct.OrgIdx[_children[1].Start + i] = _hitOct.Indices[_children[1].Start + i];
            }
            //memcpy(&this.HitOct->m_org_idx[this.Children[0].Start], &this.HitOct->tmp[this.Children[0].Start], this.Children[0].Items*sizeof(unsigned int));
            //memcpy(&this.HitOct->m_org_idx[this.Children[1].Start], &this.HitOct->tmp[this.Children[1].Start], this.Children[1].This.Items*sizeof(unsigned int));

            _children[0].CreateNextLevel(level + 1, levelEmpty);
            _children[1].CreateNextLevel(level + 1, levelEmpty);
        }
 public HitTargetData(string name, float x, float y) : base(StoragePrefix.GameItem)
 {
     Name     = name;
     Position = new Vertex3D(x, y, 0f);
 }
        private Vertex3D[] GenerateMesh(ref Vector3 position, ref float width, ref float height, ref float depth, ref float cwRadsAroundY, ref RectangularCuboidMeshTexCoords tex)
        {
            var rotationMatrix = Matrix4x4.CreateRotationY(-cwRadsAroundY);

            var normals = new Vector3[]
            {
                new Vector3(0.0f, 0.0f, -1.0f),
                new Vector3(1.0f, 0.0f, 0.0f),
                new Vector3(0.0f, 0.0f, 1.0f),
                new Vector3(-1.0f, 0.0f, 0.0f),
                new Vector3(0.0f, 1.0f, 0.0f),
                new Vector3(0.0f, -1.0f, 0.0f),
            };

            for (var n = 0; n < 6; n++)
            {
                //Extra normalise not really needed, but might clean up some fp rounding errors
                normals[n] = Vector3.Normalize(Vector3.Transform(normals[n], rotationMatrix));
            }

            /*
             *  Coordinate System is RHS, with y upwards and z positive into camera
             *
             *  The faces are set out on the cube such that
             *  1 to 4: side faces, with side one facing along z (into camera) for an unrotated cube mesh (up is positive y)
             *      1 = back face, normal along negative z
             *      2 = right face, normal along positive x
             *      3 = front face, normal along positive z
             *      4 = left face, normal along negative x
             *  side 5 is top face. with the top of that 2d area being furthest along negative z in the above example
             *  side 6 is bottom face. orientated so that upon rotating the above mentioned around the x axis the
             *  top and bottom face would appear the same way up when facing the camera
             *  i.e. when unrotated the top of the 2d area will be closest to camera upside down (highest z value).
             *  a little tricky to describe - but should be roughly "as expected"
             */

            var mesh = new Vertex3D[]
            {
                //Face 1
                new Vertex3D
                {
                    Position = new Vector3(1.0f, -1.0f, -1.0f),
                    TexCoord = tex.One.BottomLeft,
                    Normal   = normals[0]
                },
                new Vertex3D
                {
                    Position = new Vector3(1.0f, 1.0f, -1.0f),
                    TexCoord = tex.One.TopLeft,
                    Normal   = normals[0]
                },
                new Vertex3D
                {
                    Position = new Vector3(-1.0f, 1.0f, -1.0f),
                    TexCoord = tex.One.TopRight,
                    Normal   = normals[0]
                },
                new Vertex3D
                {
                    Position = new Vector3(1.0f, -1.0f, -1.0f),
                    TexCoord = tex.One.BottomLeft,
                    Normal   = normals[0]
                },
                new Vertex3D
                {
                    Position = new Vector3(-1.0f, 1.0f, -1.0f),
                    TexCoord = tex.One.TopRight,
                    Normal   = normals[0]
                },
                new Vertex3D
                {
                    Position = new Vector3(-1.0f, -1.0f, -1.0f),
                    TexCoord = tex.One.BottomRight,
                    Normal   = normals[0]
                },

                //Face 2
                new Vertex3D
                {
                    Position = new Vector3(1.0f, -1.0f, 1.0f),
                    TexCoord = tex.Two.BottomLeft,
                    Normal   = normals[1]
                },
                new Vertex3D
                {
                    Position = new Vector3(1.0f, 1.0f, 1.0f),
                    TexCoord = tex.Two.TopLeft,
                    Normal   = normals[1]
                },
                new Vertex3D
                {
                    Position = new Vector3(1.0f, 1.0f, -1.0f),
                    TexCoord = tex.Two.TopRight,
                    Normal   = normals[1]
                },
                new Vertex3D
                {
                    Position = new Vector3(1.0f, -1.0f, 1.0f),
                    TexCoord = tex.Two.BottomLeft,
                    Normal   = normals[1]
                },
                new Vertex3D
                {
                    Position = new Vector3(1.0f, 1.0f, -1.0f),
                    TexCoord = tex.Two.TopRight,
                    Normal   = normals[1]
                },
                new Vertex3D
                {
                    Position = new Vector3(1.0f, -1.0f, -1.0f),
                    TexCoord = tex.Two.BottomRight,
                    Normal   = normals[1]
                },

                //Face 3
                new Vertex3D
                {
                    Position = new Vector3(-1.0f, -1.0f, 1.0f),
                    TexCoord = tex.Three.BottomLeft,
                    Normal   = normals[2]
                },
                new Vertex3D
                {
                    Position = new Vector3(-1.0f, 1.0f, 1.0f),
                    TexCoord = tex.Three.TopLeft,
                    Normal   = normals[2]
                },
                new Vertex3D
                {
                    Position = new Vector3(1.0f, 1.0f, 1.0f),
                    TexCoord = tex.Three.TopRight,
                    Normal   = normals[2]
                },
                new Vertex3D
                {
                    Position = new Vector3(-1.0f, -1.0f, 1.0f),
                    TexCoord = tex.Three.BottomLeft,
                    Normal   = normals[2]
                },
                new Vertex3D
                {
                    Position = new Vector3(1.0f, 1.0f, 1.0f),
                    TexCoord = tex.Three.TopRight,
                    Normal   = normals[2]
                },
                new Vertex3D
                {
                    Position = new Vector3(1.0f, -1.0f, 1.0f),
                    TexCoord = tex.Three.BottomRight,
                    Normal   = normals[2]
                },

                //Face 4
                new Vertex3D
                {
                    Position = new Vector3(-1.0f, -1.0f, -1.0f),
                    TexCoord = tex.Four.BottomLeft,
                    Normal   = normals[3]
                },
                new Vertex3D
                {
                    Position = new Vector3(-1.0f, 1.0f, -1.0f),
                    TexCoord = tex.Four.TopLeft,
                    Normal   = normals[3]
                },
                new Vertex3D
                {
                    Position = new Vector3(-1.0f, 1.0f, 1.0f),
                    TexCoord = tex.Four.TopRight,
                    Normal   = normals[3]
                },
                new Vertex3D
                {
                    Position = new Vector3(-1.0f, -1.0f, -1.0f),
                    TexCoord = tex.Four.BottomLeft,
                    Normal   = normals[3]
                },
                new Vertex3D
                {
                    Position = new Vector3(-1.0f, 1.0f, 1.0f),
                    TexCoord = tex.Four.TopRight,
                    Normal   = normals[3]
                },
                new Vertex3D
                {
                    Position = new Vector3(-1.0f, -1.0f, 1.0f),
                    TexCoord = tex.Four.BottomRight,
                    Normal   = normals[3]
                },

                //Face 5
                new Vertex3D
                {
                    Position = new Vector3(-1.0f, 1.0f, 1.0f),
                    TexCoord = tex.Five.BottomLeft,
                    Normal   = normals[4]
                },
                new Vertex3D
                {
                    Position = new Vector3(-1.0f, 1.0f, -1.0f),
                    TexCoord = tex.Five.TopLeft,
                    Normal   = normals[4]
                },
                new Vertex3D
                {
                    Position = new Vector3(1.0f, 1.0f, -1.0f),
                    TexCoord = tex.Five.TopRight,
                    Normal   = normals[4]
                },
                new Vertex3D
                {
                    Position = new Vector3(-1.0f, 1.0f, 1.0f),
                    TexCoord = tex.Five.BottomLeft,
                    Normal   = normals[4]
                },
                new Vertex3D
                {
                    Position = new Vector3(1.0f, 1.0f, -1.0f),
                    TexCoord = tex.Five.TopRight,
                    Normal   = normals[4]
                },
                new Vertex3D
                {
                    Position = new Vector3(1.0f, 1.0f, 1.0f),
                    TexCoord = tex.Five.BottomRight,
                    Normal   = normals[4]
                },

                //Face 6
                new Vertex3D
                {
                    Position = new Vector3(1.0f, -1.0f, -1.0f),
                    TexCoord = tex.Six.BottomLeft,
                    Normal   = normals[5]
                },
                new Vertex3D
                {
                    Position = new Vector3(1.0f, -1.0f, 1.0f),
                    TexCoord = tex.Six.TopLeft,
                    Normal   = normals[5]
                },
                new Vertex3D
                {
                    Position = new Vector3(-1.0f, -1.0f, 1.0f),
                    TexCoord = tex.Six.TopRight,
                    Normal   = normals[5]
                },
                new Vertex3D
                {
                    Position = new Vector3(1.0f, -1.0f, -1.0f),
                    TexCoord = tex.Six.BottomLeft,
                    Normal   = normals[5]
                },
                new Vertex3D
                {
                    Position = new Vector3(-1.0f, -1.0f, 1.0f),
                    TexCoord = tex.Six.TopRight,
                    Normal   = normals[5]
                },
                new Vertex3D
                {
                    Position = new Vector3(-1.0f, -1.0f, -1.0f),
                    TexCoord = tex.Six.BottomRight,
                    Normal   = normals[5]
                },
            };

            var numVerts = mesh.Length;

            var hw = 0.5f * width;
            var hh = 0.5f * height;
            var hd = 0.5f * depth;

            for (var n = 0; n < numVerts; n++)
            {
                var pos = mesh[n].Position;
                mesh[n].Position = Vector3.Transform(new Vector3(hw * pos.X, hh * pos.Y, hd * pos.Z), rotationMatrix) + position;
            }

            return(mesh);
        }
 public static Vector3 ToUnityVector3(this Vertex3D vertex)
 {
     return(new Vector3(vertex.X, vertex.Y, vertex.Z));
 }
Example #34
0
 public void SetGrid(int xNo, int yNo, float xMin, float xMax, float yMin, float yMax)
 {
     SetDataNo(xNo * yNo);
     m_nGridXNo = xNo;
     m_nGridYNo = yNo;
     m_xMin = xMin;
     m_xMax = xMax;
     m_yMin = yMin;
     m_yMax = yMax;
     float dx = (m_xMax - m_xMin) / ((float)xNo - 1);
     float dy = (m_yMax - m_yMin) / ((float)yNo - 1);
     for (int i = 0; i < xNo; i++)
     {
         for (int j = 0; j < yNo; j++)
         {
             float xV = m_xMin + dx * ((float)(i));
             float yV = m_yMin + dy * ((float)(j));
             m_vertices[j * xNo + i] = new Vertex3D();
             SetPoint(i, j, xV, yV, 0);
         }
     }
 }
Example #35
0
        /// <summary>
        /// Reads mesh buffer infos.
        /// </summary>
        void ReadMeshBufferInfos()
        {
            // IMPLEMENTED FROM jlouis' witcherconverter
            // http://jlouisb.users.sourceforge.net/
            // https://bitbucket.org/jlouis/witcherconverter

            SBufferInfos bufferInfos = new SBufferInfos();

            // *************** READ CHUNK INFOS ***************
            foreach (var chunk in _file.chunks)
            {
                if (chunk.Type == "CMesh")
                {
                    List <SVertexBufferInfos> vertexBufferInfos = new List <SVertexBufferInfos>();
                    var cookedDatas = chunk.GetVariableByName("cookedData") as CVector;
                    foreach (var cookedData in cookedDatas.variables)
                    {
                        switch (cookedData.Name)
                        {
                        case "renderChunks":
                        {
                            var bytes     = ((CByteArray)cookedData).Bytes;
                            var nbBuffers = bytes[0];
                            int curr      = 1;
                            for (uint i = 0; i < nbBuffers; i++)
                            {
                                SVertexBufferInfos buffInfo = new SVertexBufferInfos();

                                curr += 1;         // Unknown
                                buffInfo.verticesCoordsOffset = bytes.SubArray(ref curr, 4).GetUint();
                                buffInfo.uvOffset             = bytes.SubArray(ref curr, 4).GetUint();
                                buffInfo.normalsOffset        = bytes.SubArray(ref curr, 4).GetUint();

                                curr += 9;         // Unknown
                                buffInfo.indicesOffset = bytes.SubArray(ref curr, 4).GetUint();
                                curr += 1;         // 0x1D

                                buffInfo.nbVertices = bytes.SubArray(ref curr, 2).GetUshort();
                                buffInfo.nbIndices  = bytes.SubArray(ref curr, 4).GetUint();
                                curr        += 3;                                     // Unknown
                                buffInfo.lod = bytes.SubArray(ref curr, 1).GetByte(); // lod ?

                                vertexBufferInfos.Add(buffInfo);
                            }
                            break;
                        }

                        case "indexBufferOffset":
                        {
                            bufferInfos.indexBufferOffset = uint.Parse(cookedData.ToString());
                            break;
                        }

                        case "indexBufferSize":
                        {
                            bufferInfos.indexBufferSize = uint.Parse(cookedData.ToString());
                            break;
                        }

                        case "vertexBufferOffset":
                        {
                            bufferInfos.vertexBufferOffset = uint.Parse(cookedData.ToString());
                            break;
                        }

                        case "vertexBufferSize":
                        {
                            bufferInfos.vertexBufferSize = uint.Parse(cookedData.ToString());
                            break;
                        }

                        case "quantizationOffset":
                        {
                            bufferInfos.quantizationOffset.X = float.Parse((cookedData as CVector).variables[0].ToString());
                            bufferInfos.quantizationOffset.Y = float.Parse((cookedData as CVector).variables[1].ToString());
                            bufferInfos.quantizationOffset.Z = float.Parse((cookedData as CVector).variables[2].ToString());
                            break;
                        }

                        case "quantizationScale":
                        {
                            bufferInfos.quantizationScale.X = float.Parse((cookedData as CVector).variables[0].ToString());
                            bufferInfos.quantizationScale.Y = float.Parse((cookedData as CVector).variables[1].ToString());
                            bufferInfos.quantizationScale.Z = float.Parse((cookedData as CVector).variables[2].ToString());
                            break;
                        }

                        case "bonePositions":
                        {
                            foreach (CVector item in cookedData as CArray)
                            {
                                if (item.variables.Count == 4)
                                {
                                    Vector3Df pos = new Vector3Df();
                                    pos.X = (item.variables[0] as CFloat).val;
                                    pos.Y = (item.variables[1] as CFloat).val;
                                    pos.Z = (item.variables[2] as CFloat).val;
                                    bonePositions.Add(pos);
                                }
                            }
                            break;
                        }
                        }
                    }
                    bufferInfos.verticesBuffer = vertexBufferInfos;
                    var meshChunks = chunk.GetVariableByName("chunks") as CArray;
                    foreach (var meshChunk in meshChunks.array)
                    {
                        SMeshInfos meshInfo = new SMeshInfos();
                        foreach (var mesh in (meshChunk as CVector).variables)
                        {
                            switch (mesh.Name)
                            {
                            case "numVertices":
                            {
                                meshInfo.numVertices = uint.Parse(mesh.ToString());
                                break;
                            }

                            case "numIndices":
                            {
                                meshInfo.numIndices = uint.Parse(mesh.ToString());
                                break;
                            }

                            case "numBonesPerVertex":
                            {
                                meshInfo.numBonesPerVertex = uint.Parse(mesh.ToString());
                                break;
                            }

                            case "firstVertex":
                            {
                                meshInfo.firstVertex = uint.Parse(mesh.ToString());
                                break;
                            }

                            case "firstIndex":
                            {
                                meshInfo.firstIndex = uint.Parse(mesh.ToString());
                                break;
                            }

                            case "vertexType":
                            {
                                if ((mesh as CName).Value == "MVT_StaticMesh")
                                {
                                    meshInfo.vertexType = SMeshInfos.EMeshVertexType.EMVT_STATIC;
                                }
                                else if ((mesh as CName).Value == "MVT_SkinnedMesh")
                                {
                                    meshInfo.vertexType = SMeshInfos.EMeshVertexType.EMVT_SKINNED;
                                }
                                break;
                            }

                            case "materialID":
                            {
                                meshInfo.materialID = uint.Parse(mesh.ToString());
                                break;
                            }
                            }
                        }
                        meshInfos.Add(meshInfo);
                    }
                }
                else if (chunk.Type == "CMaterialInstance")
                {
                    materialInstances.Add(chunk.data as CMaterialInstance);
                }
            }

            // *************** READ MESH BUFFER INFOS ***************
            foreach (var meshInfo in meshInfos)
            {
                SVertexBufferInfos vBufferInf = new SVertexBufferInfos();
                uint nbVertices        = 0;
                uint firstVertexOffset = 0;
                uint nbIndices         = 0;
                uint firstIndiceOffset = 0;
                for (int i = 0; i < bufferInfos.verticesBuffer.Count; i++)
                {
                    nbVertices += bufferInfos.verticesBuffer[i].nbVertices;
                    if (nbVertices > meshInfo.firstVertex)
                    {
                        vBufferInf = bufferInfos.verticesBuffer[i];
                        // the index of the first vertex in the buffer
                        firstVertexOffset = meshInfo.firstVertex - (nbVertices - vBufferInf.nbVertices);
                        break;
                    }
                }
                for (int i = 0; i < bufferInfos.verticesBuffer.Count; i++)
                {
                    nbIndices += bufferInfos.verticesBuffer[i].nbIndices;
                    if (nbIndices > meshInfo.firstIndex)
                    {
                        vBufferInf        = bufferInfos.verticesBuffer[i];
                        firstIndiceOffset = meshInfo.firstIndex - (nbIndices - vBufferInf.nbIndices);
                        break;
                    }
                }

                using (StreamReader sr = new StreamReader(_file.FileName + ".1.buffer"))
                {
                    uint vertexSize = 8;
                    if (meshInfo.vertexType == SMeshInfos.EMeshVertexType.EMVT_SKINNED)
                    {
                        vertexSize += meshInfo.numBonesPerVertex * 2;
                    }

                    sr.BaseStream.Seek(vBufferInf.verticesCoordsOffset + firstVertexOffset * vertexSize, SeekOrigin.Begin);

                    List <Vertex3D> vertex3DCoords = new List <Vertex3D>();
                    Color           defaultColor   = new Color(255, 255, 255, 255);
                    for (int i = 0; i < meshInfo.numVertices; i++)
                    {
                        ushort x, y, z, w;

                        byte[] buff = new byte[2];
                        sr.BaseStream.Read(buff, 0, 2);
                        x = buff.GetUshort();
                        sr.BaseStream.Read(buff, 0, 2);
                        y = buff.GetUshort();
                        sr.BaseStream.Read(buff, 0, 2);
                        z = buff.GetUshort();
                        sr.BaseStream.Read(buff, 0, 2);
                        w = buff.GetUshort();

                        // skip skinning data
                        if (meshInfo.vertexType == SMeshInfos.EMeshVertexType.EMVT_SKINNED)
                        {
                            sr.BaseStream.Seek(meshInfo.numBonesPerVertex * 2, SeekOrigin.Current);
                        }

                        Vertex3D vertex3DCoord = new Vertex3D();
                        vertex3DCoord.Position = new Vector3Df(x, y, z) / 65535f * bufferInfos.quantizationScale + bufferInfos.quantizationOffset;
                        vertex3DCoord.Color    = defaultColor;
                        vertex3DCoords.Add(vertex3DCoord);
                    }

                    sr.BaseStream.Seek(vBufferInf.uvOffset + firstVertexOffset * 4, SeekOrigin.Begin);

                    for (int i = 0; i < meshInfo.numVertices; i++)
                    {
                        ushort u, v;

                        byte[] buff = new byte[2];
                        sr.BaseStream.Read(buff, 0, 2);
                        u = buff.GetUshort();
                        sr.BaseStream.Read(buff, 0, 2);
                        v = buff.GetUshort();

                        float uf = u.ToFloat();
                        float vf = v.ToFloat();

                        Vertex3D vertex3DCoord = vertex3DCoords[i];
                        vertex3DCoord.TCoords = new Vector2Df(uf, vf);
                        vertex3DCoords[i]     = vertex3DCoord;
                    }

                    // Indices -------------------------------------------------------------------
                    sr.BaseStream.Seek(bufferInfos.indexBufferOffset + vBufferInf.indicesOffset + firstIndiceOffset * 2, SeekOrigin.Begin);

                    List <ushort> indices = new List <ushort>();
                    for (int i = 0; i < meshInfo.numIndices; i++)
                    {
                        indices.Add(0);
                    }

                    for (int i = 0; i < meshInfo.numIndices; i++)
                    {
                        ushort index;

                        byte[] buff = new byte[2];
                        sr.BaseStream.Read(buff, 0, 2);
                        index = buff.GetUshort();

                        // Indice need to be inversed for the normals
                        if (i % 3 == 0)
                        {
                            indices[i] = index;
                        }
                        else if (i % 3 == 1)
                        {
                            indices[i + 1] = index;
                        }
                        else if (i % 3 == 2)
                        {
                            indices[i - 1] = index;
                        }
                    }

                    MeshBuffer meshBuff = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit);
                    staticMesh.AddMeshBuffer(meshBuff);
                    meshBuff.Append(vertex3DCoords, indices);
                    meshBuff.RecalculateBoundingBox();
                    meshBuff.Drop();
                }
            }

            // *************** READ RIG DATA ***************
            if (RigFile != null)
            {
                foreach (var chunk in RigFile.chunks)
                {
                    if (chunk.Type == "CSkeleton")
                    {
                        var bones = chunk.GetVariableByName("bones") as CArray;
                        meshSkeleton.nbBones = (uint)bones.array.Count;
                        foreach (CVector bone in bones)
                        {
                            var boneName = bone.variables.GetVariableByName("nameAsCName") as CName;
                            meshSkeleton.names.Add(boneName.Value);
                        }
                        var parentIndices = chunk.GetVariableByName("parentIndices") as CArray;
                        foreach (CVariable parentIndex in parentIndices)
                        {
                            meshSkeleton.parentIdx.Add(short.Parse(parentIndex.ToString()));
                        }

                        var unknownBytes = chunk.unknownBytes.Bytes;
                        int currPos      = 0;
                        for (uint i = 0; i < meshSkeleton.nbBones; i++)
                        {
                            Vector3Df position = new Vector3Df();
                            position.X = unknownBytes.SubArray(ref currPos, 4).GetFloat();
                            position.Y = unknownBytes.SubArray(ref currPos, 4).GetFloat();
                            position.Z = unknownBytes.SubArray(ref currPos, 4).GetFloat();
                            unknownBytes.SubArray(ref currPos, 4).GetFloat(); // the w component

                            Quaternion orientation = new Quaternion();
                            orientation.X = unknownBytes.SubArray(ref currPos, 4).GetFloat();
                            orientation.Y = unknownBytes.SubArray(ref currPos, 4).GetFloat();
                            orientation.Z = unknownBytes.SubArray(ref currPos, 4).GetFloat();
                            orientation.W = unknownBytes.SubArray(ref currPos, 4).GetFloat();

                            Vector3Df scale;
                            scale.X = unknownBytes.SubArray(ref currPos, 4).GetFloat();
                            scale.Y = unknownBytes.SubArray(ref currPos, 4).GetFloat();
                            scale.Z = unknownBytes.SubArray(ref currPos, 4).GetFloat();
                            unknownBytes.SubArray(ref currPos, 4).GetFloat(); // the w component

                            Matrix posMat = new Matrix();
                            posMat.Translation = position;

                            Matrix    rotMat = new Matrix();
                            Vector3Df euler  = orientation.ToEuler();
                            // chechNaNErrors(euler);

                            rotMat.SetRotationRadians(euler);

                            Matrix scaleMat = new Matrix();
                            scaleMat.Scale = scale;

                            Matrix localTransform = posMat * rotMat * scaleMat;
                            orientation = orientation.MakeInverse();
                            meshSkeleton.matrix.Add(localTransform);
                            meshSkeleton.positions.Add(position);
                            meshSkeleton.rotations.Add(orientation);
                            meshSkeleton.scales.Add(scale);
                        }
                    }
                }
            }
        }
Example #36
0
 public IRenderVertex Set(Vertex3D v)
 {
     base.Set(v.X, v.Y);
     return(this);
 }
Example #37
0
 public void Set(Vertex3D v)
 {
     X = v.X;
     Y = v.Y;
     Z = v.Z;
 }
        private Mesh GetMesh(Table.Table table, int acc = -1, bool createHitShape = false)
        {
            _data.StaticRendering = true;
            var mesh = new Mesh(_data.Name);
            int accuracy;

            if (table.GetDetailLevel() < 5)
            {
                accuracy = 6;
            }
            else if (table.GetDetailLevel() >= 5 && table.GetDetailLevel() < 8)
            {
                accuracy = 8;
            }
            else
            {
                accuracy = (int)(table.GetDetailLevel() * 1.3f);                 // see also below
            }

            // as solid rubbers are rendered into the static buffer, always use maximum precision
            if (_data.StaticRendering)
            {
                accuracy = (int)(10.0f * 1.2f);                 // see also above
            }

            if (acc != -1)
            {
                // hit shapes and UI display have the same, static, precision
                accuracy = acc;
            }

            var splineAccuracy = acc != -1 ? 4.0f * MathF.Pow(10.0f, (10.0f - PhysicsConstants.HitShapeDetailLevel) * (float)(1.0 / 1.5)) : -1.0f;
            var sv             = new SplineVertex(_data.DragPoints, _data.Thickness, table.GetDetailLevel(), (int)splineAccuracy);

            var numRings    = sv.VertexCount - 1;
            var numSegments = accuracy;

            var numVertices = numRings * numSegments;
            var numIndices  = 6 * numVertices;            //m_numVertices*2+2;
            var height      = _data.HitHeight + table.TableHeight;

            mesh.Vertices = new Vertex3DNoTex2[numVertices];
            mesh.Indices  = new int[numIndices];

            var prevB = new Vertex3D();
            var invNr = 1.0f / numRings;
            var invNs = 1.0f / numSegments;
            var index = 0;

            for (var i = 0; i < numRings; i++)
            {
                var i2      = i == numRings - 1 ? 0 : i + 1;
                var tangent = new Vertex3D(sv.MiddlePoints[i2].X - sv.MiddlePoints[i].X,
                                           sv.MiddlePoints[i2].Y - sv.MiddlePoints[i].Y, 0.0f);

                Vertex3D biNormal;
                Vertex3D normal;
                if (i == 0)
                {
                    var up = new Vertex3D(sv.MiddlePoints[i2].X + sv.MiddlePoints[i].X, sv.MiddlePoints[i2].Y + sv.MiddlePoints[i].Y, height * 2.0f);
                    normal   = new Vertex3D(tangent.Y * up.Z, -tangent.X * up.Z, tangent.X * up.Y - tangent.Y * up.X);                   // = CrossProduct(tangent, up)
                    biNormal = new Vertex3D(tangent.Y * normal.Z, -tangent.X * normal.Z, tangent.X * normal.Y - tangent.Y * normal.X);   // = CrossProduct(tangent, normal)
                }
                else
                {
                    normal   = prevB.Clone().Cross(tangent);
                    biNormal = tangent.Clone().Cross(normal);
                }

                biNormal.Normalize();
                normal.Normalize();
                prevB = biNormal;
                var u = i * invNr;
                for (var j = 0; j < numSegments; j++)
                {
                    var v   = (j + u) * invNs;
                    var tmp = Vertex3D.GetRotatedAxis(j * (360.0f * invNs), tangent, normal)
                              .MultiplyScalar(_data.Thickness * 0.5f);

                    mesh.Vertices[index] = new Vertex3DNoTex2 {
                        X = sv.MiddlePoints[i].X + tmp.X,
                        Y = sv.MiddlePoints[i].Y + tmp.Y
                    };
                    if (createHitShape && (j == 0 || j == 3))
                    {
                        //!! hack, adapt if changing detail level for hitshape
                        // for a hit shape create a more rectangle mesh and not a smooth one
                        tmp.Z *= 0.6f;
                    }

                    mesh.Vertices[index].Z = height + tmp.Z;
                    //texel
                    mesh.Vertices[index].Tu = u;
                    mesh.Vertices[index].Tv = v;
                    index++;
                }
            }

            // calculate faces
            for (var i = 0; i < numRings; i++)
            {
                for (var j = 0; j < numSegments; j++)
                {
                    var quad = new int[4];
                    quad[0] = i * numSegments + j;

                    if (j != numSegments - 1)
                    {
                        quad[1] = i * numSegments + j + 1;
                    }
                    else
                    {
                        quad[1] = i * numSegments;
                    }

                    if (i != numRings - 1)
                    {
                        quad[2] = (i + 1) * numSegments + j;
                        if (j != numSegments - 1)
                        {
                            quad[3] = (i + 1) * numSegments + j + 1;
                        }
                        else
                        {
                            quad[3] = (i + 1) * numSegments;
                        }
                    }
                    else
                    {
                        quad[2] = j;
                        if (j != numSegments - 1)
                        {
                            quad[3] = j + 1;
                        }
                        else
                        {
                            quad[3] = 0;
                        }
                    }

                    mesh.Indices[(i * numSegments + j) * 6]     = quad[0];
                    mesh.Indices[(i * numSegments + j) * 6 + 1] = quad[1];
                    mesh.Indices[(i * numSegments + j) * 6 + 2] = quad[2];
                    mesh.Indices[(i * numSegments + j) * 6 + 3] = quad[3];
                    mesh.Indices[(i * numSegments + j) * 6 + 4] = quad[2];
                    mesh.Indices[(i * numSegments + j) * 6 + 5] = quad[1];
                }
            }

            Mesh.ComputeNormals(mesh.Vertices, numVertices, mesh.Indices, numIndices);

            var maxX = Constants.FloatMin;
            var minX = Constants.FloatMax;
            var maxY = Constants.FloatMin;
            var minY = Constants.FloatMax;
            var maxZ = Constants.FloatMin;
            var minZ = Constants.FloatMax;

            for (var i = 0; i < numVertices; i++)
            {
                if (maxX < mesh.Vertices[i].X)
                {
                    maxX = mesh.Vertices[i].X;
                }

                if (minX > mesh.Vertices[i].X)
                {
                    minX = mesh.Vertices[i].X;
                }

                if (maxY < mesh.Vertices[i].Y)
                {
                    maxY = mesh.Vertices[i].Y;
                }

                if (minY > mesh.Vertices[i].Y)
                {
                    minY = mesh.Vertices[i].Y;
                }

                if (maxZ < mesh.Vertices[i].Z)
                {
                    maxZ = mesh.Vertices[i].Z;
                }

                if (minZ > mesh.Vertices[i].Z)
                {
                    minZ = mesh.Vertices[i].Z;
                }
            }

            MiddlePoint.X = (maxX + minX) * 0.5f;
            MiddlePoint.Y = (maxY + minY) * 0.5f;
            MiddlePoint.Z = (maxZ + minZ) * 0.5f;

            return(mesh);
        }
Example #39
0
 public void ShouldCorrectlyCrossVectors()
 {
     Vertex3D.CrossVectors(new Vertex3D(1.5f, 2.5f, 4f), new Vertex3D(3.5f, 100f, 95f))
     .Should().BeEquivalentTo(new Vertex3D(-162.5f, -128.5f, 141.25f));
 }
Example #40
0
 public TestBallCreator(float x, float y, float z, float vx, float vy, float vz)
 {
     _pos = new Vertex3D(x, y, z);
     _vel = new Vertex3D(vx, vy, vz);
 }
 public void Set(Vertex3D v)
 {
     base.Set(v.X, v.Y);
 }
 public static float3 ToUnityFloat3(this Vertex3D vertex)
 {
     return(new float3(vertex.X, vertex.Y, vertex.Z));
 }
 public new void Set(Vertex3D v)
 {
     base.Set(v);
 }
Example #44
0
		/// <param name="N">Number of cubes in single dimension (e.g. total cubes for 20 is 20^3=8000)</param>
		void generateVerticesAndIndices(int N, out Vertex3D[] vertices, out uint[] indices)
		{
			int cubeSide = 32;

			// ask Irrlicht to generate cube mesh for us (we use it like a template)

			Mesh cubeMesh = device.SceneManager.GeometryCreator.CreateCubeMesh(new Vector3Df(cubeSide));
			ushort[] cubeIndices = cubeMesh.GetMeshBuffer(0).Indices as ushort[];
			Vertex3D[] cubeVertices = cubeMesh.GetMeshBuffer(0).Vertices as Vertex3D[];
			cubeMesh.Drop();

			// generate cubes

			device.Logger.Log("Generating " + N * N * N + " cubes...");

			vertices = new Vertex3D[N * N * N * cubeVertices.Length];
			indices = new uint[N * N * N * cubeIndices.Length];

			int verticesIndex = 0;
			int indicesIndex = 0;
			int colorBase = (255 - cubeVertices.Length) / N;
			float cubePosOffset = 2.0f * cubeSide;

			for (int i = 0; i < N; i++)
			{
				for (int j = 0; j < N; j++)
				{
					for (int k = 0; k < N; k++)
					{
						// add indices
						uint firstfreeIndex = (uint)verticesIndex;
						for (int l = 0; l < cubeIndices.Length; l++)
							indices[indicesIndex++] = firstfreeIndex + cubeIndices[l];

						// add vertices
						for (int l = 0; l < cubeVertices.Length; l++)
						{
							Vertex3D v = new Vertex3D(cubeVertices[l]);
							v.Color = new Color(i * colorBase + l, j * colorBase + l, k * colorBase + l);
							v.Position += new Vector3Df(i, j, k) * cubePosOffset;
							vertices[verticesIndex++] = v;
						}
					}
				}

				device.Logger.Log(
					(((i + 1) * 100) / N) + "%: " +
					(i + 1) * N * N + " cubes has been generated. ~" +
					Program.MemUsageText);

				if ((i & 0xf) == 0xf)
					GC.Collect();
			}
		}
Example #45
0
		/// <summary>
		/// Generates a MeshBuffer which represents all the vertices and indices for values of y
		/// between y0 and y1, and add it to the mesh.
		/// </summary>
		void addStrip(HeightMap map, ColorFunc cf, int y0, int y1)
		{
			Vertex3D[] vertices = new Vertex3D[(y1 - y0 + 1) * width];
			ushort[] indices = new ushort[(y1 - y0) * (width - 1) * 6]; // "6" is a number of indices in 2 triangles (which forms a quad)

			// calculate vertices

			int i = 0;
			for (int y = y0; y <= y1; ++y)
			{
				for (int x = 0; x < width; ++x)
				{
					float z = map.GetHeight(x, y);
					float xf = (float)x / (float)width;
					float yf = (float)y / (float)height;

					vertices[i++] = new Vertex3D(
						new Vector3Df(x, scale * z, y), // position
						map.GetNormal(x, y, scale), // normal
						calculate(cf, xf, yf, z), // color
						new Vector2Df(xf, yf) // tcoords
					);
				}
			}

			// calculate indices

			i = 0;
			for (int y = y0; y < y1; ++y)
			{
				for (int x = 0; x < width - 1; ++x)
				{
					int n = (y - y0) * width + x;
					indices[i++] = (ushort)n;
					indices[i++] = (ushort)(n + width);
					indices[i++] = (ushort)(n + width + 1);
					indices[i++] = (ushort)(n + width + 1);
					indices[i++] = (ushort)(n + 1);
					indices[i++] = (ushort)n;
				}
			}

			// append calculated verices and indices to mesh buffer

			MeshBuffer buf = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit); // create new buffer
			Mesh.AddMeshBuffer(buf);
			buf.Append(vertices, indices);
			buf.RecalculateBoundingBox();
			buf.Drop();
		}