private void CreatePrefabPlane()
        {
            Mesh    mesh    = (Mesh)Create("Prefab_Plane");
            SubMesh subMesh = mesh.CreateSubMesh("Prefab_Plane_Submesh");

            float[] vertices =
            {
                -100, -100, 0, // pos
                0,       0, 1, // normal
                0,       1,    // texcoord
                100,  -100, 0,
                0,       0, 1,
                1,       1,
                100,   100, 0,
                0,       0, 1,
                1,       0,
                -100,  100, 0,
                0,       0, 1,
                0, 0
            };

            mesh.SharedVertexData             = new VertexData();
            mesh.SharedVertexData.vertexCount = 4;
            VertexDeclaration   vertexDeclaration = mesh.SharedVertexData.vertexDeclaration;
            VertexBufferBinding binding           = mesh.SharedVertexData.vertexBufferBinding;

            int offset = 0;

            vertexDeclaration.AddElement(0, offset, VertexElementType.Float3, VertexElementSemantic.Position);
            offset += VertexElement.GetTypeSize(VertexElementType.Float3);

            vertexDeclaration.AddElement(0, offset, VertexElementType.Float3, VertexElementSemantic.Normal);
            offset += VertexElement.GetTypeSize(VertexElementType.Float3);

            vertexDeclaration.AddElement(0, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 0);
            offset += VertexElement.GetTypeSize(VertexElementType.Float2);

            // allocate vertex buffer
            HardwareVertexBuffer vertexBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(offset, 4, BufferUsage.StaticWriteOnly);

            // set up the binding, one source only
            binding.SetBinding(0, vertexBuffer);

            vertexBuffer.WriteData(0, vertexBuffer.Size, vertices, true);

            subMesh.useSharedVertices = true;

            HardwareIndexBuffer indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer(IndexType.Size16, 6, BufferUsage.StaticWriteOnly);

            short[] faces = { 0, 1, 2, 0, 2, 3 };
            subMesh.indexData.indexBuffer = indexBuffer;
            subMesh.indexData.indexCount  = 6;
            subMesh.indexData.indexStart  = 0;
            indexBuffer.WriteData(0, indexBuffer.Size, faces, true);

            mesh.BoundingBox          = new AxisAlignedBox(new Vector3(-100, -100, 0), new Vector3(100, 100, 0));
            mesh.BoundingSphereRadius = MathUtil.Sqrt(100 * 100 + 100 * 100);

            resourceList.Add(mesh.Name, mesh);
        }
Example #2
0
        private void CreateBuffers(ushort[] indices, short[] vertices)
        {
            var numIndices  = indices.Length;
            var numVertices = vertices.Length;

            _vertexDeclaration = HardwareBufferManager.Instance.CreateVertexDeclaration();
            _vertexDeclaration.AddElement(0, 0, VertexElementType.Short2, VertexElementSemantic.Position);
            _ib = HardwareBufferManager.Instance.CreateIndexBuffer(IndexType.Size16, numIndices, BufferUsage.WriteOnly);
            _vb = HardwareBufferManager.Instance.CreateVertexBuffer(_vertexDeclaration, numVertices, BufferUsage.WriteOnly, false);

            _ib.WriteData(0, numIndices * sizeof(ushort), indices, true);
            _vb.WriteData(0, numVertices * sizeof(ushort), vertices, true);

            var binding = new VertexBufferBinding();

            binding.SetBinding(0, _vb);

            VertexData = new VertexData();
            VertexData.vertexDeclaration   = _vertexDeclaration;
            VertexData.vertexBufferBinding = binding;
            VertexData.vertexCount         = numVertices;
            VertexData.vertexStart         = 0;

            IndexData             = new IndexData();
            IndexData.indexBuffer = _ib;
            IndexData.indexCount  = numIndices;
            IndexData.indexStart  = 0;
        }
