gr_tut26_screenshot.jpg

BuoyancyAndDestroying.cs

#region Using directives

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

using Microsoft.DirectX;
using Microsoft.DirectX.DirectSound;
using Microsoft.DirectX.Direct3D;

using JadEngine;
using JadEngine.Video;
using JadEngine.Core;
using JadEngine.Mathematics;
using JadEngine.Scene;
using JadEngine.Scene.MD5;
using JadEngine.Physics;
using JadEngine.Particles;
using JadEngine.Sound;
using JadEngine.Tools;
using JadEngine.Input;

#endregion

namespace Tutorial
{
	/// <sumary>
	/// This example will teach you to change Buoyancy properties, so an object takes
	/// more time to emerge than another. You will learn also how to destroy a RigidBody.
	/// </sumary>
	public class BuoyancyAndDestroying : JApplication
	{
		#region Fields

		/// <summary>
		/// Indicates if the help must be shown in the screen or not
		/// </summary>
		bool showHelp = true;

		/// <summary>
		/// Starting position of the spheres
		/// </summary>
		Vector3 startPosition = new Vector3(0, 5, 5);

		/// <summary>
		/// TODO
		/// </summary>
		int sphereCount = 0;

		/// <summary>
		/// Spheres
		/// </summary>
		JMeshObject[] sphere = new JMeshObject[2];

		/// <summary>
		/// Rigid body for the spheres
		/// </summary>
		JRigidBody body;

		/// <summary>
		/// Plane of the water
		/// </summary>
		Vector4 waterPlane;

		/// <summary>
		/// The water
		/// </summary>
		JMeshObject water;

		/// <summary>
		/// TODO
		/// </summary>
		float[] cubeVertices = new float[] {
			-0.5f, 0, -0.5f,1,1,
			0.5f,0,0.5f,0,0,
			-0.5f,0,0.5f,1,0,
			0.5f,0,-0.5f,0,1,
			-0.5f,1,-0.5f,0,1,
			0.5f,1,0.5f,1,0,
			0.5f,1,-0.5f,1,1,
			-0.5f,1,0.5f,0,0,
			-0.5f,0,-0.5f,0,1,
			0.5f,1,-0.5f,1,0,
			0.5f,0,-0.5f,1,1,
			-0.5f,1,-0.5f,0,0,
			0.5f,0,-0.5f,0,1,
			0.5f,1,0.5f,1,0,
			0.5f,0,0.5f,1,1,
			0.5f,1,-0.5f,0,0,
			0.5f,0,0.5f,0,1,
			-0.5f,1,0.5f,1,0,
			-0.5f,0,0.5f,1,1,
			0.5f,1,0.5f,0,0,
			-0.5f,0,0.5f,0,1,
			-0.5f,1,-0.5f,1,0,
			-0.5f,0,-0.5f,1,1,
			-0.5f,1,0.5f,0,0 };

		/// <summary>
		/// TODO
		/// </summary>
		int[] cubeFaces = new int[] {
			0,1,2,
			1,0,3,
			//4,5,6,
			//5,4,7,
			8,9,10,
			9,8,11,
			12,13,14,
			13,12,15,
			16,17,18,
			17,16,19,
			20,21,22,
			21,20,23 };

		#endregion

		#region Methods

		/// <summary>
		/// The engine calls this method after creating the device
		/// </summary>
		/// <param name="form">Form used as window</param>
		/// <returns>True if everything went right</returns>
		public override bool InitGame(Form form)
		{
			// Create the fonts and texture objects
			Jad.AfterCreateDevice();

			// Load default textures, scenes, shaders,...
			Jad.LoadCreateInHouse();

			// Activate Newton's physics system
			Jad.Physics.Create();

			// Create the water and the water container
			CreateWaterPlane();

			// Create 2 spheres, with diferent mass and different densities
			CreateSphere(30, JColor.White, 1);
			CreateSphere(3000, JColor.RedColor, 1 / 5f);

			// Put ambient light
			Jad.Scene.Lights.Ambient = new JColor(1f);

			// Set the camera
			Jad.Scene.Camera.Transform.Position = new Vector3(0, 3, 0);
			Jad.Scene.Camera.Transform.Angles = new Vector3(Geometry.DegreeToRadian(20), 0, 0);

			// We need a far plane
			Jad.Scene.Camera.FarPlane = 250.0f;

			// When working with physics the best is set a fixed time
			Jad.Timer.FixedMode = true;
			Jad.Timer.FixedModeFPS = 1.0f / 60.0f;	// 60 fps

			// Set our skybox
			Jad.Scene.SkyBox = new JSkyBox("water_skybox");

			// We need render the skybox first because of transparency
			Jad.Scene.RenderSkyBoxFirst = true;

			// Everything is set, start the engine
			Jad.Begin();

			// Create input class to manage the keyboard and the mouse
			Jad.CreateInput();

			return true;
		}

