#include #include #include #include #include // we need BSPIMD defined if we want to read & use the BSP imd files // Define this if we are compile ivis for the BSP generating tool, also for PIEBIN tool //#define PIETOOL #ifdef PIETOOL #define BSPIMD #define SAVEIMD #endif #include "ivisdef.h" #include "imd.h" #include "bug.h" #include "tex.h" #include "ivispatch.h" #ifdef PIETOOL #include "bspimd.h" #endif //************************************************************************* //************************************************************************* #define MAX_SHAPE_RADIUS 160 //************************************************************************* //************************************************************************* // Output BSP Tree to a file // This stuff saves out the BSP tree as generated by the BSP tool // // Because of the complexities of the BSP generation tool. The IMD is stored in a different // format when it is generated compared to when it is loaded and used in the game. // This means that when saving out a BSP tree from the tool other functions need to be included // most of them are in ptrlist.c which is no longer included in ivis. See the source for BSPIMD // for this file. Becareful not to confuse this with the same named file in deliverance/src which // might or might not be the same. // #ifdef PIETOOL // Prototypes for the linked list handling void *list_GetFirst(PSBSPPTRLIST pList); void *list_GetNext(PSBSPPTRLIST pList, void *pData); int BSPPolys, BSPNodes; PSBSPTREENODE BSPNodeTable[iV_IMD_MAX_POLYS]; iIMDPoly *BSPPolyTable[iV_IMD_MAX_POLYS]; void OutputTriangleList(FILE *fp, PSBSPPTRLIST TriList) { iIMDPoly *Triangle; int TriNum=0; int d; if (TriList == NULL) return; Triangle = list_GetFirst(TriList); while (Triangle != NULL) { fprintf(fp,"\t%8x %d",Triangle->flags,Triangle->npnts); for (d=0; dnpnts; d++) fprintf(fp," %d",Triangle->pindex[d]); if (Triangle->flags & iV_IMD_TEXANIM) { if (Triangle->pTexAnim == NULL) { debug( LOG_NEVER, "No TexAnim pointer!\n" ); } else { fprintf(fp," %d %d %d %d", Triangle->pTexAnim->nFrames, Triangle->pTexAnim->playbackRate, Triangle->pTexAnim->textureWidth, Triangle->pTexAnim->textureHeight); } } // if textured write texture uv's if (Triangle->flags & (iV_IMD_TEX | iV_IMD_PSXTEX)) { for (d = 0; d < Triangle->npnts; d++) { fprintf(fp," %d %d",Triangle->vrt[d].u,Triangle->vrt[d].v); } } fprintf(fp, "\n"); Triangle = list_GetNext(TriList, Triangle); } } void CountTriangleList(PSBSPPTRLIST TriList) { iIMDPoly *Triangle; assert(BSPPolysiNumNodes == 0) return; Triangle=list_GetFirst(TriList); while (Triangle != NULL) { BSPPolyTable[BSPPolys] = Triangle; BSPPolys++; Triangle = list_GetNext(TriList, Triangle); } } void CountBSPPolys(PSBSPTREENODE psNode) { if (psNode == NULL) { return; } BSPNodeTable[BSPNodes] = psNode; BSPNodes++; CountBSPPolys(psNode->link[LEFT]); CountTriangleList(psNode->psTriSameDir); CountTriangleList(psNode->psTriOppoDir); CountBSPPolys(psNode->link[RIGHT]); } void OutputBSPPolys(FILE *fp, PSBSPTREENODE psNode) { if (psNode == NULL) { return; } OutputBSPPolys(fp, psNode->link[LEFT]); OutputTriangleList(fp, psNode->psTriSameDir); OutputTriangleList(fp, psNode->psTriOppoDir); OutputBSPPolys(fp, psNode->link[RIGHT]); } int HuntNodeList(PSBSPTREENODE psNode) { int i; for (i = 0; i < BSPNodes; i++) { if (BSPNodeTable[i] == psNode) { return i; } } return -1; } int HuntPolyList(iIMDPoly *Poly) { int i; for (i = 0; i < BSPPolys; i++) { if (BSPPolyTable[i] == Poly) { return i; } } return 999; } void DumpTriangleList(FILE *fp,PSBSPPTRLIST TriList) { iIMDPoly *Triangle; assert(BSPPolyslink[LEFT])); DumpTriangleList( fp, psNode->psTriSameDir ); DumpTriangleList( fp, psNode->psTriOppoDir ); fprintf(fp,"%d\n",HuntNodeList(psNode->link[RIGHT])); OutputBSPNodes( fp, psNode->link[LEFT]); OutputBSPNodes( fp, psNode->link[RIGHT]); } /* Count Polys & Nodes in bsp - also makes a table of them */ int GetBSPPolyCount(PSBSPTREENODE psNode, int *NodeCount) { BSPPolys=0; BSPNodes=0; CountBSPPolys(psNode); *NodeCount=BSPNodes; return BSPPolys; } #endif #ifdef SAVEIMD // new code the write out the connectors ! void _imd_save_connectors(FILE *fp, iIMDShape *s) { iVector *p; int i; if (s->nconnectors != 0) { fprintf(fp,"CONNECTORS %d\n",s->nconnectors); p = s->connectors; for (i=0; inconnectors; i++, p++) { fprintf(fp,"\t%d %d %d\n", p->x,p->y,p->z); } } } //************************************************************************* //*** save IMD file //* //* pre shape successfully loaded //* //* params filename = name of file to save to including .IMD extention //* s = pointer to IMD shape //* //* returns TRUE -> ok, FLASE -> error //* //****** iBool iV_IMDSave(STRING *filename, iIMDShape *s, BOOL PieIMD) { FILE *fp; iIMDShape *sp; iIMDPoly *poly; int nlevel, i, j, d; if ((fp = fopen(filename,"w")) == NULL) { return FALSE; } if (PieIMD==TRUE) { fprintf(fp,"%s %d\n",PIE_NAME,PIE_VER); } else { fprintf(fp,"%s %d\n",IMD_NAME,IMD_VER); } fprintf(fp,"TYPE %x\n",s->flags); // if textured write tex page file info if (s->flags & iV_IMD_XTEX) { fprintf(fp,"TEXTURE %d %s %d %d\n",iV_TEXTYPE(s->texpage), iV_TEXNAME(s->texpage),iV_TEXWIDTH(s->texpage), iV_TEXHEIGHT(s->texpage)); } // find number of levels in shape for (nlevel=0, sp = s; sp != NULL; sp = sp->next, nlevel++) ; fprintf(fp,"LEVELS %d\n",nlevel); for (sp = s, i=0; inext, i++) { fprintf(fp,"LEVEL %d\n",(i+1)); fprintf(fp,"POINTS %d\n",sp->npoints); // write shape points for (j = 0; j < sp->npoints; j++) { fprintf(fp,"\t%d %d %d\n",sp->points[j].x,sp->points[j].y, sp->points[j].z); } // write shape polys #ifdef PIETOOL if (sp->BSPNode==NULL) #endif { fprintf(fp,"POLYGONS %d\n",sp->npolys); for (poly = sp->polys, j=0; jnpolys; j++, poly++) { fprintf(fp,"\t%8x %d",poly->flags,poly->npnts); for (d=0; dnpnts; d++) { fprintf(fp," %d",poly->pindex[d]); } if (poly->flags & iV_IMD_TEXANIM) { if (poly->pTexAnim == NULL) { debug( LOG_3D, "No TexAnim pointer!\n" ); } else { fprintf(fp," %d %d %d %d", poly->pTexAnim->nFrames, poly->pTexAnim->playbackRate, poly->pTexAnim->textureWidth, poly->pTexAnim->textureHeight); } } // if textured write texture uv's if (poly->flags & (iV_IMD_TEX | iV_IMD_PSXTEX)) { for (d=0; dnpnts; d++) { fprintf(fp," %d %d",poly->vrt[d].u,poly->vrt[d].v); } } fprintf(fp,"\n"); } } #ifdef PIETOOL else { int NodeCount; fprintf(fp,"POLYGONS %d\n",GetBSPPolyCount(sp->BSPNode,&NodeCount) ); OutputBSPPolys(fp,sp->BSPNode); // fprintf(fp,"BSP %d\n",NodeCount ); OutputBSPNodes(fp,sp->BSPNode); } #endif } _imd_save_connectors(fp,s); // Write out the connectors if they exist fclose(fp); return TRUE; } #endif //************************************************************************* //*** print IMD file info //* //* pre shape successfully loaded //* //* params s = pointer to IMD shape //* //****** void iV_IMDDebug(iIMDShape *s) { iIMDShape *sp; iIMDPoly *poly; int nlevel, i, j, d; iV_DEBUG0("iV_IMDSave = file info *****************************\n"); iV_DEBUG1("SHAPE\nflags\t%x\n",s->flags); iV_DEBUG1("texpage\t%d\n",s->texpage); iV_DEBUG1("oradius\t%d\n",s->oradius); iV_DEBUG1("sradius\t%d\n",s->sradius); iV_DEBUG1("radius\t%d\n",s->radius); iV_DEBUG2("xmin, xmax\t%d, %d\n",s->xmin,s->xmax); iV_DEBUG2("ymin, ymax\t%d, %d\n",s->ymin,s->ymax); iV_DEBUG2("zmin, zmax\t%d, %d\n",s->zmin,s->zmax); iV_DEBUG3("ocen\t%d %d %d\n",s->ocen.x,s->ocen.y,s->ocen.z); iV_DEBUG1("npoints\t%d\n",s->npoints); iV_DEBUG1("npolys\t%d\n",s->npolys); iV_DEBUG1("points\t%p\n",s->points); iV_DEBUG1("polys\t%p\n",s->polys); iV_DEBUG1("ntexanims\t%d\n",s->ntexanims); iV_DEBUG1("texanims\t%p\n",s->ntexanims); iV_DEBUG1("next\t%p\n",s->next); // find number of levels in shape for (nlevel=0, sp = s; sp != NULL; sp = sp->next, nlevel++) ; iV_DEBUG1("nlevels\t%d\n",nlevel); for (sp = s, i=0; inext, i++) { iV_DEBUG1("POINTS %d\n",sp->npoints); for (j=0; jnpoints; j++) iV_DEBUG3("\t%d %d %d\n",sp->points[j].x,sp->points[j].y, sp->points[j].z); iV_DEBUG1("POLYGONS %d\n",sp->npolys); // write shape polys for (poly = sp->polys, j=0; jnpolys; j++, poly++) { iV_DEBUG2("\t%8x %d",poly->flags,poly->npnts); for (d=0; dnpnts; d++) iV_DEBUG1(" %d",poly->pindex[d]); // if textured write texture uv's if (poly->flags & iV_IMD_TEX) { for (d=0; dnpnts; d++) iV_DEBUG2(" %d %d",poly->vrt[d].u,poly->vrt[d].v); } iV_DEBUG0("\n"); } } } //************************************************************************* //*** free IMD shape memory //* //* pre shape successfully allocated //* //* params shape = pointer to IMD shape //* //****** void iV_IMDRelease(iIMDShape *s) { int i; iIMDShape *d; if (s) { if (s->flags & iV_IMD_BINARY) { iV_HeapFree(s,0); return; } if (s->points) { iV_HeapFree(s->points,s->npoints * sizeof(iVector)); } if (s->connectors) { iV_HeapFree(s->connectors,s->nconnectors * sizeof(iVector)); } if (s->BSPNode) { FREE(s->BSPNode); // I used MALLOC() so i'm going to use FREE() } if (s->polys) { for (i = 0; i < s->npolys; i++) { if (s->polys[i].pindex) { iV_HeapFree(s->polys[i].pindex,s->polys[i].npnts * sizeof(int)); } if (s->polys[i].pTexAnim) { iV_HeapFree(s->polys[i].pTexAnim,sizeof(iTexAnim)); } if (s->polys[i].vrt) { iV_HeapFree(s->polys[i].vrt,s->polys[i].npnts * sizeof(iVertex)); } } iV_HeapFree(s->polys,s->npolys * sizeof(iIMDPoly)); } iV_DEBUG0("imd[IMDRelease] = release successful\n"); d = s->next; iV_HeapFree(s,sizeof(iIMDShape)); iV_IMDRelease(d); } }