Example #3
0
        /// <summary>Calculate WaterMesh precise Normals for each Vertex on Grid</summary>
        public void CalculateNormals()
        {
            Vector3 p0, p1, p2, p3, fn1, fn2;

            // Initialize Vertex Normals to ZERO
            for (int i = 0; i < cmplx + 1; i++)
            {
                for (int j = 0; j < cmplx + 1; j++)
                {
                    vNorms[i, j] = Vector3.Zero;
                }
            }

            // Calculate Normal for each Face, and add it to the normal for each Vertex
            for (int i = 0; i < cmplx; i++)
            {
                for (int j = 0; j < cmplx; j++)
                {
                    // Define 4-points of this grid square (top-left, top-right, bottom-left, bottom-right)
                    p0 = vBuf[i, j];
                    p1 = vBuf[i, j + 1];
                    p2 = vBuf[i + 1, j];
                    p3 = vBuf[i + 1, j + 1];

                    // Calc Face Normals for both Triangles of each grid square
                    fn1 = ((Vector3)(p2 - p0)).Cross(p1 - p0);
                    fn2 = ((Vector3)(p1 - p3)).Cross(p2 - p3);

                    // Add Face Normals to the adjacent Vertex Normals
                    vNorms[i, j]         += fn1;                        // top left
                    vNorms[i, j + 1]     += (fn1 + fn2);                // top right (adjacent to both triangles)
                    vNorms[i + 1, j]     += (fn1 + fn2);                // bottom left (adjacent to both triangles)
                    vNorms[i + 1, j + 1] += fn2;                        // bottom right
                }
            }
            // Normalize the Vertex normals, and write it to the Normal Buffer
            for (int i = 0; i <= cmplx; i++)
            {
                for (int j = 0; j <= cmplx; j++)
                {
                    vNorms[i, j].Normalize();
                }
            }
            normVBuf.WriteData(0, normVBuf.Size, vNorms, true);
        }
Example #4
0
        }         // end WaterMesh Constructor

        public void UpdateMesh(float timeSinceLastFrame)
        {
            lastFrameTime  = timeSinceLastFrame;
            lastTimeStamp += timeSinceLastFrame;

            // do rendering to get ANIMATIONS_PER_SECOND
            while (lastAnimationTimeStamp <= lastTimeStamp)
            {
                // switch buffer numbers
                curBufNum        = (curBufNum + 1) % 3;
                Vector3[,] vbuf0 = vBufs[curBufNum];                 // new frame
                Vector3[,] vbuf1 = vBufs[(curBufNum + 2) % 3];       // 1-frame ago
                Vector3[,] vbuf2 = vBufs[(curBufNum + 1) % 3];       // 2-frames ago

                // Algorithm from http://collective.valve-erc.com/index.php?go=water_simulation
                double C     = PARAM_C;             // ripple speed
                double D     = PARAM_D;             // distance
                double U     = PARAM_U;             // viscosity
                double T     = PARAM_T;             // time
                float  TERM1 = (float)((4.0f - 8.0f * C * C * T * T / (D * D)) / (U * T + 2));
                float  TERM2 = (float)((U * T - 2.0f) / (U * T + 2.0f));
                float  TERM3 = (float)((2.0f * C * C * T * T / (D * D)) / (U * T + 2));
                for (int i = 1; i < cmplx; i++)
                {
                    // don't do anything with border values
                    for (int j = 1; j < cmplx; j++)
                    {
                        vbuf0[i, j].y = TERM1 * vbuf1[i, j].y + TERM2 * vbuf2[i, j].y +
                                        TERM3 * (vbuf1[i, j - 1].y + vbuf1[i, j + 1].y + vbuf1[i - 1, j].y + vbuf1[i + 1, j].y);
                    }
                }

                lastAnimationTimeStamp += (1.0f / ANIMATIONS_PER_SECOND);
            }

            vBuf = vBufs[curBufNum];

            if (useFakeNormals)
            {
                CalculateFakeNormals();
            }
            else
            {
                CalculateNormals();
            }

            // set vertex buffer
            posVBuf.WriteData(0, posVBuf.Size, vBufs[curBufNum], true);
        }
