Adding bodies

Prophet

07-09-2008 17:56:04

Hm, I think I'm getting the hang of this.
But, is it possible to add a Body to a scene, without using createBody? That way I don't need to worry about garbage collection (since I know NxOgre does that better than me).
Also, does NxScene::getActor return the actor of a created body with matching name? (Ie. getActor("box") returns the actor from createBody("box",...))

betajaen

07-09-2008 18:09:45

You can use a body factory class with '22, but otherwise no.

Yep. Bodies are Actors so the name thing works on them.

Prophet

07-09-2008 18:24:57

Do you mean the RenderableFactory as described here or something that I've missed? If it is the RenderableFactory, it still needs the same arguments for creating a body? I forgot to mention it, but the main reason (good thing to forget), is that it would be handy to have a function like Body* createBox () that returned a Body with all parameters set. As I see it, to do that, you would need to do some own bodies (which you would anyway), and then change the factor every time you need to create a specific shape.
I need this, as I need to know what to create depending on one string. I see a solution, but this would be better.

betajaen

07-09-2008 20:55:58

You could always do this:

GameManager::createBox(Vector3 size, NxOgre::Pose where)
{
return mScene->createBox("box;box.mesh", new Cube(size), where, "mass: 10");
}

Prophet

07-09-2008 21:19:28

Very true. Thanks!

Prophet

08-09-2008 20:37:05

To not flood the forum with my stupid questions;
as I see it (about inheriting Actor and RenderableSource to get a Body), the RenderableFactory can only take one type of body and the scene can only use one RenderableFactory, so you only use one (or a few) bodies? Or do you keep switching between RenderableFactories?
I guess when loading, you can switch RenderableFactory a few times, but not during gameplay?

betajaen

08-09-2008 21:43:06

No:

Actor inherits RenderableSource to be a Body (Body being a Generic term for an Actor that is shown on the screen). A Body uses a NodeRenderable which is created by the SceneRenderer (i.e. the OgreSceneRenderer)

The OgreSceneRenderer can implement many different types of NodeRenderables (i.e. OgreNodeRenderable, FadeyNodeRenderable, ShinyNodeRenderable, and so on) if it wanted to. Usually knowing what the Body intent is from "mIntent in NodeRenderableParams". But most of the time; it's easier just to use a single NodeRenderable and if you need something slightly different, then use the mIntent in NodeRenderableParams and/or a combination of materials.


It's all here (most of it anyway); http://www.nxogre.org/How_the_Rendersystem_works

Prophet

08-09-2008 22:08:35

Hm, I'll have to take a closer look at that tomorrow. I've read the "How the Rendersystem works", but since it's incomplete at best, I find it hard to get a grip on. Thanks, nevertheless!

mcaden

09-09-2008 06:16:54

I didn't realize how extensible things were until I saw this code snippet.

http://www.nxogre.org/Inheriting_Actor_ ... type_class

Prophet

10-09-2008 13:56:39

Ah, now I've read a bit more. So, you make one type of Body, but through visualParams you use different NodeRenderables, true?
So, if I'm using Ogre, I will create my own Body (by inheriting from Actor and RenderableSource), my own RenderableFactory and then use OgreNodeRenderable, but still one of each?

betajaen

10-09-2008 14:02:59

No, you can use OgreRenderer (which is a RenderableFactory - although there is no class name called that) if you want to and make use of the OgreNodeRenderable.

Prophet

10-09-2008 14:19:34

Oh, so all I need to do is create my own Body-class and set it to use that? That seems too simple, but NxOgre surprises me quite often.

Djoef

03-11-2008 12:54:57

Could someone give an example on how to make a body now in NxOgre 1.0.22T5 ?

It is still unclear to me.
Before we made a body like this :

NxOgre::Body *mBody = mNxScene->createBody("test",new NxOgre::Cube(2.0f),Ogre::Vector3(3,2,0),"mass : 10");

Now we need NodeRenderable Parameters,
if i Insert :
NxOgre::NodeRenderableParams *mNPar;
mNPar->setToDefault();

NxOgre::Body *mBody = mNxScene->createBody("myB",new NxOgre::Cube(2.0f),Ogre::Vector3(5,2,3),mNPar,"mass : 10");


