Duplicate an object programmatically

View previous topic View next topic Go down

Duplicate an object programmatically

Post  matt on Tue Sep 30, 2008 6:25 pm

Is there a way to duplicate an object programmatically? I need to create instances of existing objects (e.g. a cube) at run-time.

Best,
Matt

matt

Posts : 155
Join date : 2008-09-30

View user profile http://elfrun.net

Back to top Go down

Re: Duplicate an object programmatically

Post  sodapunk on Tue Sep 30, 2008 11:33 pm

I tried giving this a shot but it didn't work out. Nothing new appears.

Here's what I tried


Code:


SIO2object * duplicateObject(char*path, char*name)
{
   SIO2object * oldObj = ( SIO2object* )sio2ResourceGet( sio2->_SIO2resource,
                                               SIO2_OBJECT,
                                               path);

   SIO2object * newObj = sio2ObjectInit(name);
   copyVector(oldObj->pos, newObj->pos );
   copyVector(oldObj->rot, newObj->rot );
   copyVector(oldObj->scl, newObj->scl );
   copyVector(oldObj->dim, newObj->dim );
   copyColor(oldObj->col, newObj->col );
   
   newObj->dst = oldObj->dst;
   newObj->mat = oldObj->mat;
   newObj->rad = oldObj->rad;
   newObj->flags = oldObj->flags;
   newObj->bounds = oldObj->bounds;
   newObj->mass = oldObj->mass;
   newObj->damp = oldObj->damp;
   newObj->rotdamp = oldObj->rotdamp;
   
   newObj->vbo = oldObj->vbo;
   
   memcpy(newObj->vbo_offset, oldObj->vbo_offset, 20);

   newObj->n_vertexgroup = oldObj->n_vertexgroup;
   
   newObj->_SIO2vertexgroup = ( SIO2vertexgroup ** ) malloc( newObj->n_vertexgroup * sizeof( SIO2vertexgroup ) );
   
   unsigned int i = 0;
   while( i != newObj->n_vertexgroup)
   {
      newObj->_SIO2vertexgroup[i] = ( SIO2vertexgroup * ) malloc( sizeof( SIO2vertexgroup ) );
      memcpy(newObj->_SIO2vertexgroup[i], oldObj->_SIO2vertexgroup[i],  sizeof( SIO2vertexgroup ));
      
      
      i++;
   }
   genObjID(newObj);
   return newObj;
}

void copyVector(vec3*from, vec3*to)
{
   from->x = to->x;
   from->y = to->y;
   from->z = to->z;   
   
}
void copyColor(col4*from, col4*to)
{
   to->r = from->r;
   to->g = from->g;
   to->b = from->b;
   to->a = from->a;
}
void genObjID(SIO2object *_SIO2object)
{
   
   sio2ObjectGenId( _SIO2object );
   unsigned int j = 0;
   while( j != _SIO2object->n_vertexgroup )
   {
      if( _SIO2object->_SIO2vertexgroup[ j ]->_SIO2material &&
        _SIO2object->_SIO2vertexgroup[ j ]->_SIO2material->_SIO2soundbuffer )
      {
         _SIO2object->_SIO2vertexgroup[ j ]->_SIO2sound = sio2SoundInit( _SIO2object->name );
         
         sio2SoundGenId( _SIO2object->_SIO2vertexgroup[ j ]->_SIO2sound,
                    _SIO2object->_SIO2vertexgroup[ j ]->_SIO2material->_SIO2soundbuffer,
                    _SIO2object->_SIO2vertexgroup[ j ]->_SIO2material->sflags );
         
         if( sio2IsEnabled( _SIO2object->_SIO2vertexgroup[ j ]->_SIO2sound->flags, SIO2_SOUND_AMBIENT ) )
         { sio2SoundSetAmbient( _SIO2object->_SIO2vertexgroup[ j ]->_SIO2sound ); }
         else
         {
            sio2SoundSetFx( _SIO2object->_SIO2vertexgroup[ j ]->_SIO2sound,
                       _SIO2object->pos,
                       _SIO2object->rad );
         }
         
         if( sio2IsEnabled( _SIO2object->_SIO2vertexgroup[ j ]->_SIO2sound->flags, SIO2_SOUND_AUTOPLAY ) )
         { sio2SoundPlay( _SIO2object->_SIO2vertexgroup[ j ]->_SIO2sound ); }
      }
      
      sio2VertexGroupGenId( _SIO2object->_SIO2vertexgroup[ j ] );
      ++j;
   }
   
}