Example #5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="v1"></param>
        /// <param name="v2"></param>
        /// <param name="v3"></param>
        public Triangle(Vector3 v1, Vector3 v2, Vector3 v3, ColorEx c1, ColorEx c2, ColorEx c3)
        {
            vertexData             = new VertexData();
            vertexData.vertexCount = 3;
            vertexData.vertexStart = 0;

            VertexDeclaration   decl    = vertexData.vertexDeclaration;
            VertexBufferBinding binding = vertexData.vertexBufferBinding;

            // add a position and color element to the declaration
            decl.AddElement(POSITION, 0, VertexElementType.Float3, VertexElementSemantic.Position);
            decl.AddElement(COLOR, 0, VertexElementType.Color, VertexElementSemantic.Diffuse);

            // POSITIONS
            // create a vertex buffer for the position
            HardwareVertexBuffer buffer =
                HardwareBufferManager.Instance.CreateVertexBuffer(
                    decl.GetVertexSize(POSITION),
                    vertexData.vertexCount,
                    BufferUsage.StaticWriteOnly);

            Vector3[] positions = new Vector3[] { v1, v2, v3 };

            // write the positions to the buffer
            buffer.WriteData(0, buffer.Size, positions, true);

            // bind the position buffer
            binding.SetBinding(POSITION, buffer);

            // COLORS
            // create a color buffer
            buffer = HardwareBufferManager.Instance.CreateVertexBuffer(
                decl.GetVertexSize(COLOR),
                vertexData.vertexCount,
                BufferUsage.StaticWriteOnly);

            // create an int array of the colors to use.
            // note: these must be converted to the current API's
            // preferred packed int format
            uint[] colors = new uint[] {
                Root.Instance.RenderSystem.ConvertColor(c1),
                Root.Instance.RenderSystem.ConvertColor(c2),
                Root.Instance.RenderSystem.ConvertColor(c3)
            };

            // write the colors to the color buffer
            buffer.WriteData(0, buffer.Size, colors, true);

            // bind the color buffer
            binding.SetBinding(COLOR, buffer);

            // MATERIAL
            // grab a copy of the BaseWhite material for our use
            Material material = MaterialManager.Instance.GetByName("BaseWhite");

            material = material.Clone("TriMat");

            // disable lighting to vertex colors are used
            material.Lighting = false;
            // set culling to none so the triangle is drawn 2 sided
            material.CullingMode = CullingMode.None;

            materialName = "TriMat";

            this.Material = material;

            // set the bounding box of the tri
            // TODO: not right, but good enough for now
            this.box = new AxisAlignedBox(new Vector3(25, 50, 0), new Vector3(-25, 0, 0));
        }
Example #6
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="startPoint">Point where the line will start.</param>
        /// <param name="direction">The direction the vector is heading in.</param>
        /// <param name="length">The length (magnitude) of the line vector.</param>
        /// <param name="color">The color which this line should be.</param>
        public Line3d(Vector3 startPoint, Vector3 direction, float length, ColorEx color)
        {
            // normalize the direction vector to ensure all elements fall in [0,1] range.
            direction.Normalize();

            // calculate the actual endpoint
            Vector3 endPoint = startPoint + (direction * length);

            vertexData             = new VertexData();
            vertexData.vertexCount = 2;
            vertexData.vertexStart = 0;

            VertexDeclaration   decl    = vertexData.vertexDeclaration;
            VertexBufferBinding binding = vertexData.vertexBufferBinding;

            // add a position and color element to the declaration
            decl.AddElement(POSITION, 0, VertexElementType.Float3, VertexElementSemantic.Position);
            decl.AddElement(COLOR, 0, VertexElementType.Color, VertexElementSemantic.Diffuse);

            // create a vertex buffer for the position
            HardwareVertexBuffer buffer =
                HardwareBufferManager.Instance.CreateVertexBuffer(
                    decl.GetVertexSize(POSITION),
                    vertexData.vertexCount,
                    BufferUsage.StaticWriteOnly);

            Vector3[] pos = new Vector3[] { startPoint, endPoint };

            // write the data to the position buffer
            buffer.WriteData(0, buffer.Size, pos, true);

            // bind the position buffer
            binding.SetBinding(POSITION, buffer);

            // create a color buffer
            buffer = HardwareBufferManager.Instance.CreateVertexBuffer(
                decl.GetVertexSize(COLOR),
                vertexData.vertexCount,
                BufferUsage.StaticWriteOnly);

            uint colorValue = Root.Instance.RenderSystem.ConvertColor(color);

            uint[] colors = new uint[] { colorValue, colorValue };

            // write the data to the position buffer
            buffer.WriteData(0, buffer.Size, colors, true);

            // bind the color buffer
            binding.SetBinding(COLOR, buffer);

            // MATERIAL
            // grab a copy of the BaseWhite material for our use
            Material material = MaterialManager.Instance.GetByName("BaseWhite");

            material = material.Clone("LineMat");
            // disable lighting to vertex colors are used
            material.Lighting = false;
            // set culling to none so the triangle is drawn 2 sided
            material.CullingMode = CullingMode.None;

            this.Material = material;

            // set the bounding box of the line
            this.box = new AxisAlignedBox(startPoint, endPoint);
        }
