Duplicate an object programmatically
4 posters
Duplicate an object programmatically
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
Best,
Matt
Re: Duplicate an object programmatically
I tried giving this a shot but it didn't work out. Nothing new appears.
Here's what I tried
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
Re: Duplicate an object programmatically
Man you really go far to get that working
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
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
Re: Duplicate an object programmatically
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
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
Re: Duplicate an object programmatically
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
I tried keeping this date in order to copy objects, but then I'm still missing the correct textures.
Best,
Matt
Re: Duplicate an object programmatically
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:
2. Clone vertex groups:
3. Have a sio2ResourceGenId which takes a single SIO2object* as a parameter:
In my wrapper class, I use the code like so:
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
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;
}
}
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;
}
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
Re: Duplicate an object programmatically
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,
Cheers,
Re: Duplicate an object programmatically
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
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
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
Re: Duplicate an object programmatically
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,
Cheers,
Similar topics
» What is SIO2v1.4 to duplicate it?
» Duplicate / clone SIO2Object with new material
» physics object inside another physics object
» Get the 2D location of an 3D object
» Physic object
» Duplicate / clone SIO2Object with new material
» physics object inside another physics object
» Get the 2D location of an 3D object
» Physic object
Permissions in this forum:
You cannot reply to topics in this forum