Example #1
0
/* Sets the KFDATA release level */
void PutKfRelease3ds(database3ds *db, releaselevel3ds release)
{
   KFHdr *d;

   if (db == NULL)
      SET_ERROR_RETURN(ERR_INVALID_ARG);
   if (db->topchunk == NULL)
      SET_ERROR_RETURN(ERR_INVALID_DATABASE);

   if ((db->topchunk->tag == M3DMAGIC) || (db->topchunk->tag == CMAGIC))
   {
      chunk3ds *kfdata;
      chunk3ds *kfhdr;

      /* Find the KFDATA section */
      FindChunk3ds(db->topchunk, KFDATA, &kfdata);

      /* If one doesn't exist, then create it */
      if (kfdata == NULL)
      {
	 InitChunkAs3ds(&kfdata, KFDATA);
	 AddChildOrdered3ds(db->topchunk, kfdata);
      }

      /* Find the KFHDR */
      FindChunk3ds(kfdata, KFHDR, &kfhdr);

      /* If a KFHDR doesn't exist, then create it */
      if (kfhdr == NULL)
      {

	 d = InitChunkAndData3ds(&kfhdr, KFHDR);
	 d->filename = strdup("");
	 d->animlength = 30; /* Just a default */
	 AddChildOrdered3ds(kfdata, kfhdr);
	 
      } else /* Else, just get its data */
      {
	 d = ReadChunkData3ds(kfhdr);
      }

      /* Set the revision level */
      switch(release)
      {
      case Release13ds:
	 d->revision = 1;
	 break;
      case Release23ds:
	 d->revision = 2;
	 break;
      case Release33ds:
	 d->revision = 5;
	 break;
      case ReleaseNotKnown3ds:
	 d->revision = 6;
	 break;
      }
   }
}
Example #2
0
void CopyBackground3ds(database3ds *destdb, database3ds *srcdb)
{
   chunk3ds *srcmdata, *destmdata, *srcchunk, *destchunk;
   
   if ((destdb == NULL) || (srcdb == NULL))
      SET_ERROR_RETURN(ERR_INVALID_ARG);
   if ((srcdb->topchunk == NULL) || (destdb->topchunk == NULL))
      SET_ERROR_RETURN(ERR_INVALID_DATABASE);
   if ((srcdb->topchunk->tag != M3DMAGIC) && (srcdb->topchunk->tag != CMAGIC))
      SET_ERROR_RETURN(ERR_WRONG_DATABASE);
   if ((destdb->topchunk->tag != M3DMAGIC) && (destdb->topchunk->tag != CMAGIC))
      SET_ERROR_RETURN(ERR_WRONG_DATABASE);

   /* Find source mesh section */
   FindChunk3ds(srcdb->topchunk, MDATA, &srcmdata);

   /* If found */
   if (srcmdata != NULL)
   {
      /* Find or create destination mesh section */
      FindChunk3ds(destdb->topchunk, MDATA, &destmdata);
      if (destmdata == NULL)
      {
	 InitChunkAs3ds(&destmdata, MDATA);
	 AddChildOrdered3ds(destdb->topchunk, destmdata);
      }

      /* Scan the source mdata section looking for background setting chunks */
      for (srcchunk = srcmdata->children; srcchunk != NULL; srcchunk = srcchunk->sibling)
      {
	 switch(srcchunk->tag)
	 {
	 case V_GRADIENT:
	 case SOLID_BGND:
	 case BIT_MAP:
	 case USE_SOLID_BGND:
	 case USE_V_GRADIENT:
	 case USE_BIT_MAP:
	    /* if the same chunk exists in the destination, then delete it */
	    FindNextChunk3ds(destmdata->children, srcchunk->tag, &destchunk);
	    if (destchunk != NULL)
	       DeleteChunk3ds(destchunk);

	    /* Copy and add the chunk */
	    CopyChunk3ds(srcchunk, &destchunk);
	    AddChildOrdered3ds(destmdata, destchunk);
	    break;
	 default:
	    break;
	 }
      }
   }
}
Example #3
0
/* Sets the MeshRelease level */
void PutMeshRelease3ds(database3ds *db, releaselevel3ds release)
{

   if (db == NULL)
      SET_ERROR_RETURN(ERR_INVALID_ARG);
   if (db->topchunk == NULL)
      SET_ERROR_RETURN(ERR_INVALID_DATA);

   if ((db->topchunk->tag == M3DMAGIC) || (db->topchunk->tag == CMAGIC))
   {
      chunk3ds *mdata;
      chunk3ds *c;
      M3dVersion *d;


      FindChunk3ds(db->topchunk, MDATA, &mdata);

      if (mdata == NULL)
      {
	 InitChunkAs3ds(&mdata, MDATA);
	 AddChildOrdered3ds(db->topchunk, mdata);
      }
      
      ReplaceOrAddChild3ds(mdata, MESH_VERSION, &c);
      d = InitChunkData3ds(c);

      switch(release)
      {
      case Release13ds:
	 d->version = 1;
	 break;
      case Release23ds:
	 d->version = 2;
	 break;
      case Release33ds:
	 d->version = 3;
	 break;
      case ReleaseNotKnown3ds:
	 d->version = 4;
      }
   }
}
Example #4
0
void PutBackground3ds(database3ds *db, background3ds *bgnd)
{
   chunk3ds *mdata;

       if(db == NULL || bgnd == NULL)
      SET_ERROR_RETURN(ERR_INVALID_ARG); 

    if(db->topchunk == NULL) 
      SET_ERROR_RETURN(ERR_INVALID_DATABASE);
    
    if (!(db->topchunk->tag == M3DMAGIC || db->topchunk->tag == CMAGIC))
      SET_ERROR_RETURN(ERR_WRONG_DATABASE);

      /* Search for a mesh data chunk */
   FindChunk3ds(db->topchunk, MDATA, &mdata);

   /* If one isn't found, add it to the list */
   if (mdata == NULL)
   {
      InitChunkAs3ds(&mdata, MDATA);
      AddChildOrdered3ds(db->topchunk, mdata);
   }

   /* if (1) */ /* Put bitmap background chunk. */
   {
      chunk3ds *c;
      BitMap *d;

      ReplaceOrAddChild3ds(mdata, BIT_MAP, &c);
      d = InitChunkData3ds(c);
      d->bitmap = (bgnd->bitmap.name)? strdup(bgnd->bitmap.name): strdup("");
   }

   /* if (1) */ /* Put the SOLID_BGND chunk */
   {
      chunk3ds *cs, *cc;
      ColorF *dc;

      ReplaceOrAddChild3ds(mdata, SOLID_BGND, &cs);

      dc = InitChunkAndData3ds(&cc, COLOR_F);
      
      dc->red = bgnd->solid.color.r;
      dc->green = bgnd->solid.color.g;
      dc->blue = bgnd->solid.color.b;
      
      AddChild3ds(cs, cc);

      dc = InitChunkAndData3ds(&cc, LIN_COLOR_F);
      
      dc->red = bgnd->solid.color.r;
      dc->green = bgnd->solid.color.g;
      dc->blue = bgnd->solid.color.b;
      
      AddChild3ds(cs, cc);
   }

   /* if (1) */ /* Put the V_GRADIENT chunk */
   {
      chunk3ds *cv, *cc;
      VGradient *dv;
      ColorF *dc;

      ReplaceOrAddChild3ds(mdata, V_GRADIENT, &cv);
      dv = InitChunkData3ds(cv);
      dv->gradpercent = bgnd->vgradient.gradpercent;

      dc = InitChunkAndData3ds(&cc, COLOR_F);
      dc->red = bgnd->vgradient.top.r;
      dc->green = bgnd->vgradient.top.g;
      dc->blue = bgnd->vgradient.top.b;
      
      AddChild3ds(cv, cc);

      dc = InitChunkAndData3ds(&cc, LIN_COLOR_F);
      dc->red = bgnd->vgradient.top.r;
      dc->green = bgnd->vgradient.top.g;
      dc->blue = bgnd->vgradient.top.b;
      
      AddChild3ds(cv, cc);

      dc = InitChunkAndData3ds(&cc, COLOR_F);
      dc->red = bgnd->vgradient.mid.r;
      dc->green = bgnd->vgradient.mid.g;
      dc->blue = bgnd->vgradient.mid.b;
      
      AddChild3ds(cv, cc);

      dc = InitChunkAndData3ds(&cc, LIN_COLOR_F);
      dc->red = bgnd->vgradient.mid.r;
      dc->green = bgnd->vgradient.mid.g;
      dc->blue = bgnd->vgradient.mid.b;
      
      AddChild3ds(cv, cc);

      dc = InitChunkAndData3ds(&cc, COLOR_F);
      dc->red = bgnd->vgradient.bottom.r;
      dc->green = bgnd->vgradient.bottom.g;
      dc->blue = bgnd->vgradient.bottom.b;
      
      AddChild3ds(cv, cc);

      dc = InitChunkAndData3ds(&cc, LIN_COLOR_F);
      dc->red = bgnd->vgradient.bottom.r;
      dc->green = bgnd->vgradient.bottom.g;
      dc->blue = bgnd->vgradient.bottom.b;
      
      AddChild3ds(cv, cc);

   }
   
   /* if (1) */ /* Add a use_bitmap_bgnd, use_solid_bgnd, or use_v_gradient */
   {
      chunk3ds *chunk;
   
      /* first, find any existing use_* chunks */
      FindChunk3ds(mdata, USE_BIT_MAP, &chunk);
      if (chunk == NULL)
      {
	 FindChunk3ds(mdata, USE_SOLID_BGND, &chunk);
	 if (chunk == NULL)
	 {
	    FindChunk3ds(mdata, USE_V_GRADIENT, &chunk);
	 }
      }
      
      /* If one was found, delete it */
      if (chunk != NULL)
      {
	 DeleteChunk3ds(chunk);
      }
      
      if (bgnd->bgndused != NoBgnd)
      {
	 if (chunk == NULL)
	 {
	    InitChunk3ds(&chunk);
	    chunk->tag = USE_BIT_MAP; /* just to help place in order */
	    AddChildOrdered3ds(mdata,chunk);
	 }
	 
	 /* add the new use_* chunk */
	 switch (bgnd->bgndused)
	 {
	 case UseBitmapBgnd:
	    chunk->tag = USE_BIT_MAP;
	    break;
	 case UseSolidBgnd:
	    chunk->tag = USE_SOLID_BGND;
	    break;
	 case UseVGradientBgnd:
	    chunk->tag = USE_V_GRADIENT;
	    break;
	 case NoBgnd:
	    chunk->tag = NULL_CHUNK;
	    break;
	 }
      }
   }
}
Example #5
0
/*----------------------------------------------------------------
 |
 | PutLight3ds
 |
 |  Put chunks in database from light3ds structure.
 |
 +-----------------------------------------------------------------*/