Example #7
0
        private void LoadLevelVertices(Quake3Level q3lvl)
        {
            //-----------------------------------------------------------------------
            // Vertices
            //-----------------------------------------------------------------------
            // Allocate memory for vertices & copy
            vertexData = new VertexData();

            // Create vertex declaration
            VertexDeclaration decl = vertexData.vertexDeclaration;
            int offset             = 0;
            int lightTexOffset     = 0;

            decl.AddElement(0, offset, VertexElementType.Float3, VertexElementSemantic.Position);
            offset += VertexElement.GetTypeSize(VertexElementType.Float3);
            decl.AddElement(0, offset, VertexElementType.Float3, VertexElementSemantic.Normal);
            offset += VertexElement.GetTypeSize(VertexElementType.Float3);
            decl.AddElement(0, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 0);
            offset += VertexElement.GetTypeSize(VertexElementType.Float2);
            decl.AddElement(0, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 1);

            // Build initial patches - we need to know how big the vertex buffer needs to be
            // to accommodate the subdivision
            // we don't want to include the elements for texture lighting, so we clone it
            InitQuake3Patches(q3lvl, (VertexDeclaration)decl.Clone());

            // this is for texture lighting color and alpha
            decl.AddElement(1, lightTexOffset, VertexElementType.Color, VertexElementSemantic.Diffuse);
            lightTexOffset += VertexElement.GetTypeSize(VertexElementType.Color);
            // this is for texture lighting coords
            decl.AddElement(1, lightTexOffset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 2);


            // Create the vertex buffer, allow space for patches
            HardwareVertexBuffer vbuf = HardwareBufferManager.Instance.CreateVertexBuffer(
                Marshal.SizeOf(typeof(BspVertex)),
                q3lvl.NumVertices + patchVertexCount,
                BufferUsage.StaticWriteOnly,
                // the vertices will be read often for texture lighting, use shadow buffer
                true
                );

            // Create the vertex buffer for texture lighting, allow space for patches
            HardwareVertexBuffer texLightBuf = HardwareBufferManager.Instance.CreateVertexBuffer(
                Marshal.SizeOf(typeof(TextureLightMap)),
                q3lvl.NumVertices + patchVertexCount,
                BufferUsage.DynamicWriteOnly,
                false
                );

            // COPY static vertex data - Note that we can't just block-copy the vertex data because we have to reorder
            // our vertex elements; this is to ensure compatibility with older cards when using
            // hardware vertex buffers - Direct3D requires that the buffer format maps onto a
            // FVF in those older drivers.
            // Lock just the non-patch area for now.

            unsafe
            {
                BspVertex       vert        = new BspVertex();
                TextureLightMap texLightMap = new TextureLightMap();

                // Keep another base pointer for use later in patch building
                for (int v = 0; v < q3lvl.NumVertices; v++)
                {
                    QuakeVertexToBspVertex(q3lvl.Vertices[v], out vert, out texLightMap);

                    BspVertex *      bvptr = &vert;
                    TextureLightMap *tlptr = &texLightMap;

                    vbuf.WriteData(
                        v * sizeof(BspVertex),
                        sizeof(BspVertex),
                        (IntPtr)bvptr
                        );

                    texLightBuf.WriteData(
                        v * sizeof(TextureLightMap),
                        sizeof(TextureLightMap),
                        (IntPtr)tlptr
                        );
                }
            }

            // Setup binding
            vertexData.vertexBufferBinding.SetBinding(0, vbuf);

            // Setup texture lighting binding
            vertexData.vertexBufferBinding.SetBinding(1, texLightBuf);

            // Set other data
            vertexData.vertexStart = 0;
            vertexData.vertexCount = q3lvl.NumVertices + patchVertexCount;
        }
