private bool GetHeightInTriangle(SimulationTriangle t, Vector3 p, out float h) { Vector2 A, B, C, P; Vector2 v0, v1, v2; float invDenom, u, v; bool IsInTriangle = false; h = 0; A = new Vector2(mVertex[t.I0].X, mVertex[t.I0].Z); B = new Vector2(mVertex[t.I1].X, mVertex[t.I1].Z); C = new Vector2(mVertex[t.I2].X, mVertex[t.I2].Z); P = new Vector2(p.X, p.Z); v0 = C - A; v1 = B - A; v2 = P - A; // Compute dot products float dot00, dot01, dot02, dot11, dot12; Vector2.Dot(ref v0, ref v0, out dot00); Vector2.Dot(ref v0, ref v1, out dot01); Vector2.Dot(ref v0, ref v2, out dot02); Vector2.Dot(ref v1, ref v1, out dot11); Vector2.Dot(ref v1, ref v2, out dot12); // Compute barycentric coordinates invDenom = 1f / (dot00 * dot11 - dot01 * dot01); u = (dot11 * dot02 - dot01 * dot12) * invDenom; v = (dot00 * dot12 - dot01 * dot02) * invDenom; // Check if point is in triangle if ((u >= 0) & (v >= 0) & (u + v <= 1)) { IsInTriangle = true; h = mVertex[t.I0].Y + u * (mVertex[t.I2].Y - mVertex[t.I0].Y) + v * (mVertex[t.I1].Y - mVertex[t.I0].Y); } return(IsInTriangle); }
//protected override void LoadContent() //{ // base.LoadContent(); // //load the wave maps // mWaveMap0 = Game.Content.Load<Texture2D>(mOptions.WaveMapAsset0); // mWaveMap1 = Game.Content.Load<Texture2D>(mOptions.WaveMapAsset1); // //get the attributes of the back buffer // PresentationParameters pp = Game.GraphicsDevice.PresentationParameters; // SurfaceFormat format = pp.BackBufferFormat; // MultiSampleType msType = pp.MultiSampleType; // int msQuality = pp.MultiSampleQuality; // //create the reflection and refraction render targets // //using the backbuffer attributes // mRefractionMap = new RenderTarget2D(Game.GraphicsDevice, mOptions.RenderTargetSize, mOptions.RenderTargetSize, // 1, format, msType, msQuality); // mReflectionMap = new RenderTarget2D(Game.GraphicsDevice, mOptions.RenderTargetSize, mOptions.RenderTargetSize, // 1, format, msType, msQuality); // mEffect = Game.Content.Load<Effect>(mEffectAsset); // //set the parameters that shouldn't change. // //Some of these might need to change every once in awhile, // //move them to updateEffectParams function if you need that functionality. // if (mEffect != null) // { // mEffect.Parameters["WaveMap0"].SetValue(mWaveMap0); // mEffect.Parameters["WaveMap1"].SetValue(mWaveMap1); // mEffect.Parameters["TexScale"].SetValue(mOptions.WaveMapScale); // mEffect.Parameters["WaterColor"].SetValue(mOptions.WaterColor); // mEffect.Parameters["SunColor"].SetValue(mOptions.SunColor); // mEffect.Parameters["SunDirection"].SetValue(Vector3.Normalize(mOptions.SunDirection)); // mEffect.Parameters["SunFactor"].SetValue(mOptions.SunFactor); // mEffect.Parameters["SunPower"].SetValue(mOptions.SunPower); // mEffect.Parameters["World"].SetValue(mWorld); // } //} //public override void Update(GameTime gameTime) //{ // float timeDelta = (float)gameTime.ElapsedGameTime.TotalSeconds; // // Update the wave map offsets so that they will scroll across the water // mOptions.WaveMapOffset0 += mOptions.WaveMapVelocity0 * timeDelta; // mOptions.WaveMapOffset1 += mOptions.WaveMapVelocity1 * timeDelta; // if (mOptions.WaveMapOffset0.X >= 1.0f || mOptions.WaveMapOffset0.X <= -1.0f) // mOptions.WaveMapOffset0.X = 0.0f; // if (mOptions.WaveMapOffset1.X >= 1.0f || mOptions.WaveMapOffset1.X <= -1.0f) // mOptions.WaveMapOffset1.X = 0.0f; // if (mOptions.WaveMapOffset0.Y >= 1.0f || mOptions.WaveMapOffset0.Y <= -1.0f) // mOptions.WaveMapOffset0.Y = 0.0f; // if (mOptions.WaveMapOffset1.Y >= 1.0f || mOptions.WaveMapOffset1.Y <= -1.0f) // mOptions.WaveMapOffset1.Y = 0.0f; //} //public override void Draw(GameTime gameTime) //{ // // Don't cull back facing triangles since we want the water to be visible // // from beneath the water plane too // Game.GraphicsDevice.RenderState.CullMode = CullMode.None; // if (Global.gWaterShowWireFrame) Game.GraphicsDevice.RenderState.FillMode = FillMode.WireFrame; // UpdateEffectParams(); // mEffect.Parameters["Time"].SetValue(tWave); // Game.GraphicsDevice.Indices = mIndexBuffer; // Game.GraphicsDevice.Vertices[0].SetSource(mVertexBuffer, 0, VertexPositionNormalTexture.SizeInBytes); // Game.GraphicsDevice.VertexDeclaration = mDecl; // mEffect.Begin(SaveStateMode.None); // foreach (EffectPass pass in mEffect.CurrentTechnique.Passes) // { // pass.Begin(); // Game.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, mNbVertices, 0, mNbTris); // pass.End(); // } // mEffect.End(); // Game.GraphicsDevice.RenderState.CullMode = CullMode.CullCounterClockwiseFace; // if (Global.gWaterShowWireFrame) Game.GraphicsDevice.RenderState.FillMode = FillMode.Solid; //} //public void SetCamera(Matrix4d viewProj, Vector3d pos) //{ // // Set the ViewProjection matrix and position of the Camera. // mViewProj = viewProj; // mViewPos = pos; //} //public void UpdateWaterMaps(GameTime gameTime) //{ // // Updates the reflection and refraction maps. Called on update. // /*------------------------------------------------------------------------------------------ // * Render to the Reflection Map // */ // //clip objects below the water line, and render the scene upside down // GraphicsDevice.RenderState.CullMode = CullMode.CullClockwiseFace; // GraphicsDevice.SetRenderTarget(0, mReflectionMap); // GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, mOptions.WaterColor, 1.0f, 0); // //reflection plane in local space // //the w value can be used to raise or lower the plane to hide gaps between objects and their // //reflection on the water. // Vector4 waterPlaneL = new Vector4(0.0f, -1.0f, 0.0f, 0.0f); // Matrix wInvTrans = Matrix.Invert(mWorld); // wInvTrans = Matrix.Transpose(wInvTrans); // //reflection plane in world space // Vector4d waterPlaneW = Vector4.Transform(waterPlaneL, wInvTrans); // Matrix wvpInvTrans = Matrix.Invert(mWorld * mViewProj); // wvpInvTrans = Matrix.Transpose(wvpInvTrans); // //reflection plane in homogeneous space // Vector4 waterPlaneH = Vector4.Transform(waterPlaneL, wvpInvTrans); // GraphicsDevice.ClipPlanes[0].IsEnabled = true; // GraphicsDevice.ClipPlanes[0].Plane = new Plane(waterPlaneH); // Matrix4d reflectionMatrix = Matrix4d.CreateReflection(new Plane(waterPlaneW)); // if (mDrawFunc != null) // mDrawFunc(reflectionMatrix); // GraphicsDevice.RenderState.CullMode = CullMode.CullCounterClockwiseFace; // GraphicsDevice.ClipPlanes[0].IsEnabled = false; // GraphicsDevice.SetRenderTarget(0, null); // /*------------------------------------------------------------------------------------------ // * Render to the Refraction Map // */ // //if the application is going to send us the refraction map // //exit early. The refraction map must be given to the water component // //before it renders. // //***This option can be handy if you're already drawing your scene to a render target*** // if (mGrabRefractionFromFB) // { // return; // } // //update the refraction map, clip objects above the water line // //so we don't get artifacts // GraphicsDevice.SetRenderTarget(0, mRefractionMap); // GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, mOptions.WaterColor, 1.0f, 1); // //only clip if the camera is above the water plane // if (mViewPos.Y > World.Translation.Y) // { // //refrection plane in local space // //here w=1.1f is a fudge factor so that we don't get gaps between objects and their refraction // //on the water. It effective raises or lowers the height of the clip plane. w=0.0 will be the clip plane // //at the water level. 1.1f raises the clip plane above the water level. // waterPlaneL = new Vector4(0.0f, -1.0f, 0.0f, 1.5f); // //refrection plane in world space // waterPlaneW = Vector4.Transform(waterPlaneL, wInvTrans); // //refrection plane in homogeneous space // waterPlaneH = Vector4.Transform(waterPlaneL, wvpInvTrans); // GraphicsDevice.ClipPlanes[0].IsEnabled = true; // GraphicsDevice.ClipPlanes[0].Plane = new Plane(waterPlaneH); // } // if (mDrawFunc != null) // mDrawFunc(Matrix.Identity); // GraphicsDevice.ClipPlanes[0].IsEnabled = false; // GraphicsDevice.SetRenderTarget(0, null); //} //void UpdateEffectParams() //{ // // Updates effect parameters related to the water shader // // Update the reflection and refraction textures // mEffect.Parameters["ReflectMap"].SetValue(mReflectionMap.GetTexture()); // mEffect.Parameters["RefractMap"].SetValue(mRefractionMap.GetTexture()); // // Normal map offsets // mEffect.Parameters["WaveMapOffset0"].SetValue(mOptions.WaveMapOffset0); // mEffect.Parameters["WaveMapOffset1"].SetValue(mOptions.WaveMapOffset1); // mEffect.Parameters["WorldViewProj"].SetValue(mWorld * mViewProj); // // Pass the position of the camera to the shader // mEffect.Parameters["EyePos"].SetValue(mViewPos); //} private void GenTriGrid(int numVertRows, int numVertCols, float dx, float dz, Vector3 center, out Vector3[] verts, out int[] indices) { // Generates a grid of vertices to use for the water plane. // "numVertRows" > Number of rows. Must be 2^n + 1. Ex. 129, 257, 513 // "numVertCols" > Number of columns. Must be 2^n + 1. Ex. 129, 257, 513 // "dx" > Cell spacing in the x dimension // "dz" > Cell spacing in the y dimension // "center" > Center of the plane // "verts" > Outputs the constructed vertices for the plane // "indices" > Outpus the constructed triangle indices for the plane int numVertices = numVertRows * numVertCols; int numCellRows = numVertRows - 1; int numCellCols = numVertCols - 1; int mNumTris = numCellRows * numCellCols * 2; float width = (float)numCellCols * dx; float depth = (float)numCellRows * dz; //=========================================== // Build vertices. // We first build the grid geometry centered about the origin and on // the xz-plane, row-by-row and in a top-down fashion. We then translate // the grid vertices so that they are centered about the specified // parameter 'center'. //verts.resize(numVertices); verts = new Vector3[numVertices]; // Offsets to translate grid from quadrant 4 to center of coordinate system. float xOffset = -width * 0.5f; float zOffset = depth * 0.5f; int k = 0; for (float i = 0; i < numVertRows; ++i) { for (float j = 0; j < numVertCols; ++j) { // Negate the depth coordinate to put in quadrant four. // Then offset to center about coordinate system. verts[k] = new Vector3(0, 0, 0); verts[k].X = j * dx + xOffset; verts[k].Z = -i * dz + zOffset; verts[k].Y = 0.0f; Matrix translation = Matrix.CreateTranslation(center); verts[k] = Vector3.Transform(verts[k], translation); ++k; // Next vertex } } //=========================================== // Build indices. //indices.resize(mNumTris * 3); indices = new int[mNumTris * 3]; // Generate indices for each quad k = 0; for (int i = 0; i < numCellRows; ++i) { for (int j = 0; j < numCellCols; ++j) { indices[k] = i * numVertCols + j; indices[k + 1] = i * numVertCols + j + 1; indices[k + 2] = (i + 1) * numVertCols + j; indices[k + 3] = (i + 1) * numVertCols + j; indices[k + 4] = i * numVertCols + j + 1; indices[k + 5] = (i + 1) * numVertCols + j + 1; // next quad k += 6; } } // Build List of triangles SimulationTriangle Face = new SimulationTriangle(); mTri = new List <SimulationTriangle>(); k = 0; for (int i = 0; i < numCellRows; ++i) { for (int j = 0; j < numCellCols; ++j) { Face.I0 = indices[k]; Face.I1 = indices[k + 1]; Face.I2 = indices[k + 2]; mTri.Add(Face); Face.I0 = indices[k + 3]; Face.I1 = indices[k + 4]; Face.I2 = indices[k + 5]; mTri.Add(Face); k += 6; } } }