Inherit from CollisionNode

Return to C++ coding using Panda3D

Inherit from CollisionNode

Postby tomallevi » Fri Jan 27, 2012 12:56 pm

Hi!
for building a game, I think to create a class inherited by CollisionNode to manage the units' informations. Than I attach a Model to my CollisionNode.
Code: Select all
class MyObject : public CollisionNode {
    // ...
    UnitInformation* info;
public:
    MyObject(string str) : CollisionNode(str) {
    //...
    }
    UnitInformation* get_info() {
        return info;
    }
};

//...
MyObject myObject;
myObject.add_solid(new CollisionSphere(0, 0, 0, 1));
NodePath node(myObject);
model.reparentTo(node);

is this the right technique to structure a large game?

thanks for all!!
tomallevi
 
Posts: 99
Joined: Sat Sep 17, 2011 3:56 am

Postby drwr » Fri Jan 27, 2012 2:07 pm

I'm not sure that I would do it this way, but you could choose this approach.

Note that if you inherit from CollisionNode, you also inherit from ReferenceCount, and you thus inherit all of the rules that go along with this. In particular, you can't do:
Code: Select all
MyObject myObject;

And you must instead do:
Code: Select all
PT(MyObject) myObject = new MyObject;


You are also inheriting from TypedObject which means you should probably also follow Panda's TypedObject convention, which means defining get_class_type(), init_type(), get_type(), and force_init_type(), as you see virtually every Panda class doing. Also ensure that you call your own class's init_type() method sometime at startup (as Panda generally does in the config_blah.cxx file).

David
drwr
 
Posts: 11425
Joined: Fri Feb 13, 2004 12:42 pm
Location: Glendale, CA

Postby tomallevi » Fri Jan 27, 2012 2:22 pm

And if i don't override those methods? What's happen?
In your opinion, what's the best solution?

Thank for your reply!
tomallevi
 
Posts: 99
Joined: Sat Sep 17, 2011 3:56 am

Postby drwr » Fri Jan 27, 2012 7:29 pm

If you don't manage the TypedObject interface, then myObject->get_type() will return CollisionNode instead of MyObject. You won't be able to ask node->is_of_type(MyObject::get_class_type()). You won't be able to use DCAST(MyObject, node) to perform a type-safe cast to MyObject.

This probably won't bother you though, if you don't actually care to use those interfaces. Nothing within Panda will care.

I cannot possible answer your second question; there is no "best" solution for such a broad question. My personal preference would *generally* be to create the game structures in my own code, and have pointers into the PandaNodes they reference, rather than tying it so intimately into the scene graph; but there are pros and cons of both approaches, and subclassing is sometimes the right answer.

David
drwr
 
Posts: 11425
Joined: Fri Feb 13, 2004 12:42 pm
Location: Glendale, CA

Postby tomallevi » Sat Jan 28, 2012 7:16 am

thanks a lot...
I try do what do you tell me but when i run my code, the program fall in segmentation fault. This is my code:
Code: Select all
#include <pandaFramework.h>
#include <pandaSystem.h>
#include <genericAsyncTask.h>
#include <collisionNode.h>

PandaFramework framework;

class MyObject : public CollisionNode {
    int a;
    static TypeHandle _type_handle;
public:
    MyObject(string str, int a) : CollisionNode(str) {
        NodePath model = framework.get_window(0)->load_model(framework.get_models(), "smiley");
        model.set_pos(0, 0, 0);
        model.reparent_to(NodePath(this));
        this->a = a;
    }
   
    int& get_a() {
        return a;
    }
   
    static TypeHandle get_class_type() {
        return _type_handle;
    }
    static void init_type() {
        CollisionNode::init_type();
        register_type(_type_handle, "MyObject", CollisionNode::get_class_type());
    }
    virtual TypeHandle get_type() const {
        return get_class_type();
    }
    virtual TypeHandle force_init_type() {
        init_type();
        return get_class_type();
    }
   
};

TypeHandle MyObject::_type_handle;

int main(int argc, char** argv) {
   framework.open_framework(argc, argv);
   WindowFramework *window = framework.open_window();
   
  NodePath path = NodePath(new MyObject("myObject", 0));
  path.set_pos(0, 10, 0);
  path.reparent_to(window->get_render());
   window->get_camera_group().look_at(path);

   framework.main_loop();
   framework.close_framework();
   return 0;
}

the problem is when i write:
Code: Select all
model.reparent_to(NodePath(this));


but i don't know how reparent model to myObject in MyObject's constructor...

Can you help me??
tomallevi
 
Posts: 99
Joined: Sat Sep 17, 2011 3:56 am

