BloodyMess Tutorial 4

From Ogre Wiki

Jump to: navigation, search
Image:NxOgreCube.pngThis page is related to the newest version of NxOgre, called BloodyMessImage:NxOgreCube.png

Disclaimer: This is not an official NxOgre tutorial. However, it has been revised and edited by the creator of NxOgre and BloodyMess, betajaen.

Image:Forum icon question2.gif Help: For any problems you encounter while working on these tutorials, as well as for detailed questions and propositions, please visit the NxOgre OgreAddons-Forum.


Contents


You can find the complete code for this tutorial here.

Image:NxOgreCube.png Introduction

In the third tutorial, you learned about the Visual Debugger, a tool that can visually show all physics objects in a scene, even those that are invisible. In this tutorial we will get to know one kind of these invisible element: Volumes/Trigger. Once you have completed this tutorial it would be a good idea to go back and integrate the visual debugger so that you can see this object within our scene.

Image:NxOgreCube.png What is a Volume?

A volume is an invisible physics object of an arbitrary shape. It doesn't move, nor can it be seen. So what is the value of it? It is used as a trigger. As soon as a physics object enters it, is fully within it, or leaves it, a special event is fired that can be used to start a defined action within your program.

One example for a trigger could be the finish area in a racing game. From the finish line up to a distance beyond it, a trigger volume is placed and as soon as the player enters this volume, an event is fired and the game can, for example, react by showing a message, playing a sound or doing whatever the programmer wanted it to do.

Image:NxOgreCube.png The Initial Code

Start a new Ogre and NxOgre project in your IDE. We will create the necessary code to make Ogre run using the ExampleApplication and ExampleFrameListener classes provided by the Ogre Samples.

Note: If you're fairly new with Ogre, it may be worth it modifying the Ogre SkyBox sample instead of creating your own Ogre project.

The following code will serve as the basis for this tutorial. It should compile and run without errors.

#include "ExampleApplication.h"

#include <NxOgre.h>
#include <NxOgreOGRE3D.h>

class BloodyMessTutorial4Listener : public ExampleFrameListener
{ 
public:
	BloodyMessTutorial4Listener(RenderWindow *win, Camera *cam) 
		: ExampleFrameListener(win, cam)
	{
		mTimeController = NxOgre::TimeController::getSingleton();
	}

	bool frameStarted(const FrameEvent& evt)
	{
		mTimeController->advance(evt.timeSinceLastFrame);
		return ExampleFrameListener::frameStarted(evt);
	}

protected:
	NxOgre::TimeController* mTimeController;
};

class BloodyMessTutorial4 : public ExampleApplication
{
protected:
	NxOgre::World*			mWorld;
	NxOgre::Scene*			mScene;
	NxOgre::TimeController*		mTimeController;
	OGRE3DRenderSystem*		mRenderSystem;

	OGRE3DBody*			mCube;
	
	void createScene()
	{
		// Set ambient light
		mSceneMgr->setAmbientLight(ColourValue(0.5f, 0.5f, 0.5f));

		// Create a light
		Light* l = mSceneMgr->createLight("MainLight");
		l->setPosition(20, 80, 50);

		// Position the camera
		mCamera->setPosition(0, 20, 80);
		mCamera->lookAt(0, 20, 0);

		// Create the world
		mWorld = NxOgre::World::createWorld();

		// Create scene description
		NxOgre::SceneDescription sceneDesc;
		sceneDesc.mGravity = NxOgre::Vec3(0, -9.81f, 0);
		sceneDesc.mName = "DemoScene";

		// Create scene
		mScene = mWorld->createScene(sceneDesc);

		// Set some physical scene values
		mScene->getMaterial(0)->setStaticFriction(0.5);
		mScene->getMaterial(0)->setDynamicFriction(0.5);
		mScene->getMaterial(0)->setRestitution(0.1);

		// Create render system
		mRenderSystem = new OGRE3DRenderSystem(mScene);

		//Create time controller
		mTimeController = NxOgre::TimeController::getSingleton();

		// Add objects
		mCube = mRenderSystem->createBody(new NxOgre::Box(1, 1, 1), NxOgre::Vec3(0, 40, 0), "cube.1m.mesh");

		// Create floor plane (Ogre)
		MovablePlane *plane = new MovablePlane("Plane");
		plane->d = 0;
		plane->normal = Vector3::UNIT_Y;
		Ogre::MeshManager::getSingleton().createPlane("PlaneMesh", 
			ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
			*plane, 120, 120, 1, 1, true, 1, 3, 3, Vector3::UNIT_Z);
		Entity *planeEnt = mSceneMgr->createEntity("PlaneEntity", "PlaneMesh");
		planeEnt->setMaterialName("Examples/GrassFloor");

		Ogre::SceneNode* mPlaneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
		mPlaneNode->attachObject(planeEnt);
	}