		/// <summary>
		/// Creates a sphere
		/// </summary>
		/// <param name="mass">Mass of the sphere</param>
		/// <param name="color">Color of the sphere</param>
		/// <param name="fluidDensity">Fluid density of the sphere</param>
		void CreateSphere(float mass, JColor color, float fluidDensity)
		{
			float radius = 0.5f;

			JMesh mesh = JMesh.CreateSphere(radius, 20, 20);

			JMeshObject meshObject = Jad.Scene.MeshObjects.Create("sphere", false);

			sphere[sphereCount++] = meshObject;

			meshObject.Mesh = mesh;

			// Create a materials array of 1 element
			JMaterial[] material = new JMaterial[1];

			material[0] = Jad.Scene.Materials.Create();

			// Create the layer
			JMaterialLayer layer = new JMaterialLayer();

			// Add it to the material
			material[0].AddLayer(layer);

			layer.DiffuseMap.Texture = Jad.Video.Textures.Create2D("wood", true);

			layer.DiffuseMap.Color = color;

			// Set the material we have just created to our ground
			meshObject.Material = material;

			// Create a collision object

			JCollision collision = new JCollision();

			collision.CreateSphere(radius, radius, radius);

			// The inertia values are very important for realistic physics.
			// Newton can compute now the inertia values for you.
			// If you do not compute inertia, the engine use the default
			// values of 1,1,1

			collision.ComputeInertia();

			collision.CalculateVolume();

			body = Jad.Physics.RigidBodies.Create(collision, meshObject);

			body.Mass = mass;

			Matrix matrix = Matrix.Translation(startPosition);

			body.Matrix = matrix;

			// Prepare the position for the next sphere
			startPosition.Z += 3f;

			// Set the fluid density for this body.
			body.Buoyancy.FluidDensity = fluidDensity;

			collision.Release();
		}

		/// <summary>
		/// TODO
		/// </summary>
		/// <param name="width">TODO</param>
		/// <param name="height">TODO</param>
		/// <param name="depth">TODO</param>
		/// <param name="tu">TODO</param>
		/// <param name="tv">TODO</param>
		/// <returns>TODO</returns>
		JMesh CreateContainer(float width, float height, float depth, float tu, float tv)
		{
			Mesh temp = new Mesh(cubeFaces.Length / 3, 24, MeshFlags.Managed, CustomVertex.PositionTextured.Format, Jad.Video.Device);

			JMesh mesh = Jad.Video.Meshes.Create();

			mesh.VertexBuffer = new JVertexBuffer(24);

			mesh.VertexBuffer.Position = new Vector3[24];
			mesh.VertexBuffer.TexCoord = new Vector2[1, 24];

			// Copy the source array

			float[] vertices = new float[cubeVertices.Length];

			cubeVertices.CopyTo(vertices, 0);

			for (int i = 0, c = 0; i < cubeVertices.Length; i += 5, c++)
			{
				mesh.VertexBuffer.Position[c].X = vertices[i] * width;
				mesh.VertexBuffer.Position[c].Y = vertices[i + 1] * height;
				mesh.VertexBuffer.Position[c].Z = vertices[i + 2] * depth;
				mesh.VertexBuffer.TexCoord[0, c].X = vertices[i + 3] * tu;
				mesh.VertexBuffer.TexCoord[0, c].Y = vertices[i + 4] * tu;
			}

			// Create a 16 bits IndexBuffer
			mesh.IndexBuffer = new JIndexBuffer(false, cubeFaces.Length);

			// Even if we have created a 16 bits indexBuffer, we always specify the indexes in 32 bits. The engine manages everything internally

			cubeFaces.CopyTo(mesh.IndexBuffer.Indices, 0);

			// We want to invert the faces

			mesh.IndexBuffer.InvertFaces();

			return mesh;
		}

		/// <summary>
		/// TODO
		/// </summary>
		void CreateWaterContainer()
		{
			float height = 30f;

			JMesh groundMesh = CreateContainer(water.Mesh.BoundingBox.Width, height, water.Mesh.BoundingBox.Depth, 20f, 20f);

			JMeshObject ground = Jad.Scene.MeshObjects.Create("container", false);

			ground.Transform.Position = water.Transform.Position - new Vector3(0, height / 2, 0);

			ground.AffectLight = false;

			// Now associate the mesh with the meshobject

			ground.Mesh = groundMesh;

			// Create a materials array of 1 element
			JMaterial[] material = new JMaterial[1];

			material[0] = Jad.Scene.Materials.Create();

			// Create the layer
			JMaterialLayer layer = new JMaterialLayer();

			// Add it to the material
			material[0].AddLayer(layer);

			layer.DiffuseMap.Texture = Jad.Video.Textures.Create2D("cement_stucco_d", true);

			layer.DiffuseMap.Color = new JColor(1f);

			// Set the material we have just created to our ground
			ground.Material = material;
		}