Postby rdb » Sat Jan 28, 2012 7:23 am

Replace that line with this:
Code: Select all
add_child(model.node());


Note that you need to call MyObject::init_type() at static init time (or in any case, before you start using your object) to initialise the type system properly.
rdb
 
Posts: 9460
Joined: Mon Dec 04, 2006 5:58 am
Location: Netherlands

Postby tomallevi » Sat Jan 28, 2012 7:29 am

thanks!!
but now nothing appears on the screen!
i print all node with render.ls() method. this is the output:
Code: Select all
PandaNode render S:(CullFaceAttrib RescaleNormalAttrib ShadeModelAttrib)
  PandaNode camera_group
    Camera camera ( PerspectiveLens )
      PerspectiveLens fov = 39.3201 30
  none myObject (0 solids) T:(pos 0 10 0) (hidden)
    ModelRoot smiley.egg
      GeomNode  (1 geoms: S:(TextureAttrib))


I resolve this inserting path.show() line in main function. But... why do i have to add this line? Why is this imply?

thanks for your helps!
tomallevi
 
Posts: 99
Joined: Sat Sep 17, 2011 3:56 am

Postby rdb » Sat Jan 28, 2012 7:40 am

CollisionNodes are hidden by default. You'll need to call show_through() on the child node if you want to make it show up anyway. Alternatively, you can call show() on the node itself, but this'll make the debug visualisation for the solids show up too.
rdb
 
Posts: 9460
Joined: Mon Dec 04, 2006 5:58 am
Location: Netherlands

Postby tomallevi » Sat Jan 28, 2012 8:41 am

thanks!!!
And are there consequence on the performance?
tomallevi
 
Posts: 99
Joined: Sat Sep 17, 2011 3:56 am

Postby rdb » Sat Jan 28, 2012 9:06 am

I don't see how calling show_through() could noticeably affect your performance.
rdb
 
Posts: 9460
Joined: Mon Dec 04, 2006 5:58 am
Location: Netherlands

Postby tomallevi » Sat Jan 28, 2012 9:24 am

oki thanks!!!
tomallevi
 
Posts: 99
Joined: Sat Sep 17, 2011 3:56 am

Postby tomallevi » Sun Jan 29, 2012 4:00 am

What's the different between PT(MyObject) and MyObject* ? and DCAST(MyObject, node) and dynamic_cast<MyObject*>(node)?
tomallevi
 
Posts: 99
Joined: Sat Sep 17, 2011 3:56 am

Postby rdb » Sun Jan 29, 2012 5:54 am

PT() is an automatic pointer for objects that inherit from ReferenceCount. It automatically increases the reference count when you create one and it decreases it when it goes out of scope, making sure that objects automatically get cleaned up when there are no references to them anymore. You should use them to refer to reference counted objects (including PandaNode derivatives). Be sure not to attempt to delete objects that inherit from ReferenceCount.

DCAST is a macro for objects that inherit from TypedObject that performs safe typecasting.
rdb
 
Posts: 9460
Joined: Mon Dec 04, 2006 5:58 am
Location: Netherlands

Postby tomallevi » Sun Jan 29, 2012 6:27 am

oh yea!
Thank for your explanations!!!

But i don't understand why is there not a manual section in which there's explanation this!!!
:D
tomallevi
 
Posts: 99
Joined: Sat Sep 17, 2011 3:56 am

Postby rdb » Sun Jan 29, 2012 4:34 pm

These interfaces are thoroughly explained in the Panda source code files of the respective interfaces.
rdb
 
Posts: 9460
Joined: Mon Dec 04, 2006 5:58 am
Location: Netherlands

Postby tomallevi » Tue Jan 31, 2012 1:40 pm

i try to inherit from CollisionNode but my code doesn't work!
Code: Select all
#include "pandaFramework.h"
#include "pandaSystem.h"
#include <collisionNode.h>
#include <collisionSphere.h>
#include <collisionRay.h>
#include <collisionTraverser.h>
#include <collisionHandlerQueue.h>
 
PandaFramework framework;
CollisionTraverser trav;
CollisionHandlerQueue* queue;
CollisionRay* ray;

class MyObject : public CollisionNode {
public:
        MyObject(string name) : CollisionNode(name) {
        }

        static TypeHandle get_class_type() {
            return _type_handle;
        }

        static void init_type() {
            CollisionNode::init_type();
            register_type(_type_handle, "MyObject", CollisionNode::get_class_type());
        }
       
       
        virtual TypeHandle get_type() const {
            return get_class_type();
        }

        virtual TypeHandle force_init_type() {
            init_type();
            return get_class_type();
        }



    private:
        static TypeHandle _type_handle;
};