sodapunk

Posts : 7
Join date : 2008-09-28

View user profile

Back to top Go down

Re: Duplicate an object programmatically

Post  sio2interactive on Wed Oct 01, 2008 12:19 am

Man you really go far to get that working Wink

You can simply to do this:

1. Open an .sio2

2. use the sio2ResourceExtractFile function pointing to the file you want to duplicate (like: "object/Cube") then use the usual:

sio2ResourceClose( sio2->_SIO2resource );

sio2ResourceGenId( sio2->_SIO2resource );

Et voila! However if you want to modify some properties you'll first need to get the handle manually cuz sio2ResourceGet will pickup the first one with the name that he found...

You can always add another functions that will do it backward... check the source of sio2ResourceGet
avatar
sio2interactive

Posts : 1526
Join date : 2008-08-26
Age : 37
Location : Shanghai

View user profile http://sio2interactive.com

Back to top Go down

Re: Duplicate an object programmatically

Post  matt on Wed Oct 01, 2008 3:11 pm

From what I see, the way you described goes through the whole resource extraction process again. The file gets decompressed to the file system, then is read from the file system again...

This sounds pretty slow to me and seems unsuitable for objects which need to be duplicated really fast... Think of something like bullets from a gun. I'd prefer to have a dedicated function which clones objects in memory. I guess this is most likely not needed for videos, maybe even sounds don't have to be cloned if this is done by the OpenAL integration. But at least objects need to be duplicated in memory really fast!

Moreover, following your suggestion, an object would have to know from which sio2 file it was loaded or you would have to provide this information from the outside. I don't really like this approach.

Finally, I wouldn't be able to access this object later with sio2ResourceGet, as you already mentioned, which makes cloning pretty useless after all. In my particular case, I'm wrapping things up in C++ classes and I need a way to access the correct (cloned) object instance to wrap the correct one.

So, I'd greatly appreciate if you could provide means to clone objects in a more suitable way!

Thanks and keep up the good work!
Matt

matt

Posts : 155
Join date : 2008-09-30

View user profile http://elfrun.net

Back to top Go down

Re: Duplicate an object programmatically

Post  sio2interactive on Wed Oct 01, 2008 3:58 pm

Allright I'll see what I can do... will keep you posted.
avatar
sio2interactive

Posts : 1526
Join date : 2008-08-26
Age : 37
Location : Shanghai

View user profile http://sio2interactive.com

Back to top Go down

Re: Duplicate an object programmatically

Post  matt on Wed Oct 01, 2008 4:30 pm

Thanks! I tried it for myself but one particular problem I encountered was that the "buf" attribute of an object is no longer available once sio2ObjectGenId was called on the clone source. I would have taken the VBO back from the source using glGetBufferSubData, but that's not available in OpenGL ES :-( Same for the indices in SIO2vertexgroup.ind...

I tried keeping this date in order to copy objects, but then I'm still missing the correct textures.

Best,
Matt

matt

Posts : 155
Join date : 2008-09-30

View user profile http://elfrun.net

Back to top Go down

Re: Duplicate an object programmatically

Post  matt on Wed Oct 01, 2008 6:05 pm

Given that you DO NOT free the vertex groups indices (comment out free on attribute ind, sio2VertexGroupGenId) and vertex data (comment out free on attribute buf, sio2ObjectGenId), the following code works for me:

