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; } } } }
ulong3ds GetMeshMatCount3ds(chunk3ds *current) { chunk3ds *datachunk; ushort3ds meshmatcount=0; FindChunk3ds(current, MSH_MAT_GROUP, &datachunk); while(datachunk != NULL) { meshmatcount++; FindNextChunk3ds(datachunk->sibling, MSH_MAT_GROUP, &datachunk); } return(meshmatcount); }
/* Retreaves the background settings from the chunk database */ void GetBackground3ds(database3ds *db, /* the database being searched */ background3ds **bgnd /* the background settings destination. If *atmo is NULL, then a new structure will be allocated */ ) { chunk3ds *mdata, *chunk; if (db == NULL || bgnd == NULL) SET_ERROR_RETURN(ERR_INVALID_ARG); /* Find the MDATA chunk */ FindChunk3ds(db->topchunk, MDATA, &mdata); /* only continue with structure filling if an MDATA chunk is found */ if (mdata != NULL) { InitBackground3ds(bgnd); /* Search for bitmap chunk */ FindChunk3ds(mdata, BIT_MAP, &chunk); if (chunk != NULL) { BitMap *bitmap; /* Read the chunk information */ ReadChunkData3ds(chunk); /* Alias the data */ bitmap = chunk->data; /* Copy the bitmap filename to the structure */ if (bitmap->bitmap != NULL) (*bgnd)->bitmap.name = strdup(bitmap->bitmap); else (*bgnd)->bitmap.name = strdup(""); } FindChunk3ds(mdata, SOLID_BGND, &chunk); if (chunk != NULL) { chunk3ds *cc; FindChunk3ds(chunk, COLOR_F, &cc); if (cc != NULL) { ColorF *cd; cd = ReadChunkData3ds(cc); (*bgnd)->solid.color.r = cd->red; (*bgnd)->solid.color.g = cd->green; (*bgnd)->solid.color.b = cd->blue; } FindChunk3ds(chunk, LIN_COLOR_F, &cc); if (cc != NULL) { LinColorF *cd; cd = ReadChunkData3ds(cc); (*bgnd)->solid.color.r = cd->red; (*bgnd)->solid.color.g = cd->green; (*bgnd)->solid.color.b = cd->blue; } } FindChunk3ds(mdata, V_GRADIENT, &chunk); if (chunk != NULL) { chunk3ds *topcolor, *midcolor, *botcolor; /* The COLOR_F chunks are the old, non-gamma corrected colors */ ReadChunkData3ds(chunk); (*bgnd)->vgradient.gradpercent = ((VGradient *)(chunk->data))->gradpercent; FindChunk3ds(chunk, COLOR_F, &topcolor); if (topcolor != NULL) { ReadChunkData3ds(topcolor); (*bgnd)->vgradient.top.r = ((ColorF *)(topcolor->data))->red; (*bgnd)->vgradient.top.g = ((ColorF *)(topcolor->data))->green; (*bgnd)->vgradient.top.b = ((ColorF *)(topcolor->data))->blue; FindNextChunk3ds(topcolor->sibling, COLOR_F, &midcolor); if (midcolor != NULL) { ReadChunkData3ds(midcolor); (*bgnd)->vgradient.mid.r = ((ColorF *)(midcolor->data))->red; (*bgnd)->vgradient.mid.g = ((ColorF *)(midcolor->data))->green; (*bgnd)->vgradient.mid.b = ((ColorF *)(midcolor->data))->blue; FindNextChunk3ds(midcolor->sibling, COLOR_F, &botcolor); if (botcolor != NULL) { ReadChunkData3ds(botcolor); (*bgnd)->vgradient.bottom.r = ((ColorF *)(botcolor->data))->red; (*bgnd)->vgradient.bottom.g = ((ColorF *)(botcolor->data))->green; (*bgnd)->vgradient.bottom.b = ((ColorF *)(botcolor->data))->blue; } } } /* If the newer, gamma correct colors are available, then use them instead */ FindChunk3ds(chunk, LIN_COLOR_F, &topcolor); if (topcolor != NULL) { ReadChunkData3ds(topcolor); (*bgnd)->vgradient.top.r = ((ColorF *)(topcolor->data))->red; (*bgnd)->vgradient.top.g = ((ColorF *)(topcolor->data))->green; (*bgnd)->vgradient.top.b = ((ColorF *)(topcolor->data))->blue; FindNextChunk3ds(topcolor->sibling, LIN_COLOR_F, &midcolor); if (midcolor != NULL) { ReadChunkData3ds(midcolor); (*bgnd)->vgradient.mid.r = ((ColorF *)(midcolor->data))->red; (*bgnd)->vgradient.mid.g = ((ColorF *)(midcolor->data))->green; (*bgnd)->vgradient.mid.b = ((ColorF *)(midcolor->data))->blue; FindNextChunk3ds(midcolor->sibling, LIN_COLOR_F, &botcolor); if (botcolor != NULL) { ReadChunkData3ds(botcolor); (*bgnd)->vgradient.bottom.r = ((ColorF *)(botcolor->data))->red; (*bgnd)->vgradient.bottom.g = ((ColorF *)(botcolor->data))->green; (*bgnd)->vgradient.bottom.b = ((ColorF *)(botcolor->data))->blue; } } } } /* Search for use_bitmap, use_solid_bgnd, or use_v_gradient */ FindChunk3ds(mdata, USE_BIT_MAP, &chunk); if (chunk != NULL) { (*bgnd)->bgndused = UseBitmapBgnd; } else { FindChunk3ds(mdata, USE_SOLID_BGND, &chunk); if (chunk != NULL) { (*bgnd)->bgndused = UseSolidBgnd; } else { FindChunk3ds(mdata, USE_V_GRADIENT, &chunk); if (chunk != NULL) { (*bgnd)->bgndused = UseVGradientBgnd; } else { (*bgnd)->bgndused = NoBgnd; } } } } }
/*------------------------------------------------------------------------ | | GetLightEntryChunk3ds | Fills out the *light structure with the light pointed to | by *chunk | +-----------------------------------------------------------------------*/ void GetLightEntryChunk3ds(chunk3ds *chunk, light3ds **light) { chunk3ds *nobj, *dlite, *spot, *current; if (light == NULL) SET_ERROR_RETURN(ERR_INVALID_ARG); FindNextChunk3ds(chunk->children, N_DIRECT_LIGHT, &dlite); if (dlite == NULL) SET_ERROR_RETURN(ERR_WRONG_OBJECT); CopyChunk3ds(chunk, &nobj); FindChunk3ds(nobj, N_DIRECT_LIGHT, &dlite); FindChunk3ds(nobj, DL_SPOTLIGHT, &spot); if (dlite != NULL) { NamedObject *nobjd; NDirectLight *ndl; /* Initilize **light properly */ if (spot == NULL) InitLight3ds(light); else InitSpotlight3ds(light); /* Copy the object name */ nobjd = ReadChunkData3ds(nobj); strcpy((*light)->name, nobjd->name); /* Copy the light postion */ ndl = ReadChunkData3ds(dlite); (*light)->pos = ndl->lightpos; /* scan all the chunks the light contains */ for (current = dlite->children; current != NULL; current = current->sibling) { switch(current->tag) { case COLOR_F: /* The color of the light */ { ColorF *d; d = ReadChunkData3ds(current); (*light)->color.r = d->red; (*light)->color.g = d->green; (*light)->color.b = d->blue; } break; case COLOR_24: /* The color of the (*light) */ { Color24 *d; d = ReadChunkData3ds(current); (*light)->color.r = (float3ds)d->red / 255.0F; (*light)->color.g = (float3ds)d->green / 255.0F; (*light)->color.b = (float3ds)d->blue / 255.0F; } break; case DL_MULTIPLIER: /* The light intensity */ { DlMultiplier *d; d = ReadChunkData3ds(current); (*light)->multiplier = d->multiple; } break; case DL_INNER_RANGE: { DlInnerRange *d; d = ReadChunkData3ds(current); /* assuming since there is a value it is on */ (*light)->attenuation.inner = d->range; } break; case DL_OUTER_RANGE: { DlOuterRange *d; d = ReadChunkData3ds(current); /* assuming since there is a value it is on */ (*light)->attenuation.outer = d->range; } break; case DL_EXCLUDE: { DlExclude *d; char3ds *name; d = ReadChunkData3ds(current); if ((*light)->exclude == NULL) InitNameList3ds(&((*light)->exclude), 0); name = d->name; d->name = NULL; AddToNameList3ds(&((*light)->exclude), name); free(name); } break; case DL_OFF: (*light)->dloff = True3ds; break; case DL_ATTENUATE: (*light)->attenuation.on = True3ds; break; } } /*--- DL_SPOTLIGHT chunk */ if (spot != NULL){ DlSpotlight *d; /*--- Read spotlight data */ d = ReadChunkData3ds(spot); (*light)->spot->target = d->spotlighttarg; (*light)->spot->hotspot = d->hotspotangle; (*light)->spot->falloff = d->falloffangle; /* scan all the chunks the spotlight contains */ for (current = spot->children; current != NULL; current = current->sibling) { switch(current->tag) { case DL_SPOT_ROLL: { DlSpotRoll *d; d = ReadChunkData3ds(current); (*light)->spot->roll = d->angle; } break; case DL_LOCAL_SHADOW: (*light)->spot->shadows.cast = True3ds; break; case DL_LOCAL_SHADOW2: { DlLocalShadow2 *d; d = ReadChunkData3ds(current); (*light)->spot->shadows.bias = d->localshadowbias; (*light)->spot->shadows.filter = d->localshadowfilter; (*light)->spot->shadows.mapsize = d->localshadowmapsize; (*light)->spot->shadows.local = True3ds; } break; case DL_SHADOWED: (*light)->spot->shadows.cast = True3ds; break; case DL_SPOT_RECTANGULAR: (*light)->spot->cone.type = Rectangular; break; case DL_SEE_CONE: (*light)->spot->cone.show = True3ds; break; case DL_SPOT_OVERSHOOT: (*light)->spot->cone.overshoot = True3ds; break; case DL_SPOT_ASPECT: { DlSpotAspect *d; d = ReadChunkData3ds(current); (*light)->spot->aspect = d->aspect; } break; case DL_RAY_BIAS: { DlRayBias *d; d = ReadChunkData3ds(current); (*light)->spot->shadows.raybias = d->bias; } break; case DL_RAYSHAD: { (*light)->spot->shadows.type = UseRayTraceShadow; break; } case DL_SPOT_PROJECTOR: { DlSpotProjector *d; d = ReadChunkData3ds(current); (*light)->spot->projector.bitmap = d->name; (*light)->spot->projector.use = True3ds; d->name = NULL; } break; } } } } ReleaseChunk3ds(&nobj); }
void GetMeshEntryChunk3ds(chunk3ds *chunk, mesh3ds **mesh) { chunk3ds *nobj=NULL, *datachunk=NULL, *ntrichunk, *current; void *data = NULL; ushort3ds meshmatcount=0; if (chunk == NULL || mesh == NULL) SET_ERROR_RETURN(ERR_INVALID_ARG); FindNextChunk3ds(chunk->children, N_TRI_OBJECT, &ntrichunk); if (ntrichunk == NULL) SET_ERROR_RETURN(ERR_WRONG_OBJECT); InitMeshObj3ds(mesh,0,0,0); /* Copy the mesh chunk into a temporary chunk */ CopyChunk3ds(chunk, &nobj); ON_ERROR_RETURN; /* Get the N_TRI_OBJECT part out of it. */ FindNextChunk3ds(nobj->children, N_TRI_OBJECT, &ntrichunk); /* Get the mesh name. */ { NamedObject *d; d = ReadChunkData3ds(nobj); strcpy((*mesh)->name, d->name); } for (current = ntrichunk->children; current != NULL; current = current->sibling) { switch(current->tag) { case POINT_ARRAY: { PointArray *d; d = ReadChunkData3ds(current); (*mesh)->nvertices = d->vertices; (*mesh)->vertexarray = d->pointlist; d->pointlist = NULL; break; } case POINT_FLAG_ARRAY: { PointFlagArray *flags; flags = ReadChunkData3ds(current); (*mesh)->nvflags = flags->flags; (*mesh)->vflagarray = flags->flaglist; flags->flaglist = NULL; break; } case FACE_ARRAY: { FaceArray *d; d = ReadChunkData3ds(current); (*mesh)->nfaces = d->faces; (*mesh)->facearray = d->facelist; d->facelist = NULL; if (current->children != NULL) { /* begin search for MESH_MAT_GROUP and SMOOTH_GROUP */ chunk3ds *facearraychunk=current; /* create a list of all mesh mat groups */ FindChunk3ds(facearraychunk, MSH_MAT_GROUP, &datachunk); if (datachunk != NULL) { ulong3ds index; meshmatcount = (ushort3ds)GetMeshMatCount3ds(datachunk); (*mesh)->nmats = meshmatcount; (*mesh)->matarray = calloc(meshmatcount, sizeof(objmat3ds)); for (index = 0; index < (*mesh)->nmats; index++) { MshMatGroup *omat = NULL; omat = ReadChunkData3ds(datachunk); strcpy((*mesh)->matarray[index].name, omat->matname); (*mesh)->matarray[index].nfaces = omat->faces; (*mesh)->matarray[index].faceindex = omat->facelist; omat->facelist = NULL; FindNextChunk3ds(datachunk->sibling, MSH_MAT_GROUP, &datachunk); } } FindNextChunk3ds(facearraychunk->children, SMOOTH_GROUP, &datachunk); if (datachunk != NULL) { SmoothGroup *sm; long3ds smelements; sm = ReadChunkData3ds(datachunk); smelements = (datachunk->size - 6)/LongSize3ds; (*mesh)->smootharray = sm->grouplist; sm->grouplist = NULL; } FindNextChunk3ds(facearraychunk->children, MSH_BOXMAP, &datachunk); if (datachunk != NULL) { MshBoxmap *bm; ushort3ds i; ReadChunkData3ds(datachunk); bm = datachunk->data; for (i = 0; i < 6; i++) strcpy((*mesh)->boxmap[i], bm->matnames[i]); (*mesh)->useboxmap = True3ds; } } break; } case TEX_VERTS: { TexVerts *tv; ReadChunkData3ds(current); tv = current->data; (*mesh)->ntextverts = tv->numcoords; (*mesh)->textarray = tv->textvertlist; tv->textvertlist = NULL; break; } case MESH_MATRIX: { ReadChunkData3ds(current); data = current->data; memcpy((*mesh)->locmatrix ,((MeshMatrix *)data)->xmatrix, 12*sizeof(float3ds)); break; } case MESH_TEXTURE_INFO: { (*mesh)->usemapinfo = True3ds; ReadChunkData3ds(current); data = current->data; (*mesh)->map.maptype = ((MeshTextureInfo *)data)->maptype; (*mesh)->map.tilex = ((MeshTextureInfo *)data)->xtiling; (*mesh)->map.tiley = ((MeshTextureInfo *)data)->ytiling; (*mesh)->map.cenx = ((MeshTextureInfo *)data)->iconpos.x; (*mesh)->map.ceny = ((MeshTextureInfo *)data)->iconpos.y; (*mesh)->map.cenz = ((MeshTextureInfo *)data)->iconpos.z; (*mesh)->map.scale = ((MeshTextureInfo *)data)->iconscaling; memcpy((*mesh)->map.matrix , ((MeshTextureInfo *)data)->xmatrix, 12*sizeof(float3ds)); (*mesh)->map.pw = ((MeshTextureInfo *)data)->iconwidth; (*mesh)->map.ph = ((MeshTextureInfo *)data)->iconheight; (*mesh)->map.ch = ((MeshTextureInfo *)data)->cyliconheight; break; } case PROC_NAME: { ReadChunkData3ds(current); data = current->data; strcpy((*mesh)->procname, ((ProcName *)data)->name); break; } case PROC_DATA: { IpasData *d; d = ReadChunkData3ds(current); (*mesh)->procsize = d->size; (*mesh)->procdata = d->data; d->data = NULL; /* CCJ */ break; } case MESH_COLOR: { ReadChunkData3ds(current); (*mesh)->meshcolor = ((MeshColor *)(current->data))->color; break; } } } FindNextChunk3ds(nobj->children, OBJ_HIDDEN, ¤t); if (current != NULL) (*mesh)->ishidden = True3ds; else (*mesh)->ishidden = False3ds; FindNextChunk3ds(nobj->children, OBJ_VIS_LOFTER, ¤t); if (current != NULL) (*mesh)->isvislofter = True3ds; else (*mesh)->isvislofter = False3ds; FindNextChunk3ds(nobj->children, OBJ_DOESNT_CAST, ¤t); if (current != NULL) (*mesh)->isnocast = True3ds; else (*mesh)->isnocast = False3ds; FindNextChunk3ds(nobj->children, OBJ_MATTE, ¤t); if (current != NULL) (*mesh)->ismatte = True3ds; else (*mesh)->ismatte = False3ds; FindNextChunk3ds(nobj->children, OBJ_FAST, ¤t); if (current != NULL) (*mesh)->isfast = True3ds; else (*mesh)->isfast = False3ds; FindNextChunk3ds(nobj->children, OBJ_FROZEN, ¤t); if (current != NULL) (*mesh)->isfrozen = True3ds; else (*mesh)->isfrozen = False3ds; FindNextChunk3ds(nobj->children, OBJ_DONT_RCVSHADOW, ¤t); if (current != NULL) (*mesh)->isnorcvshad = True3ds; else (*mesh)->isnorcvshad = False3ds; FindNextChunk3ds(nobj->children, OBJ_PROCEDURAL, ¤t); if (current != NULL) (*mesh)->useproc = True3ds; else (*mesh)->useproc = False3ds; ReleaseChunk3ds(&nobj); }