TypeHandle MyObject::_type_handle;

void clickOnObject(const Event* ev, void* data) {
    WindowFramework* win = framework.get_window(0);
    float x = (2 * win->get_graphics_window()->get_pointer(0).get_x()) / ((float)win->get_graphics_window()->get_x_size())- 1;
    float y = (2 * win->get_graphics_window()->get_pointer(0).get_y()) / ((float)win->get_graphics_window()->get_y_size())- 1;
    ray->set_from_lens(framework.get_window(0)->get_camera(0), x, y);
    trav.traverse(framework.get_window(0)->get_render());
    cout << queue->get_num_entries() << endl;
}

int main(int argc, char *argv[]) {
    framework.open_framework(argc, argv);
    framework.set_window_title("My Panda3D Window");
    WindowFramework *window = framework.open_window();
    framework.get_window(0)->enable_keyboard();
   
    MyObject* obj = new MyObject("hi");
    obj->add_solid(new CollisionSphere(0, 0, 0, 2));
    obj->set_into_collide_mask(BitMask32::all_on());
   
    NodePath path(obj);
    path.reparent_to(window->get_render());
    path.set_pos(-10, -10, -10);
    path.show();
    window->get_camera_group().look_at(path);
   
   
    queue = new CollisionHandlerQueue();
    CollisionNode* cnode= new CollisionNode("ray");
    ray = new CollisionRay();
    cnode->add_solid(ray);
    NodePath cpath(cnode);
    cpath.reparent_to(window->get_camera_group());
    trav.add_collider(cpath, queue);
   
    framework.define_key("mouse1", "click", clickOnObject, NULL);
 
    framework.main_loop();
    framework.close_framework();
    return (0);
}

If i replace this line
Code: Select all
MyObject* obj = new MyObject("hi");

with this
Code: Select all
CollisionNode* obj = new CollisionNode("hi");

it work!!

why??

thanks!!
tomallevi
 
Posts: 99
Joined: Sat Sep 17, 2011 3:56 am

Postby rdb » Tue Jan 31, 2012 4:30 pm

As David already said, you should use this:
Code: Select all
PT(MyObject) obj = new MyObject("hi");


I'm not sure if that is the problem here though, because you haven't elaborated on "doesn't work". What doesn't work? Does it crash? Does it show an error?
rdb
 
Posts: 9460
Joined: Mon Dec 04, 2006 5:58 am
Location: Netherlands

Postby tomallevi » Tue Jan 31, 2012 4:42 pm

the problem isn't resolved if i use PT instead of *.

There're no crash. this's not work: if i click on the sphere, in the terminal is printed 0. if i use CollisionNode instead of MyObject, in the terminal is printed 1...
why?
tomallevi
 
Posts: 99
Joined: Sat Sep 17, 2011 3:56 am

Postby rdb » Tue Jan 31, 2012 4:46 pm

I also don't see you initialise the type properly using init_type().
rdb
 
Posts: 9460
Joined: Mon Dec 04, 2006 5:58 am
Location: Netherlands

Postby tomallevi » Tue Jan 31, 2012 4:56 pm

Do I call MyObject::init_type() in main function?
Code: Select all
int main(...) {
   ...
   MyObject::init_type();
   ...
}


If i do it, the problem's not resolved!

Excuse me ... I don't understand what you tell me

PS: ok, i understand but it doesn't work... i try to move MyObject::init_type method at the beginning of the main and than of open_framework call, but the problem's not resolved... where am i wrong?
PS2: and is not a register problem: i print obj->get_type().get_name() and it is "MyObject". and obj->get_type().get_parent_class(0).get_name() is "CollisionNode".
tomallevi
 
Posts: 99
Joined: Sat Sep 17, 2011 3:56 am

Postby drwr » Tue Jan 31, 2012 5:40 pm

It is important that obj->is_of_type(CollisionNode::get_class_type()) returns true, which ought to be the case if you have called init_type(). But you can verify this.

Other than that, I don't know what's wrong. Maybe you can get a clue if you set "notify-level-collide spam" in your Config.prc file, and compare the output from the CollisionNode vs. the MyObject cases.

David
drwr
 
Posts: 11425
Joined: Fri Feb 13, 2004 12:42 pm
Location: Glendale, CA

Postby tomallevi » Tue Jan 31, 2012 5:51 pm

with MyObject there's in the terminal
Code: Select all
:collide(debug): Recomputing viz for sphere, c (0 0 0), r 2
:collide(spam):   Considering render
  Comparing 0: bline, (-0.593575 -0.558208 -0.580267) - (-1.18696 -1.11624 -1.16035) to bsphere, infinite, is_in = 1