	// Create a new frame listener
	void createFrameListener()
	{
		mFrameListener = new BloodyMessTutorial4Listener(mWindow, mCamera);
		mRoot->addFrameListener(mFrameListener);
	}
};

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
	INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT)
#else
	int main(int argc, char **argv)
#endif
	{
		// Create application object
		BloodyMessTutorial4 app;

		try {
			app.go();
		} catch(Exception& e) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
			MessageBoxA(NULL, e.getFullDescription().c_str(),
				"An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
			std::cerr << "An exception has occurred: " << e.getFullDescription();
#endif
		}

		return 0;
	}

#ifdef __cplusplus
}
#endif

Image:NxOgreCube.png Initialize the Volume

First of all, we need to make two changes to our tutorial class. We have to declare a new member variable:

NxOgre::Volume* mVolume;

We also have to make our tutorial class inherit NxOgre::Callback in order for it to be able to deal with the events that a volume will fire when, in this case, an NxOgre::Actor enters.

As such, ensure that our class declaration looks like this:

class BloodyMessTutorial4 : public ExampleApplication, public NxOgre::Callback

Next, at the bottom of our createScene() function, we need to create a volume that has these parameters:

  • the shape of the volume, in this case a 5x5x5 metre box
  • the position of the volume, which is the center of our scene
  • the callback class for the volume, which is this class which we previously had inherit from NxOgre::Callback
  • the callback behavior (for which events the onVolumeEvent() should be called), which will react to an Actor entering, existing within, or exiting the volume
mVolume = mScene->createVolume(new NxOgre::Box(5), NxOgre::Matrix44(NxOgre::Vec3(0, 0, 0)),
                                     this, NxOgre::Enums::VolumeCollisionType_All);

Image:NxOgreCube.png The Callback Function

The final thing we have to do is create the function which will be called when an Actor triggers our callback. Place this function at the bottom of our tutorial class:

void onVolumeEvent(NxOgre::Volume* volume, NxOgre::Shape* volumeShape, NxOgre::RigidBody* rigidBody,
                            NxOgre::Shape* rigidBodyShape, unsigned int collisionEvent)
{
	if(collisionEvent == NxOgre::Enums::VolumeCollisionType_OnEnter)
	{
		NxOgre::Actor* actor = static_cast<NxOgre::Actor*>(rigidBody);
		float y =   (9.81 * actor->getMass())				  // counteract gravity
			+ (-actor->getLinearVelocity().y * actor->getMass())      // counteract vertical velocity
			+ (10 - actor->getGlobalPosition().y * actor->getMass()); // add some force to move it to the top

		actor->addForce(NxOgre::Vec3(0, y, 0), NxOgre::Enums::ForceMode_Impulse); 
	}
}

This bit of code checks what type of collisionEvent occurred, which in this case we only want when an actor enters our volume. We then apply a force to our actor which will send it flying back up vertically along the Y axis.

Image:NxOgreCube.png Conclusion

That's it! When you run the application now, you should see our cube falling straight down till it reaches our volume where it will then reverse direction and go flying back in to the air until gravity begins to pull it back down once more, so on and so fourth. Onward, for in the next tutorial we will cover Kinematics!

image:NxOgreLogoTemplateBox.png

Official Wiki and Website - Forum - Ogre Portal for NxOgre
Betajaen's Guide to creating a Bloody mess


Code snippetsbloody mess
General - Particles - Mesh Cooking - Cloths

Spacegaier's Tutorialsbloody mess
Setting up BloodyMess - First steps - Visual Debugger - Volumes & Triggers - Kinematics - Raycasting - Resources and Meshes
Terrain / Heigthfields - Joints - Cloth

Personal tools
administration