I get :
error C2783: 'NxOgre::Actor *NxOgre::Scene::createBody(const NxOgre::NxString &,NxOgre::Shape *,const NxOgre::Pose &,const NxOgre::NodeRenderableParams &,const NxOgre::ActorParams &)' : could not deduce template argument for 'BodyClass'
1> c:\nxogre\include\NxOgreScene.h(439) : see declaration of 'NxOgre::Scene::createBody'


On the page :
http://www.nxogre.org/Inheriting_Actor_and_forcing_NxOgre_to_use_your_own_Body_type_class
I can see that I should make a "body class" that inherits from Actor and renderablesource. Still I do not understand where the mOwner comes from, and if I have to define a NxOgre::Renderable *mRenderable before it is used.

mRenderable = Owner->getSceneRenderer()->createNodeRenderable(visualParams);
mNodeRenderable = static_cast<NodeRenderable*>(mRenderable);
mVoidPointer->RenderPtr = this;


So I would appreciate if someone could post a simple example, where a mesh is loaded, shown on screen, and so ; has its node & entity & actor.

Also, how do we now make the actor have the shape of the mesh ?
before I did :
NxOgre::Body *myGroundBody = mNxScene->createBody("ground;level.mesh",new NxOgre::TriangleMeshShape("level.mesh"),Ogre::Vector3(0,1,0),"static: yes");


Now it seams to need an actual mesh and params.

I am aware that I should not use 1.0.22T5 as it is not really released yet, still I need the new raycasting method, which Betajean was refering to in other posts.

Thank you for helping me out here.
geoffrey.

mcaden

03-11-2008 13:05:32


NxOgre::Body *mBody = mNxScene->createBody<Body>("test",new NxOgre::Cube(2.0f),Ogre::Vector3(3,2,0),"mass : 10");


That should create a new body using the default body class. Notice the added "<Body>" because it's now using a class template system.

Djoef

03-11-2008 13:26:01

Hi,
Thanks for the quick response !

when inserting your code I have :
error C2065: 'Body' : undeclared identifier
I suppose this is because I am not using namespace NxOgre,
So I tried :
NxOgre::Body *mBody = mNxScene->createBody<NxOgre::Body>("test",new NxOgre::Cube(2.0f),Ogre::Vector3(3,2,0),"mass : 10");

but then I get ;
error C2440: 'initializing' : cannot convert from 'NxOgre::Actor *' to 'NxOgre::Body *'
1> Cast from base to derived requires dynamic_cast or static_cast'


What should I use as template ?

And what about the TriangleMesh shape question ?

Thank you !

geoffrey.

mcaden

03-11-2008 14:04:29

Oh, createBody returns an Actor* until you make your own class.

Djoef

03-11-2008 14:08:59

So the new class would be the template? (what is between the brackets e.g. <Body> = i need to make a class Body)
Can you give a simple example of what this class would look like if you would just want to render a mesh that has its actor ?

thank you,
geoffrey.

mcaden

03-11-2008 14:22:19

Oops! I forgot, you have to typecast it.

NxOgre::Body *mBody = (Body*)mNxScene->createBody<NxOgre::Body>("test",new NxOgre::Cube(2.0f),Ogre::Vector3(3,2,0),"mass : 10");

Djoef

03-11-2008 17:39:51

The question remains, how would the Body class look like ?
Can you give an example for a basic visualization of the actor as the entity.
(The way it worked in older versions)

Second question also remains, what about Trianglemesh instead of e.g. cube shape. How can you now make the actor have the shape of the mesh.

Thank you
Geoffrey.

mcaden

