/*---------------------------------------------------------------- | | 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, ¤t); /* 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); } }
/* 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, ¤t); /* 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); } }