/*========================================================================= * * Borders.c - Borders & Frontier management * * Version 1.0 * Revision date * *=======================================================================*/ #include #include "Borders.h" #include "conventi.h" #include "defines.h" #include "print.h" #include "MatStack.h" #include "ModLib.h" #include "SPOLoad.h" #include "SctSave.h" #include "Levels.h" //-------------------------------------------------------------------- /**************************************************************************** * Description: delete the border referece in hierarchy * * Parameters: hSprObj : root of the hierarchy * sParam : name of the current sector *--------------------------------------------------------------------------- * Revision date: Author: *****************************************************************************/ void MLT_vEraseBorderInHierarchy (MLT_tdxHandleToSuperObject hSprObj, char *sParam) { long i, lNbChild; xString sAction, sSectorName, sFile, sIdent; // matrix parameters lNbChild = 0; MLT_xPushMatrix(hSprObj->p_stMatrix); // check each child for (i=0; ilNbChild; i++ ) { // get super-object name SCR_fn_v_RdL0_SplitSectionName(hSprObj->sName, sFile, sAction, sIdent); // root super-object if( (strcmp(sAction, M_SuperObject) == 0) && (strcmp(sIdent, M_Root) == 0) ) { // get each sector SCR_fn_v_RdL0_SplitSectionName(hSprObj->d_hChild[i]->stSector.sName, sFile, sAction, sSectorName); if(strstr(sSectorName, M_SPO_) != NULL) { xString sTmp; sprintf(sTmp, "%s", sSectorName+strlen(M_SPO_)); // delete the string "SPO_" sprintf(sSectorName, "%s", sTmp); } } // sector super-object else sprintf(sSectorName, "%s", sParam); lNbChild++; // check if the object is a fronteer if(strstr(hSprObj->d_hChild[i]->sName, M_Frontier) != NULL) { // compute border if (!g_bRaymanII) MLT_vComputeAbsoluteBorder(hSprObj->d_hChild[i], sSectorName); else MLT_vComputeAbsoluteValuesOfBorder(hSprObj, i, sSectorName); // remove from hierarchy MLT_vDeleteHierarchy(hSprObj->d_hChild[i]); hSprObj->d_hChild[i] = NULL; lNbChild--; } // else iterate on next level else { MLT_vEraseBorderInHierarchy(hSprObj->d_hChild[i], sSectorName); } } MLT_xPopMatrix(); // clean the hierarchy for NULL children for(i=0; id_hChild[j] == NULL) j++; hTemp = hSprObj->d_hChild[j]; hSprObj->d_hChild[j] = NULL; hSprObj->d_hChild[i] = hTemp; } // update the number of children hSprObj->lNbChild = lNbChild; } /**************************************************************************** * Description: merge all sector's border to build a single one * * Parameters: hSprObj : root of the hierarchy *--------------------------------------------------------------------------- * Revision date: Author: *****************************************************************************/ void MLT_vMakeGoThroughInLib (MLT_tdxHandleToSuperObject hSprObj) { MLT_tdstGeometricObject **h_stObj; xString sAction, sIdent, sIdent2, sFile, sObjName; long i, j, lNbObj; // check each sector for (i=0; ilNbChild; i++) { // get sector name SCR_fn_v_RdL0_SplitSectionName(hSprObj->d_hChild[i]->stSector.sName, sFile, sAction, sIdent); sprintf(sIdent2,"%s_%s",M_NameGothrough, sIdent); sprintf(sFile,"%s.mod",g_sLevelFileIn); // compute corresponding section name SCR_fn_v_RdL0_ComputeSectionName(sObjName, sFile, M_Geometric, sIdent2); // find the coresponding object MLT_vRequestObjInLib(sObjName, &h_stObj, &lNbObj); // merge the object with the current border for(j=1; jsGeometric); if(p_stObj == NULL) { MLT_vOutput( C_ComRes_cErrorLine, "\nError : Can't load %s", hSprObj->sGeometric); return; } MLT_xPushMatrix(hSprObj->p_stMatrix); // get geometric name SCR_fn_v_RdL0_SplitSectionName(p_stObj->sName, sFile, sAction, sIdent); // separate type of border MLT_vSplitSectionInformation('_', sIdent, sType, sTemp); // separate destination sector MLT_vSplitSectionInformation('_', sTemp, sSectorDest, sAction); // remove "SPO_" prefix if(strstr(sSectorDest, M_SPO_) != NULL) { xString sTmp; sprintf(sTmp, "%s", sSectorDest+4); sprintf(sSectorDest, "%s", sTmp); } // check the destination sector if(!MLT_bIsGoodSector(sSectorDest)) { MLT_vOutput( C_ComRes_cErrorLine, "\nError : Bad sector's name %s in border %s", sSectorDest, p_stObj->sName); } // create border name (gothrough) sprintf(sIdent, "%s_%s", M_NameGothrough, sSector); // nom du border SCR_fn_v_RdL0_ComputeSectionName(p_stObj->sName, sFile, M_Geometric, sIdent); sprintf(p_stObj->sComment, ""); // compute absolute vertices for(i=0; ixNbPoints; i++) { MLT_xMulMatrixVertex(p_stObj->d_stListOfPoints+i, g_p_stCurrentMatrix, p_stObj->d_stListOfPoints+i); } p_cString = strstr(sType, M_FronRever); // reversible fronteer -> do symmetric if ((p_cString != NULL) || ((p_cString = strstr(sType, M_NewFronRever))!=NULL)) { MLT_tdstGeometricObject *p_stObjRev; *p_cString = 0; MLT_vInformSectorHasBorder(g_hRoot, sSectorDest, sSector); MLT_vMakeReverseObjInLib(p_stObj, &p_stObjRev, sSectorDest); if (strstr(sType, M_Fermeture) == NULL) MLT_vPointedSectorOfBorder(p_stObjRev, sSector); } // update sector links form border MLT_vInformSectorHasBorder(g_hRoot, sSector, sSectorDest); // it's not a closed border if (strstr(sType, M_Fermeture) == NULL) MLT_vPointedSectorOfBorder(p_stObj, sSectorDest); MLT_xPopMatrix(); } /**************************************************************************** * Description: compute the border as a bounding box * * Parameters: hSprObj : root super object * i : sector index * sSector : sector name *--------------------------------------------------------------------------- * Revision date: Author: *****************************************************************************/ void MLT_vComputeAbsoluteValuesOfBorder(MLT_tdxHandleToSuperObject hSprObj, int i, char *sSector) { MLT_tdstGeometricObject *p_stObj; xString sAction, sIdent, sFile; xString sSectorDest; //get the geometrical object p_stObj = MLT_pFindInLib(hSprObj->d_hChild[i]->sGeometric); if(p_stObj == NULL) { MLT_vOutput( C_ComRes_cErrorLine, "\nError : Can't load %s", hSprObj->d_hChild[i]->sGeometric); return; } MLT_xPushMatrix(hSprObj->d_hChild[i]->p_stMatrix); // get geometric name SCR_fn_v_RdL0_SplitSectionName(p_stObj->sName, sFile, sAction, sIdent); // create border name (gothrough) sprintf(sIdent, "%s_%s", M_NameGothrough, sSector); // nom du border SCR_fn_v_RdL0_ComputeSectionName(p_stObj->sName, sFile, M_Geometric, sIdent); sprintf(p_stObj->sComment, ""); // compute absolute vertices for(i=0; ixNbPoints; i++) { MLT_xMulMatrixVertex(p_stObj->d_stListOfPoints+i, g_p_stCurrentMatrix, p_stObj->d_stListOfPoints+i); } // compute the minimum and maximum of the border, after modified the absolute values MLT_vComputeMinMaxPointOfBorder (p_stObj, &hSprObj->stSector.stPointMin, &hSprObj->stSector.stPointMax); // update sector links form border MLT_vInformSectorHasBorder(g_hRoot, sSector, sSectorDest); MLT_xPopMatrix(); } /**************************************************************************** * Description: update sector links according to border * * Parameters: hRoot : root super object * sSectorDest : destination sector * sSectorOrg : origin sector *--------------------------------------------------------------------------- * Revision date: Author: *****************************************************************************/ void MLT_vInformSectorHasBorder(MLT_tdxHandleToSuperObject hRoot, char *sSectorDest, char *sSectorOrg) { long i; char *sTmp; for (i=0; ilNbChild; i++) { sTmp = strstr(hRoot->d_hChild[i]->sName, "_sct"); if(sTmp && (stricmp(sTmp+1, sSectorDest) == 0) ) { // update border flag hRoot->d_hChild[i]->stSector.bIsVirtual = FALSE; // update graphic link sprintf(hRoot->d_hChild[i]->stSector.a_sSecteurGraphic[hRoot->d_hChild[i]->stSector.lNbSecteurGraphic], "%s", sSectorOrg); hRoot->d_hChild[i]->stSector.lNbSecteurGraphic++; // update activity link sprintf(hRoot->d_hChild[i]->stSector.a_sSecteurActivity[hRoot->d_hChild[i]->stSector.lNbSecteurActivity], "%s", sSectorOrg); hRoot->d_hChild[i]->stSector.lNbSecteurActivity++; // update collision link sprintf(hRoot->d_hChild[i]->stSector.a_sSecteurCollision[hRoot->d_hChild[i]->stSector.lNbSecteurCollision], "%s", sSectorOrg); hRoot->d_hChild[i]->stSector.lNbSecteurCollision++; } } } /**************************************************************************** * Description: update sector pointer into the border * * Parameters: p_stObj : fronteer object * sNameSector : destination sector *--------------------------------------------------------------------------- * Revision date: Author: *****************************************************************************/ void MLT_vPointedSectorOfBorder (MLT_tdstGeometricObject *p_stObj, char *sNameSector) { long i; for(i=0; ixNbElements; i++) { switch(p_stObj->d_xListOfElementsTypes[i]) { // update sector name in indexed triangle case MLT_C_xElementIndexedTriangles: { MLT_tdstElementIndexedTriangles *p_stLocal; xString sFile; p_stLocal = (MLT_tdstElementIndexedTriangles*)(p_stObj->d_stListOfElements[i]); sprintf(p_stLocal->sMaterial,""); sprintf(sFile,"%s.sct", g_sLevelFileIn); SCR_fn_v_RdL0_ComputeSectionName(p_stLocal->sSectorName, sFile, M_Sector, sNameSector); } break; // update sector name in face map descriptor case MLT_C_xElementFaceMapDescriptors: { long j; MLT_tdstElementFaceMapDescriptors *p_stLocal; p_stLocal = (MLT_tdstElementFaceMapDescriptors*)(p_stObj->d_stListOfElements[i]); for(j=0; jxNbFaces; j++) { sprintf(p_stLocal->d_stListOfFacesQuadrupled[j].hFaceMapDescriptor->sMaterial,""); SCR_fn_v_RdL0_ComputeSectionName(p_stLocal->d_stListOfFacesQuadrupled[j].hFaceMapDescriptor->sSprObjName, "*", M_SuperObject, sNameSector); } } break; // other types : not implementes case MLT_C_xElementSprites: break; case MLT_C_xElementTMeshes: break; case MLT_C_xElementPoints: break; case MLT_C_xElementLines: break; case MLT_C_xElementSpheres: break; case MLT_C_xElementAlignedBoxes: break; case MLT_C_xElementCones: break; } } } /**************************************************************************** * Description: compute minmax points of a border * * Parameters: p_stObj : border object * p_stMin : min point * p_stMax : max point *--------------------------------------------------------------------------- * Revision date: Author: *****************************************************************************/ void MLT_vComputeMinMaxPointOfBorder (MLT_tdstGeometricObject *p_stObj, MTH3D_tdstVector *p_stMin, MTH3D_tdstVector *p_stMax) { int i; // check coordinates of each point for (i = 0; i < p_stObj->xNbPoints; i++) { // check x coordinate if (p_stObj->d_stListOfPoints[i].xX < p_stMin->xX) p_stMin->xX = p_stObj->d_stListOfPoints[i].xX; if (p_stObj->d_stListOfPoints[i].xX > p_stMax->xX) p_stMax->xX = p_stObj->d_stListOfPoints[i].xX; // check y coordinate if (p_stObj->d_stListOfPoints[i].xY < p_stMin->xY) p_stMin->xY = p_stObj->d_stListOfPoints[i].xY; if (p_stObj->d_stListOfPoints[i].xY > p_stMax->xY) p_stMax->xY = p_stObj->d_stListOfPoints[i].xY; // check z coordinate if (p_stObj->d_stListOfPoints[i].xZ < p_stMin->xZ) p_stMin->xZ = p_stObj->d_stListOfPoints[i].xZ; if (p_stObj->d_stListOfPoints[i].xZ > p_stMax->xZ) p_stMax->xZ = p_stObj->d_stListOfPoints[i].xZ; } } /**************************************************************************** * Description: compute minmax points of a border, updating with absolute position * * Parameters: p_stObj : border object * p_stMin : min point * p_stMax : max point * p_stMatrix : absolute matrix *--------------------------------------------------------------------------- * Revision date: Author: *****************************************************************************/ void MLT_vComputeMinMaxPointWithMatrix (MLT_tdstGeometricObject *p_stObj, MTH3D_tdstVector *p_stMin, MTH3D_tdstVector *p_stMax, MLT_tdstMatrix *p_stMatrix) { MTH3D_tdstVector p_stPoint; int i; // check coordinates of each point for (i = 0; i < p_stObj->xNbPoints; i++) { // get the absolute coordinates MLT_xMulMatrixVertex(&p_stPoint, p_stMatrix, p_stObj->d_stListOfPoints+i); // check x coordinate if (p_stPoint.xX < p_stMin->xX) p_stMin->xX = p_stPoint.xX; if (p_stPoint.xX > p_stMax->xX) p_stMax->xX = p_stPoint.xX; // check y coordinate if (p_stPoint.xY < p_stMin->xY) p_stMin->xY = p_stPoint.xY; if (p_stPoint.xY > p_stMax->xY) p_stMax->xY = p_stPoint.xY; // check z coordinate if (p_stPoint.xZ < p_stMin->xZ) p_stMin->xZ = p_stPoint.xZ; if (p_stPoint.xZ > p_stMax->xZ) p_stMax->xZ = p_stPoint.xZ; } } /**************************************************************************** * Description: decode a string : return the sub string before and after the caractere p * * Parameters: p : character to search for * p_sSection : initial string * p_sFirst : string before p * p_sTemp : string after p *--------------------------------------------------------------------------- * Revision date: Author: *****************************************************************************/ void MLT_vSplitSectionInformation (char p, char *p_sSection, char *p_sFirst, char *p_sTemp) { char *p_char; // iit first string sprintf(p_sFirst, "%s", p_sSection); p_char = p_sFirst; // cut first string on p if ((p_char=strchr(p_sFirst, p))!=NULL) *p_char = 0; // update second string if(strlen(p_sFirst) == strlen(p_sSection)) sprintf(p_sTemp, ""); else sprintf(p_sTemp, "%s", ++p_char); } /**************************************************************************** * Description: attach the surface whn it belongs to several sectors * * Parameters: hRoot : sector super-object * sSprObj : surface super-object * sDirSave : destination directory *--------------------------------------------------------------------------- * Revision date: Author: *****************************************************************************/ BOOL MLT_bAttachSurfaceToSector(MLT_tdxHandleToSuperObject hRoot, MLT_tdxHandleToSuperObject hSprObj, char *sDirSave) { xString sTemp, sSector; char *sSurface; sSurface = strstr(hSprObj->sName, M_Surface); // decoding the name of the target sectors MLT_vSplitSectionInformation('|', sSurface, sSector, sTemp); while(strlen(sTemp) != 0) { MLT_vSplitSectionInformation('|', sTemp, sSector, sTemp); if(MLT_bIsGoodSector(sSector)) { MLT_vAddSurfaceToSector(hRoot, hSprObj->sName, sSector, sDirSave); } else { MLT_vOutput( C_ComRes_cErrorLine, "\nError : Bad sector's name %s in surface %s", sSector, sSurface); } } return TRUE; } /**************************************************************************** * Description: add the surface to the sector structure * * Parameters: hRoot : root super-object * sSprObj : surface super-object * sSector : sector name * sDirSave : destination directory *--------------------------------------------------------------------------- * Revision date: Author: *****************************************************************************/ void MLT_vAddSurfaceToSector(MLT_tdxHandleToSuperObject hRoot, char *sSprObj, char *sSector, char *sDirSave) { long i, j, k; char *sSurface; xString sFile, sAction, sIdent, sMatrix, sFile2, sAction2, sIdent2; MLT_tdxHandleToSuperObject hSprSurface; // test the good surface sSurface = strstr(sSprObj, M_Surface); if (sSurface == NULL) return; // recover the SuperObjet surface sprintf(sFile, "%s%s.srf", sDirSave, g_sLevelFileIn); hSprSurface = MLT_hFindInHierarchy(sSurface, hRoot); // cover the sectors for(i=0; ilNbChild; i++) { if(strlen(hRoot->d_hChild[i]->stSector.sName) == 0) continue; SCR_fn_v_RdL0_SplitSectionName(hRoot->d_hChild[i]->stSector.sName, sFile, sAction, sIdent); // test the good sector if(stricmp(sIdent, sSector) == 0) { MLT_tdstMatrix *p_stMat, stMat1, stMat2; xString sTemp1, sTemp2; // recover the surface's matrix sprintf(sMatrix, "%s", hSprSurface->p_stMatrix->sName); p_stMat = hSprSurface->p_stMatrix; // sort the surface by growing altitude for(j=0; jd_hChild[i]->stSector.lNbSurface; j++) { if( p_stMat->stTranslation.xZ > hRoot->d_hChild[i]->stSector.a_stSurface[j].stMatrix.stTranslation.xZ ) { stMat1 = hRoot->d_hChild[i]->stSector.a_stSurface[j].stMatrix; sprintf(sTemp1, "%s", hRoot->d_hChild[i]->stSector.a_stSurface[j].sGeometric); for(k=j; kd_hChild[i]->stSector.lNbSurface; k++) { stMat2 = hRoot->d_hChild[i]->stSector.a_stSurface[k+1].stMatrix; hRoot->d_hChild[i]->stSector.a_stSurface[k+1].stMatrix = stMat1; stMat1 = stMat2; sprintf(sTemp2, "%s", hRoot->d_hChild[i]->stSector.a_stSurface[k+1].sGeometric); sprintf(hRoot->d_hChild[i]->stSector.a_stSurface[k+1].sGeometric, "%s", sTemp1); sprintf(sTemp1, "%s", sTemp2); } break; } } // store the surface MLT_vComputeAltitudeSrf(p_stMat, hSprSurface->sGeometric); hRoot->d_hChild[i]->stSector.a_stSurface[j].stMatrix = *p_stMat; SCR_fn_v_RdL0_SplitSectionName(hSprSurface->sGeometric, sFile2, sAction2, sIdent2); sprintf(hRoot->d_hChild[i]->stSector.a_stSurface[j].sGeometric, "%s", sIdent2); hRoot->d_hChild[i]->stSector.lNbSurface++; break; } } } /**************************************************************************** * Description: compute the altitude of the surface. * * Parameters: p_stMat : absolute position * sSurface : surface name *--------------------------------------------------------------------------- * Revision date: Author: *****************************************************************************/ void MLT_vComputeAltitudeSrf(MLT_tdstMatrix *p_stMat, char *sSurface) { MLT_tdstGeometricObject *p_stSrf; float dAltitude; long i; // get surface object p_stSrf = MLT_pFindInLib(sSurface); if(p_stSrf == NULL) { MLT_vOutput( C_ComRes_cErrorLine, "\nError : Can't load %s", sSurface); return; } // the z composante of the surface's vertices must be zero dAltitude = p_stSrf->d_stListOfPoints[0].xZ; for(i=0; ixNbPoints; i++) { p_stSrf->d_stListOfPoints[i].xZ -= dAltitude; } p_stMat->stTranslation.xZ += dAltitude; }