:collide(spam):   render has 1 interested colliders ( 0. ray )
:collide(spam):     Considering render/camera_group
    Comparing 0: bline, (-0.593575 -0.558208 -0.580267) - (-1.18696 -1.11624 -1.16035) to bsphere, infinite, is_in = 1
:collide(spam):     render/camera_group has 1 interested colliders ( 0. ray )
:collide(spam):       Considering render/camera_group/camera
:collide(spam):       render/camera_group/camera has 0 interested colliders ( )
:collide(spam):       Considering render/camera_group/ray
      Not comparing 0 to render/camera_group/ray (same node)
:collide(spam):       render/camera_group/ray has 0 interested colliders ( )
:collide(spam):     Considering render/ciao
    Comparing 0: bline, (-0.593575 -0.558208 -0.580267) - (-1.18696 -1.11624 -1.16035) to bsphere, c (-10 -10 -10), r 2, is_in = 1
:collide(spam):     render/ciao has 1 interested colliders ( 0. ray )
0


with collisionNode there's
Code: Select all
:collide(debug): Recomputing viz for sphere, c (0 0 0), r 2
:collide(spam):   Considering render
  Comparing 0: bline, (-0.567779 -0.585463 -0.578809) - (-1.13551 -1.17088 -1.15757) to bsphere, infinite, is_in = 1
:collide(spam):   render has 1 interested colliders ( 0. ray )
:collide(spam):     Considering render/camera_group
    Comparing 0: bline, (-0.567779 -0.585463 -0.578809) - (-1.13551 -1.17088 -1.15757) to bsphere, infinite, is_in = 1
:collide(spam):     render/camera_group has 1 interested colliders ( 0. ray )
:collide(spam):       Considering render/camera_group/camera
:collide(spam):       render/camera_group/camera has 0 interested colliders ( )
:collide(spam):       Considering render/camera_group/ray
      Not comparing 0 to render/camera_group/ray (same node)
:collide(spam):       render/camera_group/ray has 0 interested colliders ( )
:collide(spam):     Considering render/ciao
    Comparing 0: bline, (-0.567779 -0.585463 -0.578809) - (-1.13551 -1.17088 -1.15757) to bsphere, c (-10 -10 -10), r 2, is_in = 1
:collide(spam):     render/ciao has 1 interested colliders ( 0. ray )
:collide(spam): Colliding against CollisionNode 0x10d5808:5 which has 1 collision solids.
:collide(debug): intersection detected from render/camera_group/ray into render/ciao


thanks for your patience!

i don't tell I use develop skd... in ubuntu 11.10 64bit
tomallevi
 
Posts: 99
Joined: Sat Sep 17, 2011 3:56 am

Postby drwr » Tue Jan 31, 2012 6:04 pm

Oh, hmm, I see the problem. The CollisionTraverser has a check for is_exact_type(CollisionNode::get_class_type()). That is, it doesn't support subclassing of CollisionNode.

I can put in an easy fix for this.

David
drwr
 
Posts: 11425
Joined: Fri Feb 13, 2004 12:42 pm
Location: Glendale, CA

Postby tomallevi » Tue Jan 31, 2012 6:14 pm

Thanks a lot!! :)
Will it be fixed?
tomallevi
 
Posts: 99
Joined: Sat Sep 17, 2011 3:56 am

Postby drwr » Tue Jan 31, 2012 6:46 pm

The fix is committed. You'll have to either get the source and build it yourself, or wait for the buildbot to update the 1.8.0 version.

David
drwr
 
Posts: 11425
Joined: Fri Feb 13, 2004 12:42 pm
Location: Glendale, CA

Postby tomallevi » Wed Feb 01, 2012 2:05 am

You hate me now.. :)
Is the version 1.8 the same of the develop version? If not, where can i download this?
thanks a lot!

PS: now it works!!

thankssssss!!!!!!! :D :D :D :D :D
tomallevi
 
Posts: 99
Joined: Sat Sep 17, 2011 3:56 am

Postby tomallevi » Sun Feb 05, 2012 10:49 am

Uhm... i have another problem...
Code: Select all
#include "pandaFramework.h"
#include "pandaSystem.h"
#include "aiCharacter.h"
#include "typeHandle.h"

#include "genericAsyncTask.h"
#include "asyncTaskManager.h"

#include <collisionRay.h>
#include <collisionHandlerQueue.h>
#include <collisionTraverser.h>
#include <collisionSphere.h>
#include <nodePathCollection.h>
 
PandaFramework framework;
WindowFramework* window;
PT(AsyncTaskManager) taskMgr = AsyncTaskManager::get_global_ptr();