void PutLight3ds(database3ds *db, light3ds *light)
{
  chunk3ds *pMdata, *pNamed, *pLight, *pSpot, *current, *xdata;

  if (db == NULL || light == NULL) SET_ERROR_RETURN(ERR_INVALID_ARG);
  if (db->topchunk == NULL) SET_ERROR_RETURN(ERR_INVALID_DATABASE);
  if (!(db->topchunk->tag == M3DMAGIC || db->topchunk->tag == CMAGIC))
     SET_ERROR_RETURN(ERR_WRONG_DATABASE);

  FindChunk3ds(db->topchunk, MDATA, &pMdata);
  if (pMdata == NULL) 
    {
      InitChunk3ds(&pMdata);
      pMdata->tag = MDATA;
      AddChildOrdered3ds(db->topchunk, pMdata);
    }
  
  /* Discover if the named object already exists */
  FindNamedObject3ds(db, light->name, &pNamed);
  
  /* If it does, then delete it */
  if (pNamed != NULL)
    {
      /* First, rescue the xdata chunk if there is one */
      FindChunk3ds(pNamed, XDATA_SECTION, &current);
      
      /* If there is one */
      if (current != NULL)
    {
      /* Then make a copy of it to reintroduce later */
     CopyChunk3ds(current, &xdata);
      }
      
      /* Delete the chunk's children and data, 
     leaving it in the same list order */
      DeleteChunk3ds(pNamed);
      pNamed->tag = NAMED_OBJECT; /* retag the chunk */

   } else /* else pNamed needs to be initialized and added */
   {
      InitChunkAs3ds(&pNamed, NAMED_OBJECT);
      AddChildOrdered3ds(pMdata, pNamed);
   }

  { /*--- NAME */
    NamedObject *d;

    d = InitChunkData3ds(pNamed);
    d->name = strdup(light->name);
    MakeNamedObjectListDirty3ds(db);
  }
  
  {  /*--- N_DIRECT_LIGHT & POSITION  */
    NDirectLight *d;

    pLight = kfPutGenericNode(N_DIRECT_LIGHT, pNamed);
    d = InitChunkData3ds(pLight);
    memcpy(&(d->lightpos), &(light->pos), sizeof(point3ds));
   }

  /*
   | Add children to DIRECT_LIGHT 
   */

  /*--- COLOR */
  {
    ColorF *d;
    chunk3ds *pChunk;

    pChunk = kfPutGenericNode(COLOR_F, pLight);
    d = InitChunkData3ds(pChunk);

    d->red = light->color.r;
    d->green = light->color.g;
    d->blue = light->color.b;
  }

  putTagFloat(pLight, DL_OUTER_RANGE, &light->attenuation.outer);
  ON_ERROR_RETURN;
  
  putTagFloat(pLight, DL_INNER_RANGE, &light->attenuation.inner);
  ON_ERROR_RETURN;
  
  putTagFloat(pLight, DL_MULTIPLIER, &light->multiplier);
  ON_ERROR_RETURN;

  if (light->dloff == True3ds)
    kfPutGenericNode(DL_OFF, pLight);

  if  (light->attenuation.on == True3ds)
    kfPutGenericNode(DL_ATTENUATE, pLight);

  /*--- DL_EXCLUDE */
  if (light->exclude != NULL && light->exclude->count > 0){
    chunk3ds *pChunk;
    ulong3ds i;
    DlExclude *d;

    for(i=0; i<light->exclude->count; i++){
      pChunk = kfPutGenericNode(DL_EXCLUDE, pLight);
      d = InitChunkData3ds(pChunk);
      d->name = strdup((light->exclude->list)[i].name);
    }
  }


  /*-----------------------
   |  SPOTLIGHT SECTION 
   +-----------------------*/
  if (light->spot == NULL)
    return;
  
  {
    DlSpotlight *d;

    pSpot = kfPutGenericNode(DL_SPOTLIGHT, pLight);
    d = InitChunkData3ds(pSpot);
    memcpy(&d->spotlighttarg, &light->spot->target, sizeof(point3ds));
    d->hotspotangle = light->spot->hotspot;
    d->falloffangle = light->spot->falloff;
  }
  
  putTagFloat(pSpot, DL_SPOT_ROLL, &light->spot->roll);  

  if (light->spot->aspect != 1.0F)
    putTagFloat(pSpot, DL_SPOT_ASPECT, &light->spot->aspect);  

  /*--- SHADOWS */
  if (light->spot->shadows.cast == True3ds)
    kfPutGenericNode(DL_SHADOWED, pSpot);
  
  if (light->spot->shadows.type == UseRayTraceShadow)
    kfPutGenericNode(DL_RAYSHAD, pSpot);
  
  putTagFloat(pSpot, DL_RAY_BIAS, &light->spot->shadows.raybias);

  /*--- DL_LOCAL_SHADOW2 */
  if (light->spot->shadows.local == True3ds)
  {
    DlLocalShadow2 *d;
    chunk3ds *pChunk;

    kfPutGenericNode(DL_LOCAL_SHADOW, pSpot);
    pChunk = kfPutGenericNode(DL_LOCAL_SHADOW2, pSpot);
    d = InitChunkData3ds(pChunk);

    d->localshadowbias = light->spot->shadows.bias;
    d->localshadowfilter = light->spot->shadows.filter;
    d->localshadowmapsize = light->spot->shadows.mapsize;
  }
  

  /*--- CONE */
  if (light->spot->cone.type == Rectangular)
    kfPutGenericNode(DL_SPOT_RECTANGULAR, pSpot);
  if (light->spot->cone.show == True3ds)
    kfPutGenericNode(DL_SEE_CONE, pSpot);
  if (light->spot->cone.overshoot == True3ds)
    kfPutGenericNode(DL_SPOT_OVERSHOOT, pSpot);

  /*--- PROJECTOR */
  if (light->spot->projector.use == True3ds)
  {
    DlSpotProjector *d;
    chunk3ds *pChunk;

    pChunk = kfPutGenericNode(DL_SPOT_PROJECTOR, pSpot);
    d = InitChunkData3ds(pChunk);

    d->name = strdup(light->spot->projector.bitmap);
  }
}
Example #6
0
/* Puts a mesh3ds into the chunk database.  Note that this routine will clobber
   named objects of the same name, except that it will transfer the old xdata onto
   the new object. If the developer wants to wipe out the XDATA too, he'll have
   to explicitly delete using the DeleteMesh3ds function */