Example #8
0
        /// <summary>
        ///
        /// </summary>
        protected void Initialize()
        {
            // Create geometry
            int nvertices = this.slices * 4;           // n+1 planes
            int elemsize  = 3 * 3;
            int dsize     = elemsize * nvertices;
            int x;

            var indexData  = new IndexData();
            var vertexData = new VertexData();
            var vertices   = new float[dsize];

            var coords = new float[4, 2]
            {
                {
                    0.0f, 0.0f
                }, {
                    0.0f, 1.0f
                }, {
                    1.0f, 0.0f
                }, {
                    1.0f, 1.0f
                }
            };

            for (x = 0; x < this.slices; x++)
            {
                for (int y = 0; y < 4; y++)
                {
                    float xcoord = coords[y, 0] - 0.5f;
                    float ycoord = coords[y, 1] - 0.5f;
                    float zcoord = -((float)x / (float)(this.slices - 1) - 0.5f);
                    // 1.0f .. a/(a+1)
                    // coordinate
                    vertices[x * 4 * elemsize + y * elemsize + 0] = xcoord * (this.size / 2.0f);
                    vertices[x * 4 * elemsize + y * elemsize + 1] = ycoord * (this.size / 2.0f);
                    vertices[x * 4 * elemsize + y * elemsize + 2] = zcoord * (this.size / 2.0f);
                    // normal
                    vertices[x * 4 * elemsize + y * elemsize + 3] = 0.0f;
                    vertices[x * 4 * elemsize + y * elemsize + 4] = 0.0f;
                    vertices[x * 4 * elemsize + y * elemsize + 5] = 1.0f;
                    // tex
                    vertices[x * 4 * elemsize + y * elemsize + 6] = xcoord * Utility.Sqrt(3.0f);
                    vertices[x * 4 * elemsize + y * elemsize + 7] = ycoord * Utility.Sqrt(3.0f);
                    vertices[x * 4 * elemsize + y * elemsize + 8] = zcoord * Utility.Sqrt(3.0f);
                }
            }

            var faces = new short[this.slices * 6];

            for (x = 0; x < this.slices; x++)
            {
                faces[x * 6 + 0] = (short)(x * 4 + 0);
                faces[x * 6 + 1] = (short)(x * 4 + 1);
                faces[x * 6 + 2] = (short)(x * 4 + 2);
                faces[x * 6 + 3] = (short)(x * 4 + 1);
                faces[x * 6 + 4] = (short)(x * 4 + 2);
                faces[x * 6 + 5] = (short)(x * 4 + 3);
            }

            //setup buffers
            vertexData.vertexStart = 0;
            vertexData.vertexCount = nvertices;

            VertexDeclaration   decl = vertexData.vertexDeclaration;
            VertexBufferBinding bind = vertexData.vertexBufferBinding;
            int offset = 0;

            offset += decl.AddElement(0, 0, VertexElementType.Float3, VertexElementSemantic.Position).Size;
            offset += decl.AddElement(0, offset, VertexElementType.Float3, VertexElementSemantic.Normal).Size;
            offset += decl.AddElement(0, offset, VertexElementType.Float3, VertexElementSemantic.TexCoords).Size;

            HardwareVertexBuffer vertexBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(decl, nvertices,
                                                                                                  BufferUsage.StaticWriteOnly);

            bind.SetBinding(0, vertexBuffer);

            HardwareIndexBuffer indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer(IndexType.Size16, this.slices * 6,
                                                                                               BufferUsage.StaticWriteOnly);

            indexData.indexBuffer = indexBuffer;
            indexData.indexCount  = this.slices * 6;
            indexData.indexStart  = 0;

            indexBuffer.WriteData(0, indexBuffer.Size, faces, true);
            vertexBuffer.WriteData(0, vertexBuffer.Size, vertices);
            vertices = null;
            faces    = null;

            // Now make the render operation
            renderOperation.operationType = OperationType.TriangleList;
            renderOperation.indexData     = indexData;
            renderOperation.vertexData    = vertexData;
            renderOperation.useIndices    = true;

            // Create a brand new private material
            if (!ResourceGroupManager.Instance.GetResourceGroups().Contains("VolumeRendable"))
            {
                ResourceGroupManager.Instance.CreateResourceGroup("VolumeRendable");
            }

            var material = (Material)MaterialManager.Instance.Create(this.texture, "VolumeRendable");

            // Remove pre-created technique from defaults
            material.RemoveAllTechniques();

            // Create a techinique and a pass and a texture unit
            Technique        technique   = material.CreateTechnique();
            Pass             pass        = technique.CreatePass();
            TextureUnitState textureUnit = pass.CreateTextureUnitState();

            // Set pass parameters
            pass.SetSceneBlending(SceneBlendType.TransparentAlpha);
            pass.DepthWrite      = false;
            pass.CullingMode     = CullingMode.None;
            pass.LightingEnabled = false;
            textureUnit.SetTextureAddressingMode(TextureAddressing.Clamp);
            textureUnit.SetTextureName(this.texture, TextureType.ThreeD);
            textureUnit.SetTextureFiltering(TextureFiltering.Trilinear);

            this.unit     = textureUnit;
            base.material = material;
        }