CollisionTraverser trav;
CollisionHandlerQueue* queue;
CollisionRay* ray;
NodePathCollection coll;

class MyObject : public CollisionNode {
public:
    AICharacter* c;
   
    MyObject() : CollisionNode("MyObject") {
    }
   
        static TypeHandle get_class_type() {
            return _type_handle;
        }

        static void init_type() {
            TypedObject::init_type();
            register_type(_type_handle, "MyObject", TypedObject::get_class_type());
        }
       
       
        virtual TypeHandle get_type() const {
            return MyObject::get_class_type();
        }
        virtual TypeHandle force_init_type() {
            init_type();
            return MyObject::get_class_type();
        }
               
    private:       
        static TypeHandle _type_handle;
};
TypeHandle MyObject::_type_handle;

void select(const Event* ev, void* data) {
        float x = (2 * window->get_graphics_window()->get_pointer(0).get_x()) / ((float) window->get_graphics_window()->get_x_size()) - 1;
        float y = (2 * window->get_graphics_window()->get_pointer(0).get_y()) / ((float) window->get_graphics_window()->get_y_size()) - 1;
    ray->set_from_lens(window->get_camera(0), x, -y);
    trav.traverse(window->get_render());
    coll.clear();
    for (int i =0; i < queue->get_num_entries(); i++)
        coll.add_path(queue->get_entry(i)->get_into_node_path());
    cout << "num: " << queue->get_num_entries() << endl;
}

void print(const Event* ev, void* data) {
    for(int i =0; i < coll.get_num_paths(); i++) {
        cout << i << " " << coll[i] <<  endl;
        if (coll[i].node()->is_of_type(MyObject::get_class_type())) {
            cout << DCAST(MyObject, coll[i].node())->c << endl;
        }
    }
}

int main(int argc, char *argv[]) {
    framework.open_framework(argc, argv);
    framework.set_window_title("My Panda3D Window");
    window = framework.open_window();
    framework.get_window(0)->enable_keyboard();
   
    PT(MyObject) obj = new MyObject();
    obj->add_solid(new CollisionSphere(0, 0, 0, 3));
    NodePath path (obj);
    path.show();
    obj->c = new AICharacter("char", path, 60, 0.05, 15);
    path.reparent_to(window->get_render());
    path.set_pos(-10, -10, -10);
    window->get_camera_group().look_at(path);
   
    ray = new CollisionRay();
    queue = new CollisionHandlerQueue();
    CollisionNode* n = new CollisionNode("ray");
    n->add_solid(ray);
    NodePath p = window->get_camera_group().attach_new_node(n);
    trav.add_collider(p, queue);
   
    framework.define_key("mouse1", "select", &select, (void*)NULL);
   
    framework.define_key("mouse3", "print", &print, (void*)NULL);
    framework.main_loop();
    framework.close_framework();
    return (0);
}


when i click on the collision sphere with the mouse1 button, it's printed "num1". but when i click with the mouse3 button it's printed
Code: Select all
0 render/MyObject
Type

and the program is blocked here. I must kill it with Ctrl+C...
Why?
Where am i wrong?

thanks a lot for your patience!
tomallevi
 
Posts: 99
Joined: Sat Sep 17, 2011 3:56 am

Postby drwr » Sun Feb 05, 2012 3:07 pm

I don't know; that's strange. What do you see on the stack if you break into the program with the debugger once it is blocked?

David
drwr
 
Posts: 11425
Joined: Fri Feb 13, 2004 12:42 pm
Location: Glendale, CA

Postby tomallevi » Sun Feb 05, 2012 3:25 pm

If i use this
Code: Select all
void print(const Event* ev, void* data) {
    cout << DCAST(MyObject, coll[0].node())->c << endl;
}

as print function, the program works perfectly.

but with this, the program doesn't work
Code: Select all
void print(const Event* ev, void* data) {
    cout << DCAST(MyObject, coll[0].node())->c << endl;
    cout << "type: " << coll[0].node()->is_of_type(MyObject::get_class_type()) << endl;
}


I suppose that the error is in the calling of is_of_type method. or in MyObject::get_class_type method.
tomallevi
 
Posts: 99
Joined: Sat Sep 17, 2011 3:56 am

Postby drwr » Mon Feb 06, 2012 11:21 pm

I don't see anything obviously wrong. If something is indeed broken, it must be something subtle. Have you found any more information recently?

David
drwr
 
Posts: 11425
Joined: Fri Feb 13, 2004 12:42 pm
Location: Glendale, CA

Next

Return to C++ coding using Panda3D

Who is online

Users browsing this forum: No registered users and 1 guest