reman3/Rayman_X/cpa/Appli/Max23Dos/src/Borders.c

641 lines
21 KiB
C

/*=========================================================================
*
* Borders.c - Borders & Frontier management
*
* Version 1.0
* Revision date
*
*=======================================================================*/
#include <Windows.h>
#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; i<hSprObj->lNbChild; 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; i<lNbChild; i++)
{
MLT_tdxHandleToSuperObject hTemp;
int j;
j=i;
while(hSprObj->d_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; i<hSprObj->lNbChild; 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; j<lNbObj; j++)
{
MLT_vMergeObjects(h_stObj[0], h_stObj[j]);
MLT_vEraseMergeObjInLib(h_stObj[j]);
}
// free useless objects
if(lNbObj != 0)
free(h_stObj);
}
}
/****************************************************************************
* Description: compute the border in the global repere (with absolute coordinate)
*
* Parameters: hSprObj : fronteer super object
* sSector : sector name
*---------------------------------------------------------------------------
* Revision date: Author:
*****************************************************************************/
void MLT_vComputeAbsoluteBorder(MLT_tdxHandleToSuperObject hSprObj, char *sSector)
{
MLT_tdstGeometricObject *p_stObj;
xString sAction, sSectorDest, sTemp, sType, sIdent, sFile;
char *p_cString;
int i;
// find corresponding object
p_stObj = MLT_pFindInLib(hSprObj->sGeometric);
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; i<p_stObj->xNbPoints; 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; i<p_stObj->xNbPoints; 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; i<hRoot->lNbChild; 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; i<p_stObj->xNbElements; 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; j<p_stLocal->xNbFaces; 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; i<hRoot->lNbChild; 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; j<hRoot->d_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; k<hRoot->d_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; i<p_stSrf->xNbPoints; i++)
{
p_stSrf->d_stListOfPoints[i].xZ -= dAltitude;
}
p_stMat->stTranslation.xZ += dAltitude;
}