1. Clone the object:
Code:
SIO2object *sio2ObjectClone( SIO2object *_SIO2object, char *_name )
{
   SIO2object *clone = sio2ObjectInit( _name );
   
   memcpy( clone->pos, _SIO2object->pos, 12 );
   memcpy( clone->rot, _SIO2object->rot, 12 );
   memcpy( clone->scl, _SIO2object->scl, 12 );
   sio2ObjectGetMatrix( clone );
   
   memcpy( &clone->rad, &_SIO2object->rad, 4 );
   memcpy( &clone->flags, &_SIO2object->flags, 4 );
   memcpy( &clone->bounds, &_SIO2object->bounds, 1 );
   memcpy( &clone->mass, &_SIO2object->mass, 4 );
   memcpy( &clone->damp, &_SIO2object->damp, 4 );
   memcpy( &clone->rotdamp, &_SIO2object->rotdamp, 4 );
   memcpy( clone->dim, _SIO2object->dim, 12 );
   memcpy( &clone->iname[ 0 ], &_SIO2object->iname[ 0 ], SIO2_MAX_CHAR );
   
   if( !_SIO2object->iname[ 0 ] )
   {
      memcpy( clone->vbo_offset, _SIO2object->vbo_offset, SIO2_OBJECT_NVBO_OFFSET * sizeof( int ) );
      if( clone->vbo_offset[ SIO2_OBJECT_SIZE ] )
      {
         clone->buf = ( unsigned char * ) malloc( _SIO2object->vbo_offset[ SIO2_OBJECT_SIZE ] );
         memcpy( &clone->buf[ 0 ], &_SIO2object->buf[ 0 ], clone->vbo_offset[ SIO2_OBJECT_SIZE ] );
      }
      
      memcpy( &clone->n_vertexgroup, &_SIO2object->n_vertexgroup, 1 );
      
      if( clone->n_vertexgroup )
      {
         unsigned int i = 0;
         
         clone->_SIO2vertexgroup = ( SIO2vertexgroup ** ) malloc( clone->n_vertexgroup * sizeof( SIO2vertexgroup ) );
         
         while( i != clone->n_vertexgroup )
         {
            char name[ SIO2_MAX_CHAR ];
            memcpy( &name[ 0 ], &_SIO2object->_SIO2vertexgroup[ i ]->name[ 0 ], SIO2_MAX_CHAR );
            clone->_SIO2vertexgroup[ i ]  = sio2VertexGroupInit( name );
            sio2VertexGroupClone( clone->_SIO2vertexgroup[ i ], _SIO2object->_SIO2vertexgroup[ i ] );
            ++i;
         }
      }
   }   
   
   sio2ResourceGenId( clone );
   sio2ResourceBindMaterial( sio2->_SIO2resource, clone ); // Apply materials
   
   return clone;
}

2. Clone vertex groups:
Code:
void sio2VertexGroupClone( SIO2vertexgroup *_SIO2dest,
                    SIO2vertexgroup     *_SIO2source )
{
   // Note that n_ind is divided by 2 below!
   unsigned int real_n_ind = _SIO2source->n_ind * 2;
   
   memcpy( _SIO2dest->mname, _SIO2source->mname, SIO2_MAX_CHAR );
   memcpy( &_SIO2dest->n_ind, &real_n_ind, 4 );
   
   if( _SIO2dest->n_ind )
   {
      _SIO2dest->ind = (unsigned short *) malloc( real_n_ind );
      memcpy( &_SIO2dest->ind[ 0 ], &_SIO2source->ind[ 0 ], real_n_ind );
   }
}

3. Have a sio2ResourceGenId which takes a single SIO2object* as a parameter:
Code:
void sio2ResourceGenId( SIO2object *_SIO2object )
{
   unsigned int j = 0;

   sio2ObjectGenId( _SIO2object );
   
   while( j != _SIO2object->n_vertexgroup )
   {
      if( _SIO2object->_SIO2vertexgroup[ j ]->_SIO2material &&
        _SIO2object->_SIO2vertexgroup[ j ]->_SIO2material->_SIO2soundbuffer )
      {
         _SIO2object->_SIO2vertexgroup[ j ]->_SIO2sound = sio2SoundInit( _SIO2object->name );
         
         sio2SoundGenId( _SIO2object->_SIO2vertexgroup[ j ]->_SIO2sound,
                    _SIO2object->_SIO2vertexgroup[ j ]->_SIO2material->_SIO2soundbuffer,
                    _SIO2object->_SIO2vertexgroup[ j ]->_SIO2material->sflags );
         
         if( sio2IsEnabled( _SIO2object->_SIO2vertexgroup[ j ]->_SIO2sound->flags, SIO2_SOUND_AMBIENT ) )
         { sio2SoundSetAmbient( _SIO2object->_SIO2vertexgroup[ j ]->_SIO2sound ); }
         else
         {
            sio2SoundSetFx( _SIO2object->_SIO2vertexgroup[ j ]->_SIO2sound,
                       _SIO2object->pos,
                       _SIO2object->rad );
         }
         
         if( sio2IsEnabled( _SIO2object->_SIO2vertexgroup[ j ]->_SIO2sound->flags, SIO2_SOUND_AUTOPLAY ) )
         { sio2SoundPlay( _SIO2object->_SIO2vertexgroup[ j ]->_SIO2sound ); }
      }
      
      sio2VertexGroupGenId( _SIO2object->_SIO2vertexgroup[ j ] );
      ++j;
   }
}
(I also changed sio2ResourceGenId( SIO2resource *_SIO2resource ) to use that one.)