		/// <summary>
		/// TODO
		/// </summary>
		void CreateWaterPlane()
		{
			// Create a rectangle to use as a floor

			float depth = 30f;

			// IMPORTANT
			// Newton sets by default +-100 m of World Size.
			// when you build a TreeCollision, Jad adjusts the world size.
			// But here we are creating a very very big plane , so we must
			// change the world size

			Jad.Physics.SetWorldSize(new Vector3(-1000, -1000, -1000), new Vector3(1000, 1000, 1000));

			JMesh mesh = JMesh.CreateRectangle(depth, depth, 100, 100, JCreateRectangle.XZ, false, 10f, 10f);

			water = Jad.Scene.MeshObjects.Create("water", false);

			// Now associate the mesh with the meshobject

			water.Mesh = mesh;

			// Create the material

			water.Material = new JMaterial[1];

			// Load the material
			water.Material[0] = Jad.Scene.Materials.Load("calm_water.material");

			// Modify the wave params( see the calm_water.material file)

			water.Material[0].ShaderParams.SetVector("wave_WaveParams", new Vector4(0, 0.05f, 0, 0.3f));

			water.Transform.Position = new Vector3(0, 0, 0);

			// Now we need to create the absoluteTM

			water.TransformDown();

			waterPlane = new Vector4(0, 1, 0, water.Transform.Position.Y);

			JPhysics.BuoyancyPlane = waterPlane;

			CreateWaterContainer();
		}

		/// <summary>
		/// Releases the objects
		/// </summary>
		public override void End()
		{
		}

		/// <summary>
		/// Enables / Disables the buoyancy 
		/// </summary>
		void ComputeBuoyancy()
		{
			for (int i = 0; i < sphereCount; i++)
			{
				JMeshObject meshObject = sphere[i];

				JRigidBody body = meshObject.Physics.RigidBody;

				// If the body is null then the object has been destroyed

				if (body != null)
				{
					if (meshObject.Transform.Position.Y <= waterPlane.W)
					{
						body.Buoyancy.Enabled = true;

						// Controlled by the application
						body.AutoFreeze = false;
					}

					else
					{
						body.Buoyancy.Enabled = false;

						// Controlled by Newton
						body.AutoFreeze = true;
					}
				}
			}
		}

		/// <summary>
		/// This method is called every frame and it´s where the input
		/// events and the game action must be placed
		/// </summary>
		/// <returns>True to continue, false to exit the application</returns>
		public override bool Update()
		{
			// Exit the app?
			if (Jad.Input.Keyboard[Key.Escape].Down) return false;

			if (Jad.Input.Keyboard[Key.F1].Pressed) showHelp = !showHelp;

			// If G key was pressed we activate / deactivate the gizmos
			// The diference between KeyTouch and KeyPressed is that KeyTouch only returns
			// true if the key was pressed for the first time and not when it´s down as in
			// KeyPressed

			// KeyTouch is like normal writting, returning true only once for every key press

			if (Jad.Input.Keyboard[Key.G].Pressed)
				Jad.Scene.ShowGizmos = !Jad.Scene.ShowGizmos;

			// If they P key was pressed you can see / hide Newton collision objects
			if (Jad.Input.Keyboard[Key.P].Pressed)
				Jad.Physics.Debug = !Jad.Physics.Debug;

			if (Jad.Input.Keyboard[Key.K].Pressed)
			{
				// Destroy the body, but not the JMeshObject
				// if you want the JMeshObject disappear, then set:
				// sphere[0].Hide=true;
				Jad.Physics.RigidBodies.Destroy(sphere[0].Physics.RigidBody);
			}

			ComputeBuoyancy();

			// Everything was right, continue
			return true;
		}

		/// <summary>
		/// Render method
		/// </summary>
		public override void Render()
		{
			JView backbuffer = Jad.Video.Views[0];

			// Render the Jad.Scene using the scene camera
			backbuffer.Render();

			if (showHelp)
			{
				// Get access to the 1st font. The engine creates a font by default
				JFont font = Jad.Video.Fonts[0];

				// Start fonts rendering
				Jad.Video.Fonts.Begin();

				// Write text in the first line, position x=0, yellow color
				font.RenderLine(Jad.Version + ". Press ESC to exit. Press G to Show/Hide Gizmos. F1 show/hide text", 0, JColor.Yellow);

				font.RenderLine("Press K to destroy the first sphere rigid body.", 0, JColor.Yellow);

				// End fonts rendering
				Jad.Video.Fonts.End();
			}

			// Show the backbuffer
			backbuffer.Present();
		}

		#endregion
	}
}

Last edited Mar 8, 2007 at 7:38 PM by Vicente, version 5

Comments

No comments yet.