void PutMesh3ds(database3ds *db, mesh3ds *mesh)
{
   chunk3ds *mdata, *nobj, *ntri, *current;
   NamedObject *nobjdata;
   chunk3ds *xdata = NULL;
   long3ds i;


   if (db == NULL || mesh == NULL) SET_ERROR_RETURN(ERR_INVALID_ARG);
   if (db->topchunk == NULL) SET_ERROR_RETURN(ERR_INVALID_DATABASE);
   if (!(db->topchunk->tag == M3DMAGIC || db->topchunk->tag == CMAGIC))
      SET_ERROR_RETURN(ERR_WRONG_DATABASE);

   FindChunk3ds(db->topchunk, MDATA, &mdata);

   if (mdata == NULL) 
   {
      InitChunk3ds(&mdata);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      mdata->tag = MDATA;
      AddChildOrdered3ds(db->topchunk, mdata);
   }

   /* Discover if the named object already exists */
   FindNamedObject3ds(db, mesh->name, &nobj);
   ON_ERROR_RETURN;
   
   /* If it does, then delete it */
   if (nobj != NULL)
   {
      /* First, rescue the xdata chunk if there is one */
      FindChunk3ds(nobj, XDATA_SECTION, &current);

      /* If there is one */
      if (current != NULL)
      {
	 /* Then make a copy of it to reintroduce later */
	 CopyChunk3ds(current, &xdata);
	 ADD_ERROR_RETURN(ERR_PUT_FAIL);
      }
      
      /* Delete the chunk's children and data, leaving it in the same list order */
      DeleteChunk3ds(nobj);
      nobj->tag = NAMED_OBJECT; /* retag the chunk */

   } else /* else nobj needs to be initialized and added */
   {
      InitChunkAs3ds(&nobj, NAMED_OBJECT);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);

      AddChildOrdered3ds(mdata, nobj);
      
   }
   

   /* Copy the mesh name into the chunk */
   nobjdata = InitChunkData3ds(nobj);
   ADD_ERROR_RETURN(ERR_PUT_FAIL);
   nobjdata->name = strdup(mesh->name);
   MakeNamedObjectListDirty3ds(db);

   InitChunk3ds(&ntri);
   ADD_ERROR_RETURN(ERR_PUT_FAIL);
   ntri->tag = N_TRI_OBJECT;
   AddChildOrdered3ds(nobj, ntri);

   if ((mesh->nvertices > 0) && (mesh->vertexarray != NULL))
   { /* Add the point array */
      PointArray *d;
      chunk3ds *temp = NULL;
      
      InitChunk3ds(&temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      temp->tag = POINT_ARRAY;
      d = InitChunkData3ds(temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      d->vertices = mesh->nvertices;
      d->pointlist = malloc(sizeof(point3ds)*d->vertices);
      if (d->pointlist == NULL) SET_ERROR_RETURN(ERR_NO_MEM);
      memcpy(d->pointlist, mesh->vertexarray, sizeof(point3ds)*d->vertices);
      AddChildOrdered3ds(ntri, temp);
   }

   if (mesh->ntextverts > 0)
   {
      TexVerts *d;
      chunk3ds *temp = NULL;
      
      InitChunk3ds(&temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      temp->tag = TEX_VERTS;
      d = InitChunkData3ds(temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      d->numcoords = mesh->ntextverts;
      d->textvertlist = malloc(sizeof(textvert3ds)*d->numcoords);
      if (d->textvertlist == NULL) SET_ERROR_RETURN(ERR_NO_MEM);
      memcpy(d->textvertlist, mesh->textarray, sizeof(textvert3ds)*d->numcoords);
      AddChildOrdered3ds(ntri, temp);
   }

   if (mesh->usemapinfo)
   {
      MeshTextureInfo *d;
      chunk3ds *temp;

      InitChunk3ds(&temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      temp->tag = MESH_TEXTURE_INFO;
      d = InitChunkData3ds(temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);

      d->maptype = mesh->map.maptype;
      d->xtiling = mesh->map.tilex;
      d->ytiling = mesh->map.tiley;      
      d->iconpos.x = mesh->map.cenx;
      d->iconpos.y = mesh->map.ceny;
      d->iconpos.z = mesh->map.cenz;
      d->iconscaling = mesh->map.scale;
      memcpy(d->xmatrix, mesh->map.matrix, sizeof(float3ds)*12);
      d->iconwidth = mesh->map.pw;
      d->iconheight = mesh->map.ph;
      d->cyliconheight = mesh->map.ch;
      AddChildOrdered3ds(ntri, temp);
   }
   
   if ((mesh->nvflags > 0) && (mesh->vflagarray != NULL))
   {
      PointFlagArray *d;
      chunk3ds *temp = NULL;
      
      InitChunk3ds(&temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      temp->tag = POINT_FLAG_ARRAY;
      d = InitChunkData3ds(temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      d->flags = mesh->nvflags;
      d->flaglist = malloc(sizeof(ushort3ds)*d->flags);
      if (d->flaglist == NULL) SET_ERROR_RETURN(ERR_NO_MEM);
      memcpy(d->flaglist, mesh->vflagarray, sizeof(ushort3ds)*d->flags);
      AddChildOrdered3ds(ntri, temp);
   }

   
   {
      MeshMatrix *d;
      chunk3ds *temp = NULL;

      InitChunk3ds(&temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      temp->tag = MESH_MATRIX;
      d = InitChunkData3ds(temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      memcpy(d->xmatrix, mesh->locmatrix, sizeof(float3ds)*12);
      AddChildOrdered3ds(ntri, temp);
   }
   

   {
      chunk3ds *temp = NULL;

      InitChunk3ds(&temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      temp->tag = MESH_COLOR;
      InitChunkData3ds(temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      ((MeshColor *)(temp->data))->color = mesh->meshcolor;
      AddChildOrdered3ds(ntri, temp);
   }

   if (mesh->nfaces > 0)
   {
      chunk3ds *farr = NULL;
      FaceArray *d;

      InitChunk3ds(&farr);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      farr->tag = FACE_ARRAY;
      d = InitChunkData3ds(farr);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      farr->data = d;
      d->faces = mesh->nfaces;
      d->facelist = malloc(sizeof(face3ds)*d->faces);
      if (d->facelist == NULL) SET_ERROR_RETURN(ERR_NO_MEM);
      memcpy(d->facelist, mesh->facearray, sizeof(face3ds)*d->faces);
      AddChildOrdered3ds(ntri, farr);

      if (mesh->nmats > 0)
      {
	 chunk3ds *matgroup;
	 ushort3ds x;
	 MshMatGroup *d;
	 
	 for (x = 0; x < mesh->nmats; x++)
	 {
	    matgroup = NULL;
	    InitChunk3ds(&matgroup);
	    ADD_ERROR_RETURN(ERR_PUT_FAIL);
	    matgroup->tag = MSH_MAT_GROUP;
	    d = InitChunkData3ds(matgroup);
	    ADD_ERROR_RETURN(ERR_PUT_FAIL);
	    d->matname = strdup(mesh->matarray[x].name);
	    d->faces = mesh->matarray[x].nfaces;
	    if (d->faces > 0)
	    {
	       d->facelist = malloc(sizeof(short3ds)*d->faces);
	       if (d->facelist == NULL) SET_ERROR_RETURN(ERR_NO_MEM);
	       memcpy(d->facelist, mesh->matarray[x].faceindex, sizeof(short3ds)*d->faces);
	    } else
	    {
	       d->facelist = NULL;
	    }
	    AddChildOrdered3ds(farr, matgroup);
	 }
      }
      
      if (mesh->smootharray != NULL)
      {
	 chunk3ds *smooth = NULL;
	 SmoothGroup *d;
	 
	 InitChunk3ds(&smooth);
	 ADD_ERROR_RETURN(ERR_PUT_FAIL);
	 smooth->tag = SMOOTH_GROUP;
	 d = InitChunkData3ds(smooth);
	 ADD_ERROR_RETURN(ERR_PUT_FAIL);

	 d->groups = mesh->nfaces;
	 d->grouplist = malloc(sizeof(long3ds)*d->groups);
	 if (d->grouplist == NULL) SET_ERROR_RETURN(ERR_NO_MEM);
	 memcpy(d->grouplist, mesh->smootharray, sizeof(long3ds)*d->groups);
	 AddChildOrdered3ds(farr, smooth);
      }
      
      if (mesh->useboxmap)
      {
	 chunk3ds *boxmap = NULL;
	 MshBoxmap *d;

	 InitChunk3ds(&boxmap);
	 ADD_ERROR_RETURN(ERR_PUT_FAIL);
	 boxmap->tag = MSH_BOXMAP;
	 d = InitChunkData3ds(boxmap);
	 ADD_ERROR_RETURN(ERR_PUT_FAIL);

	 for (i = 0; i < 6; i++)
	 {
	    d->matnames[i] = strdup(mesh->boxmap[i]);
	 }
	 AddChildOrdered3ds(farr, boxmap);
      }
   }
   
   if (mesh->procdata != NULL)
   {
      chunk3ds *procname, *procdata;
      ProcName *pname;
      IpasData *pdata;

      InitChunk3ds(&procname);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      InitChunk3ds(&procdata);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      procname->tag = PROC_NAME;
      procdata->tag = PROC_DATA;
      pname = InitChunkData3ds(procname);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      pdata = InitChunkData3ds(procdata);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      
      pname->name = strdup(mesh->procname);
      pdata->size = mesh->procsize;
      pdata->data = malloc(pdata->size);
      if (pdata->data == NULL) SET_ERROR_RETURN(ERR_NO_MEM);
      memcpy(pdata->data, mesh->procdata, pdata->size);
      AddChildOrdered3ds(ntri, procname);
      AddChildOrdered3ds(ntri, procdata);
   }

   if (mesh->ishidden)
   {
      chunk3ds *temp;
      InitChunk3ds(&temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      temp->tag = OBJ_HIDDEN;
      AddChildOrdered3ds(nobj, temp);
   }

   if (mesh->isvislofter)
   {
      chunk3ds *temp;
      InitChunk3ds(&temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      temp->tag = OBJ_VIS_LOFTER;
      AddChildOrdered3ds(nobj, temp);
   }

   if (mesh->ismatte)
   {
      chunk3ds *temp;
      InitChunk3ds(&temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      temp->tag = OBJ_MATTE;
      AddChildOrdered3ds(nobj, temp);
   }

   if (mesh->isnocast)
   {
      chunk3ds *temp;
      InitChunk3ds(&temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      temp->tag = OBJ_DOESNT_CAST;
      AddChildOrdered3ds(nobj, temp);
   }

   if (mesh->isfast)
   {
      chunk3ds *temp;
      InitChunk3ds(&temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      temp->tag = OBJ_FAST;
      AddChildOrdered3ds(nobj, temp);
   }

   if (mesh->isnorcvshad)
   {
      chunk3ds *temp;
      InitChunk3ds(&temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      temp->tag = OBJ_DONT_RCVSHADOW;
      AddChildOrdered3ds(nobj, temp);
   }

   if (mesh->isfrozen)
   {
      chunk3ds *temp;
      InitChunk3ds(&temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      temp->tag = OBJ_FROZEN;
      AddChildOrdered3ds(nobj, temp);
   }

   if ((mesh->useproc==True3ds) && (mesh->procdata != NULL))
   {
      chunk3ds *temp;
      InitChunk3ds(&temp);
      ADD_ERROR_RETURN(ERR_PUT_FAIL);
      temp->tag = OBJ_PROCEDURAL;
      AddChildOrdered3ds(nobj, temp);
   }

   if (xdata != NULL)
   {
      AddChildOrdered3ds(ntri, xdata);
   }
    }