Example #9
0
        public WaterMesh(String meshName, float planeSize, int cmplx)           // najak R-F
        // Assign Fields to the Initializer values
        {
            this.meshName = meshName;
            this.size     = planeSize;
            this.cmplx    = cmplx;                         // Number of Rows/Columns in the Water Grid representation
            cmplxAdj      = (float)Math.Pow((cmplx / 64f), 1.4f) * 2;
            numFaces      = 2 * (int)Math.Pow(cmplx, 2);   // Each square is split into 2 triangles.
            numVertices   = (int)Math.Pow((cmplx + 1), 2); // Vertex grid is (Complexity+1) squared

            // Allocate and initialize space for calculated Normals
            vNorms = new Vector3[cmplx + 1, cmplx + 1];        // vertex Normals for each grid point
            fNorms = new Vector3[cmplx, cmplx, 2];             // face Normals for each triangle

            // Create mesh and submesh to represent the Water
            mesh    = (Mesh)MeshManager.Instance.CreateManual(meshName);
            subMesh = mesh.CreateSubMesh();
            subMesh.useSharedVertices = false;

            // Construct metadata to describe the buffers associated with the water submesh
            subMesh.vertexData             = new VertexData();
            subMesh.vertexData.vertexStart = 0;
            subMesh.vertexData.vertexCount = numVertices;

            // Define local variables to point to the VertexData Properties
            VertexDeclaration   vdecl = subMesh.vertexData.vertexDeclaration;            // najak: seems like metadata
            VertexBufferBinding vbind = subMesh.vertexData.vertexBufferBinding;          // najak: pointer to actual buffer

            //najak: Set metadata to describe the three vertex buffers that will be accessed.
            vdecl.AddElement(0, 0, VertexElementType.Float3, VertexElementSemantic.Position);
            vdecl.AddElement(1, 0, VertexElementType.Float3, VertexElementSemantic.Normal);
            vdecl.AddElement(2, 0, VertexElementType.Float2, VertexElementSemantic.TexCoords);

            // Prepare buffer for positions - todo: first attempt, slow
            // Create the Position Vertex Buffer and Bind it index 0 - Write Only
            posVBuf = HwBufMgr.CreateVertexBuffer(3 * 4, numVertices, BufferUsage.DynamicWriteOnly);
            vbind.SetBinding(0, posVBuf);

            // Prepare buffer for normals - write only
            // Create the Normals Buffer and Bind it to index 1 - Write only
            normVBuf = HwBufMgr.CreateVertexBuffer(3 * 4, numVertices, BufferUsage.DynamicWriteOnly);
            vbind.SetBinding(1, normVBuf);

            // Prepare Texture Coordinates buffer (static, written only once)
            // Creates a 2D buffer of 2D coordinates: (Complexity X Complexity), pairs.
            //    Each pair indicates the normalized coordinates of the texture to map to.
            //    (0,1.00), (0.02, 1.00), (0.04, 1.00), ... (1.00,1.00)
            //    (0,0.98), (0.02, 0.98), (0.04, 1.00), ... (1.00,0.98)
            //    ...
            //    (0,0.00), (0.02, 0.00), (0.04, 0.00), ... (1.00,0.00)
            // This construct is simple and is used to calculate the Texture map.
            // Todo: Write directly to the buffer, when Axiom supports this in safe manner
            float[,,] tcBufDat = new float[cmplx + 1, cmplx + 1, 2];
            for (int i = 0; i <= cmplx; i++)
            {
                // 2D column iterator for texture map
                for (int j = 0; j <= cmplx; j++)
                {
                    // 2D row iterator for texture map
                    // Define the normalized(0..1) X/Y-coordinates for this element of the 2D grid
                    tcBufDat[i, j, 0] = (float)i / cmplx;
                    tcBufDat[i, j, 1] = 1.0f - ((float)j / (cmplx));
                }
            }

            // Now Create the actual hardware buffer to contain the Texture Coordinate 2d map.
            //   and Bind it to buffer index 2
            tcVBuf = HwBufMgr.CreateVertexBuffer(2 * 4, numVertices, BufferUsage.StaticWriteOnly);
            tcVBuf.WriteData(0, tcVBuf.Size, tcBufDat, true);
            vbind.SetBinding(2, tcVBuf);

            // Create a Graphics Buffer on non-shared vertex indices (3 points for each triangle).
            //  Since the water grid consist of [Complexity x Complexity] squares, each square is
            //  split into 2 right triangles 45-90-45.  That is how the water mesh is constructed.
            //  Therefore the number of faces = 2 * Complexity * Complexity
            ushort[,,] idxBuf = new ushort[cmplx, cmplx, 6];
            for (int i = 0; i < cmplx; i++)                // iterate the rows
            {
                for (int j = 0; j < cmplx; j++)            // iterate the columns
                // Define 4 corners of each grid
                {
                    ushort p0 = (ushort)(i * (cmplx + 1) + j);                 // top left point on square
                    ushort p1 = (ushort)(i * (cmplx + 1) + j + 1);             // top right
                    ushort p2 = (ushort)((i + 1) * (cmplx + 1) + j);           // bottom left
                    ushort p3 = (ushort)((i + 1) * (cmplx + 1) + j + 1);       // bottom right

                    // Split Square Grid element into 2 adjacent triangles.
                    idxBuf[i, j, 0] = p2; idxBuf[i, j, 1] = p1; idxBuf[i, j, 2] = p0;               // top-left triangle
                    idxBuf[i, j, 3] = p2; idxBuf[i, j, 4] = p3; idxBuf[i, j, 5] = p1;               // bottom-right triangle
                }
            }
            // Copy Index Buffer to the Hardware Index Buffer
            HardwareIndexBuffer hdwrIdxBuf = HwBufMgr.CreateIndexBuffer(IndexType.Size16, 3 * numFaces, BufferUsage.StaticWriteOnly, true);

            hdwrIdxBuf.WriteData(0, numFaces * 3 * 2, idxBuf, true);

            // Set index buffer for this submesh
            subMesh.indexData.indexBuffer = hdwrIdxBuf;
            subMesh.indexData.indexStart  = 0;
            subMesh.indexData.indexCount  = 3 * numFaces;

            //Prepare Vertex Position Buffers (Note: make 3, since each frame is function of previous two)
            vBufs = new Vector3[3][, ];
            for (int b = 0; b < 3; b++)
            {
                vBufs[b] = new Vector3[cmplx + 1, cmplx + 1];
                for (int y = 0; y <= cmplx; y++)
                {
                    for (int x = 0; x <= cmplx; x++)
                    {
                        vBufs[b][y, x].x = (float)(x) / (float)(cmplx) * (float)size;
                        vBufs[b][y, x].y = 0;
                        vBufs[b][y, x].z = (float)(y) / (float)(cmplx) * (float)size;
                    }
                }
            }

            curBufNum = 0;
            vBuf      = vBufs[curBufNum];
            posVBuf.WriteData(0, posVBuf.Size, vBufs[0], true);

            AxisAlignedBox meshBounds = new AxisAlignedBox(new Vector3(0, 0, 0), new Vector3(size, 0, size));

            mesh.BoundingBox = meshBounds;              //	mesh->_setBounds(meshBounds); // najak: can't find _setBounds()

            mesh.Load();
            mesh.Touch();
        }         // end WaterMesh Constructor