In my wrapper class, I use the code like so:
Code:
NamedEntity* Mesh::clone() {
   SIO2object* clonedObject = sio2ObjectClone( object, (char*) getName().c_str() );
   sio2PhysicAddObject( sio2->_SIO2physic, clonedObject );
   Mesh* clonedMesh = new Mesh( clonedObject, getName() );
   return clonedMesh;
}
(Note the sio2PhysicAddObject!)

This is NOT a solution for "production code". Since vertices and indices are not free'd, this approach takes lots of unneccessary memory and produces memory leaks. Still, it worked for me for testing until sio2interactive provides a better approach which e.g. makes use of mesh data sharing.

Matt

matt

Posts : 155
Join date : 2008-09-30

View user profile http://elfrun.net

Back to top Go down

Re: Duplicate an object programmatically

Post  sio2interactive on Wed Oct 01, 2008 7:11 pm

I agree this is not a good solution, however glGetBufferPointervOES is available so I think its possible to map/unmap the GL_ARRAY_BUFFER, I tried just now but couldn't make it work I will give it a shot later.

Cheers,
avatar
sio2interactive

Posts : 1526
Join date : 2008-08-26
Age : 37
Location : Shanghai

View user profile http://sio2interactive.com

Back to top Go down

Re: Duplicate an object programmatically

Post  ludi on Fri Dec 05, 2008 2:47 am

Is there already any solution without reading the sio2 file again?

Anyway, I just tried to add the following code within the templateScreenTap method.

sio2ResourceOpen( sio2->_SIO2resource, "ball.sio2", 1 );
sio2ResourceExtractFile(sio2->_SIO2resource, "object/ball");
sio2ResourceClose( sio2->_SIO2resource );
sio2ResourceGenId( sio2->_SIO2resource );

But now I receive the following error:
ERROR: /Users/lt/Documents/work/Master/Semester 3/iPhone/SVN/Code/Game_3D/../src/sio2/sio2_object.cc(398):sio2ObjectGenId
Game(11449,0xa07d6fa0) malloc: *** error for object 0x1897000: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Game(11449,0xa07d6fa0) malloc: *** error for object 0x5fe2220: Non-aligned pointer being freed (2)
*** set a breakpoint in malloc_error_break to debug
Game(11449,0xa07d6fa0) malloc: *** error for object 0x1894000: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Game(11449,0xa07d6fa0) malloc: *** error for object 0x189f400: non-page-aligned, non-allocated pointer being freed
*** set a breakpoint in malloc_error_break to debug


Thanks a lot
Ludi

sio2interactive wrote:Man you really go far to get that working Wink

You can simply to do this:

1. Open an .sio2

2. use the sio2ResourceExtractFile function pointing to the file you want to duplicate (like: "object/Cube") then use the usual:

sio2ResourceClose( sio2->_SIO2resource );

sio2ResourceGenId( sio2->_SIO2resource );

Et voila! However if you want to modify some properties you'll first need to get the handle manually cuz sio2ResourceGet will pickup the first one with the name that he found...

You can always add another functions that will do it backward... check the source of sio2ResourceGet

ludi

Posts : 14
Join date : 2008-10-19

View user profile

Back to top Go down

Re: Duplicate an object programmatically

Post  sio2interactive on Fri Dec 05, 2008 4:24 pm

Check the sio2ObjectDuplicate function, and also check for another thread on the subject in this forum, don't remember which one but I know I was giving an example how to use that function to create objects on the fly...

Cheers,
avatar
sio2interactive

Posts : 1526
Join date : 2008-08-26
Age : 37
Location : Shanghai

View user profile http://sio2interactive.com

Back to top Go down

Re: Duplicate an object programmatically

Post  Sponsored content


Sponsored content


Back to top Go down

View previous topic View next topic Back to top

- Similar topics

 
Permissions in this forum:
You cannot reply to topics in this forum