03-11-2008 23:21:30

  1. http://www.nxogre.org/Inheriting_Actor_and_forcing_NxOgre_to_use_your_own_Body_type_class - specifically the T2 section at the bottom. There's a couple typos and you need to add a second constructor to TestActor but you should be able to figure it out if you know anything about C++. If you try and still can't get it I posted a explanation in the T2 thread about it which should help. - http://www.ogre3d.org/phpBB2addons/viewtopic.php?t=8306 - my post 2nd from the bottom.[/*:m]
  2. After making a .nxs mesh using flour you'd use something like the following code:
    Shape* collisionShape = NULL;
    NxOgre::Resources::ResourceSystem::getSingleton()->addMeshAs("file://../../media/models/myMesh.nxs", "myMesh.nxs");
    collisionShape = new TriangleMesh(NxOgre::Resources::ResourceSystem::getSingleton()->getMesh( "myMesh.nxs"));
    TestActor* myActor = (TestActor*)mScene->createBody<TestActor>(renderParams.mIdentifier,
    collisionShape, actorPose, renderParams, actorParams);
    [/*:m][/list:o]

Djoef

04-11-2008 09:39:02

Hi,
Thank you for the response.

I know the page :
http://www.nxogre.org/Inheriting_Actor_and_forcing_NxOgre_to_use_your_own_Body_type_class

As explained in my pervious post, I did not understand where the mOwner comes from in the TestActor class. Is the declaration of mOwner missing, what is mOwner supposed to be ? Just as e.g. mRenderable, should I declare that ? (NxOgre::Renderable *mRenderable) Or do those things come from somewhere else ?

I understand it is quite simple for you, but for me it still seems unclear. Is it possible to give an example without typo's, and with necessary declarations included (if there were any missing off course)? I believe it would be helpfull for other NxOgre users too, to have a well explained basic example.

Thank you for your help!

geoffrey.

mcaden

04-11-2008 15:00:55

mOwner is a member variable within the actor class (which you should be inheriting from, therefore you have access to it).

Djoef

05-11-2008 16:30:18

Hi,

Before all, thank you for the response.
I copied the classes from the NxOgre site and your post.
I made a header file and cpp file for each and called the classes MyActor and MyFactory.

When I now want to make a renderable actor I use :

NxOgre::Body *mBody = (NxOgre::Body *)mNxScene->createBody<MyActor>("test",new NxOgre::Cube(2.0f),Ogre::Vector3(3,2,0),"mass : 10");

This does not give compilation errors, but does not work at runtime.
I think I should use the MyFactory class as template, and that I should register this class somewhere, but I don't know exactly what to do.

I tried to register the factory class as explained on : http://www.ogre3d.org/phpBB2addons/viewtopic.php?t=8306
mNxScene->registerRenderableActorFactory(MyActor::FactoryIdentifier,new MyFactory(),true);

1>.\BaseApp.cpp(266) : error C2259: 'MyFactory' : cannot instantiate abstract class
1> due to following members:
1> 'NxOgre::Actor *NxOgre::RenderableActorFactory::createRendereredActor(NxOgre::Scene *,const NxOgre::VisualIdentifier &,const NxOgre::ActorParams &,const NxOgre::Pose &,NxOgre::Shape *,unsigned int)' : is abstract
1> c:\nxogre\include\NxOgreRenderableActorFactory.h(37) : see declaration of 'NxOgre::RenderableActorFactory::createRendereredActor'


Can anyone tell me if there is a mistake in the classes, and if not, how I should now create an actor with visualisation ?

Thank you,
g


MyActor.h
=======
#ifndef MYACTOR_H
#define MYACTOR_H

#include "NxOgre.h"

class MyActor : public NxOgre::Actor, public NxOgre::RenderableSource {

public:
MyActor(const NxOgre::NxString& name,
const NxOgre::Pose& pose,
NxOgre::Shape* shape,
NxOgre::Scene* scene,
const NxOgre::NodeRenderableParams& visualParams,
const NxOgre::ActorParams& params);

// Destructor. Clean anything you have custom in here.
~MyActor() ;

// Required by the RenderableSource. (Tells where the Actor is)
NxOgre::Pose getSourcePose(const NxOgre::TimeStep&) const ;

// To work out what exactly the class is, if the pointer is passed
// around as an Actor.
NxOgre::NxShortHashIdentifier getType() const ;

// Same as above, but uses a String. It is slower to check this way.
NxOgre::NxString getStringType() const ;

// Just providing a courtesy function.
Ogre::SceneNode* getNode() ;

enum { FactoryIdentifier = 1337 }; // Unique identifier for RenderableActorFactory.

protected:
NxOgre::NodeRenderable* mNodeRenderable;
NxOgre::OgreNodeRenderable* mOgreNodeRenderable;
};
#endif /* MYACTOR_H */



MyActor.cpp
========
#include "MyActor.h"

MyActor::MyActor(const NxOgre::NxString& name, const NxOgre::Pose& pose,
NxOgre::Shape* shape, NxOgre::Scene* scene,
const NxOgre::NodeRenderableParams& visualParams,
const NxOgre::ActorParams& params)
: Actor(name, scene, shape, pose, params)
{
// Create the NodeRenderable based of the Params. The outcome is
// based on the Renderer used (specified in the Scene)

mRenderable = mOwner->getSceneRenderer()->createNodeRenderable(visualParams);
mNodeRenderable = static_cast<NxOgre::NodeRenderable*>(mRenderable);
mVoidPointer->RenderPtr = this;

// Set the Render mode to Interpolate. (Interpolation is handled
// somewhere else, and is out of the scope of the TestActor).
setRenderMode(RM_Interpolate);
// You can use the NodeRenderable functions to mirror most or if
// not all of the actual RenderSystem's NodeRenderable functions
// but in some instances you can't. But you can cast it into another,
// if you have to.

if (mNodeRenderable->getHashType() == NxOgre::NxOgreClass_OgreNodeRenderable)
{
mOgreNodeRenderable = static_cast<NxOgre::OgreNodeRenderable*>(mNodeRenderable);
}
// Tell the Scene to render this Actor, every simulation.
mOwner->getSceneRenderer()->registerSource(this);
// Usually at this point, it may be best to use any NxOgre classes that
// require you to watch collisions, join
// to other actors, or anything else.
}

// Destructor. Clean anything you have custom in here.
MyActor::~MyActor()
{
mOwner->getSceneRenderer()->unregisterSource(this);
if (mRenderable)
{
delete mRenderable;
mRenderable = 0;
}
}

// Required by the RenderableSource. (Tells where the Actor is)
NxOgre::Pose MyActor::getSourcePose(const NxOgre::TimeStep&) const
{
return getGlobalPose();
}

// To work out what exactly the class is, if the pointer is passed
// around as an Actor.
NxOgre::NxShortHashIdentifier MyActor::getType() const
{
return 12345;
}

// Same as above, but uses a String. It is slower to check this way.
NxOgre::NxString MyActor::getStringType() const
{
return "TestActor";
}

// Just providing a courtesy function.
Ogre::SceneNode* MyActor::getNode()
{
return mOgreNodeRenderable->getNode();
}


MyFactory.h
========
#ifndef MYFACTORY_H
#define MYFACTORY_H

#include "NxOgre.h"
#include "MyActor.h"

class MyFactory : public NxOgre::RenderableActorFactory
{
public:
~MyFactory();

// For Bodies that use the VisualIdentifier (body;body.mesh).
NxOgre::Actor* createRendereredActor(
NxOgre::Scene* scene, const NxOgre::VisualIdentifier& vi,
const NxOgre::ActorParams& a_params, const NxOgre::Pose& pose,
NxOgre::Shape* shape, unsigned int FactoryIdentifier
);

// For Bodies that use the NodeRenderableParams.
NxOgre::Actor* createRendereredActor(
NxOgre::Scene* scene, const NxOgre::NxString& identifier,
const NxOgre::ActorParams& a_params, const NxOgre::NodeRenderableParams& nr_params,
const NxOgre::Pose& pose, NxOgre::Shape* shape,
unsigned int FactoryIdentifier
);
Betajaen::SharedList<MyActor> mTestActors;
};
#endif /* MYFACTORY_H */


MyFactory.cpp
=========
#include "MyFactory.h"

MyFactory::~MyFactory()
{}

//// For Bodies that use the VisualIdentifier (body;body.mesh).
//NxOgre::Actor *MyFactory::createRendereredActor(
// Scene* scene, const VisualIdentifier& vi,
// const ActorParams& a_params, const NxOgre::Pose& pose,
// Shape* shape, unsigned int FactoryIdentifier
// )
//{
// // Using the FactoryIdentifier as a point of reference, this class can be registered
// // multiple times as a RenderableActorFactory, without the need for one factory for one body.
// if (FactoryIdentifier == MyActor::FactoryIdentifier)
// {
// MyActor *actor = new MyActor( TestActor(vi, pose, shape, scene, ar_params); //<<Correction: I swapped "pose" and "scene"
// // We manage the pointers for inherited Actors. So the SharedList which
// // uses garbage collection is a nice container to use.
// mTestActors.Insert(actor);
// return actor; //<<Correction: Add this
// }
// return NULL; // Whoops, somebody registered this Factory with the wrong FactoryIdentifier.
//}

// For Bodies that use the NodeRenderableParams.
NxOgre::Actor* MyFactory::createRendereredActor(
NxOgre::Scene* scene, const NxOgre::NxString& identifier,
const NxOgre::ActorParams& a_params, const NxOgre::NodeRenderableParams& nr_params,
const NxOgre::Pose& pose, NxOgre::Shape* shape,
unsigned int FactoryIdentifier)
{
// Again the FactoryIdentifier as a point of reference, we can work with many
// different types of inherited Actors with one class.
if (FactoryIdentifier == MyActor::FactoryIdentifier)
{
MyActor* actor = new MyActor(identifier, pose, shape, scene, nr_params, a_params); //<<Correction: I swapped "pose" and "scene"
// We manage the pointers for inherited Actors. So the SharedList which
// uses garbage collection is a nice container to use.
mTestActors.Insert(actor);

return actor; //<<Correction: Add this
}
return NULL;
}


That's it, Thanks again !

Djoef

07-11-2008 17:26:05

Anyone out there has an idea how to solve the problem described above ?

thank you!
g

mcaden

08-11-2008 01:50:27

your class needs a second constructor because there are 2 ways to create an actor. Something along the lines of:


MyActor::MyActor(const VisualIdentifier& vi, const NxOgre::Pose& pose, Shape* shape, Scene* scene,
const ActorParams& params) :
Actor(vi.getIdentifier(), scene, shape, pose, params)
{
NodeRenderableParams renderParams;
renderParams.setToDefault();
renderParams.mGraphicsModel = vi.getVisualIdentifier();
renderParams.mGraphicsModelScale = NxVec3(1, 1, 1);
renderParams.mIdentifier = vi.getIdentifier();
renderParams.mIdentifierUsage = renderParams.IU_Use;
renderParams.mMode = RenderableSource::RM_Interpolate;

mRenderable = mOwner->getSceneRenderer()->createNodeRenderable( renderParams );
mNodeRenderable = static_cast<NodeRenderable*>(mRenderable);
mVoidPointer->RenderPtr = this;

if (mNodeRenderable->getHashType() == NxOgreClass_OgreNodeRenderable)
mOgreNodeRenderable = static_cast<OgreNodeRenderable*>(mNodeRenderable);

mOwner->getSceneRenderer()->registerSource(this);
}

buckEd

08-11-2008 11:27:22

Oops! I forgot, you have to typecast it.

NxOgre::Body *mBody = (Body*)mNxScene->createBody<NxOgre::Body>("test",new NxOgre::Cube(2.0f),Ogre::Vector3(3,2,0),"mass : 10");


Hi.
Sorry for hijacking, but as I am having a similar problem I thought I would just ask in here rather than create yet another thread of that kind.

When I do the above thing I get an error:
""type-conversion: 'overloaded function! cannot be converted into "NxOgre::Body" "

I am using NxOgre 1.0 '21

[EDIT]
Guess the above code is for '22? That might explain why it doesn't work :)
However there's another thing. I copied a line directly out of cake:
mScene->createBody("Boo; cube.1m.mesh", new Cube(1), Vector3(10, 0.5f + i, 10), ActorParams("Mass: 10"));
This compiles well but when I run it it crashes and gives me an unhandeled exception error and points me at a sourcefile called xsstring.
Has anyone had that same problem before and knows what's wrong? because it happens all the time, whenever I try to create an Actor/Body[/EDIT]

mcaden

08-11-2008 15:11:32

  1. yup, '22[/*:m]
  2. I'm not sure about xsstring but...
    1. do you have cube.1m.mesh where Ogre can find it?[/*:m]
    2. I'm assuming i is an int, float, Real, or something similar?[/*:m][/list:o][/*:m][/list:o]

      Haven't run into the xsstring prob before, hope this helps though