JD2022-TU1/main/extern/Camcam/LIBS/Mixer/Particules.cpp

1177 lines
32 KiB
C++

#include "SCENE.h"
u32 COL_MulColor(u32 A,u32 B);
#define FLOAT_RAND (2*((float)rand() - RAND_MAX/2)/RAND_MAX)
#define VAL_RAND(x,y) (x*(1+y*FLOAT_RAND))
#define BARYCENTER(x,y,c,n) (((x)*((n)-(c))+(y)*(c))/(n))
#define EPSILON 0.0001
#define RATIO 32
typedef float M33[3][3];
void MuliplyM(M33 *M1, M33 *M2, M33 *M)
{
int i, j, k;
for (i=0; i<3; i++)
{
for (j=0; j<3; j++)
{
(*M)[i][j] = 0.0f;
for (k=0; k<3; k++)
{
(*M)[i][j] += (*M1)[i][k]*(*M2)[k][j];
}
}
}
}
void ZeroM(M33 *M)
{
int i, j;
for (i=0; i<3; i++)
{
for (j=0; j<3; j++)
{
(*M)[i][j] = 0.0f;
}
}
}
void CopyM(M33 *MSRC, M33 *MDST)
{
int i, j;
for (i=0; i<3; i++)
{
for (j=0; j<3; j++)
{
(*MDST)[i][j] = (*MSRC)[i][j];
}
}
}
Vector RotateVector(Vector v, float angle)
{
float angleR;
Vector resV;
M33 M;
M33 M1;
M33 M2;
angleR = angle*FLOAT_RAND;
ZeroM(&M);
M[0][0] = 1.0f;
M[1][1] = cos(angleR);
M[1][2] = -sin(angleR);
M[2][1] = -M[1][2];
M[2][2] = M[1][1];
CopyM(&M, &M2);
angleR = angle*FLOAT_RAND;
ZeroM(&M1);
M1[0][0] = cos(angleR);
M1[0][2] = -sin(angleR);
M1[1][1] = 1.0f;
M1[2][0] = -M1[0][2];
M1[2][2] = M1[0][0];
MuliplyM(&M1, &M2, &M);
CopyM(&M, &M2);
angleR = angle*FLOAT_RAND;
ZeroM(&M1);
M1[0][0] = cos(angleR);
M1[0][1] = -sin(angleR);
M1[1][0] = -M1[0][1];
M1[1][1] = M1[0][0];
M1[2][2] = 1.0f;
MuliplyM(&M1, &M2, &M);
resV.x = M[0][0]*v.x + M[0][1]*v.y + M[0][2]*v.z;
resV.y = M[1][0]*v.x + M[1][1]*v.y + M[1][2]*v.z;
resV.z = M[2][0]*v.x + M[2][1]*v.y + M[2][2]*v.z;
return resV;
}
BOOL SegmentCollision(Vector *ptSrc, Vector *ptDst, Vector *speed);
#define NB_RAND_ELMTS (2*1024) // 2* -> X,Y
static BOOL RandInit = 0;
static float RandTab[NB_RAND_ELMTS];
inline void GetPointMass(Mesh *mesh, MAP *massTexture, int faceIdx, int ptIdx, float *massR)
{
int xPos, yPos;
xPos = mesh->PointsUV[mesh->Indexes_UV[faceIdx].I[ptIdx]].x * (massTexture->SX - 1);
xPos = xPos % massTexture->SX;
yPos = mesh->PointsUV[mesh->Indexes_UV[faceIdx].I[ptIdx]].y * (massTexture->SY - 1);
yPos = yPos % massTexture->SY;
if (massR)
*massR= ((float)((massTexture->GetValue(xPos + yPos*massTexture->PITCH) >> 16) & 255))/255.0f;
}
inline float GetFaceMass(Mesh *mesh, MAP *massTexture, int faceIdx, float *massPointOut)
{
float massPt[3];
float massFace;
float *massPoint;
if (massPointOut == NULL)
{
massPoint = massPt;
for (int ptIdx=0; ptIdx<3; ptIdx++)
{
GetPointMass(mesh, massTexture, faceIdx, ptIdx, &massPoint[ptIdx]);
massPoint[ptIdx] *= 8;
}
} else {
massPoint = massPointOut;
}
// We test Here the best mass compute method
massFace = (massPoint[0]+massPoint[1]+massPoint[2])/3;
/********* LINEAR *********
return massFace;
/********* LINEAR *********/
/******** QUADRIC *********/
return massFace*massFace;
/******** QUADRIC *********/
/******* GEOMETRIC ********
return pow(massPoint[0]*massPoint[1]*massPoint[2], 1.0f/3);
/******* GEOMETRIC ********/
}
float GetMeshSurface(Mesh *mesh, MATRIX *global, float *surfaceList, MAP *massTexture)
{
u32 faceIdx, ptIdx;
FaceIndex *Indexes = mesh->Indexes;
Vector pts[3];
float surface = 0;
float face;
float ptsMass;
ptsMass = 1.0f;
for (faceIdx = 0; faceIdx<mesh->NumberOfFaces; faceIdx++, Indexes++)
{
if (global)
{
for (ptIdx=0; ptIdx<3; ptIdx++)
pts[ptIdx] = *global**(mesh->Points + Indexes->I[ptIdx]);
} else
{
for (ptIdx=0; ptIdx<3; ptIdx++)
pts[ptIdx] = *(mesh->Points + Indexes->I[ptIdx]);
}
if (massTexture)
ptsMass = GetFaceMass(mesh, massTexture, faceIdx, NULL);
face = ((pts[1] - pts[0])^(pts[2] - pts[0])).Norm()*ptsMass/2.0f;
if (surfaceList)
surfaceList[faceIdx] = face;
surface += face;
}
return surface;
}
int GetPointRepartition(Vector *points, Vector *normals, Vector *ulist, Vector *uvtList, int number, Mesh *mesh, MATRIX *global, float density, float *surfaceList, MAP *massTexture, int initFace, int initRand, u32 seed)
{
u32 faceIdx, ptIdx;
FaceIndex *Indexes;
Vector pts[3];
Vector ptsW[3];
Vector ptsU[3];
Vector ptsUV[3];
float globalSurface = 0;
float stepSurface = 0;
Vector faceNormal;
u32 currentFace = initFace;
float ptsMass[3];
Vector ptsMassUV[3];
float scaleFactor;
if (currentFace >= mesh->NumberOfFaces)
currentFace = 0;
Indexes = mesh->Indexes + currentFace;
if (!RandInit)
{
float *randTabPtr = RandTab;
if (seed != -1) srand(seed);
else srand(timeGetTime());
for (int rdIdx = 0; rdIdx<NB_RAND_ELMTS; rdIdx+=2, randTabPtr+=2)
{
*randTabPtr = ((float)rand())/RAND_MAX;
*(randTabPtr+1) = ((float)rand())/RAND_MAX;
if ((*randTabPtr + *(randTabPtr+1)) > 1.0)
{
*randTabPtr = 1.0f - *randTabPtr;
*(randTabPtr+1) = 1.0f - *(randTabPtr+1);
}
}
RandInit = 1;
}
int randPos = initRand;
int currentPoint = 0;
ptsMass[0] = ptsMass[1] = ptsMass[2] = 1.0f;
for (faceIdx = 0; faceIdx<mesh->NumberOfFaces; faceIdx++, Indexes++, currentFace++)
{
if (currentFace >= mesh->NumberOfFaces)
{
currentFace = 0;
Indexes = mesh->Indexes;
}
for (ptIdx=0; ptIdx<3; ptIdx++)
{
ptsMassUV[ptIdx] = mesh->PointsUV[mesh->Indexes_UV[faceIdx].I[ptIdx]];
}
if (massTexture)
{
for (ptIdx=0; ptIdx<3; ptIdx++)
{
GetPointMass(mesh, massTexture, faceIdx, ptIdx, &ptsMass[ptIdx]);// + 1; // !!!! +1 pour eviter les effets de bord
ptsMass[ptIdx] *= 8;
}
}
globalSurface += surfaceList[currentFace];
if (stepSurface < globalSurface)
{
for (ptIdx=0; ptIdx<3; ptIdx++)
{
pts[ptIdx] = *global**(mesh->Points + Indexes->I[ptIdx]);
ptsW[ptIdx]= pts[ptIdx]*ptsMass[ptIdx];
ptsUV[ptIdx]= ptsMassUV[ptIdx]*ptsMass[ptIdx];
}
if (ulist)
{
for (ptIdx=0; ptIdx<3; ptIdx++)
ptsU[ptIdx] = *(mesh->PointsUV + Indexes->I[ptIdx]);
}
faceNormal = (pts[1] - pts[0])^(pts[2] - pts[0]);
faceNormal.Normalize();
while (stepSurface < globalSurface)
{
scaleFactor = 1.0f/(ptsMass[0] + ((ptsMass[1]-ptsMass[0])*RandTab[randPos]) + ((ptsMass[2]-ptsMass[0])*RandTab[randPos+1]));
points[currentPoint] = ptsW[0] + ((ptsW[1]-ptsW[0])*RandTab[randPos]) + ((ptsW[2]-ptsW[0])*RandTab[randPos+1]);
points[currentPoint] *= scaleFactor;
normals[currentPoint] = faceNormal;
if (uvtList)
{
uvtList[currentPoint] = ptsUV[0] + ((ptsUV[1]-ptsUV[0])*RandTab[randPos]) + ((ptsUV[2]-ptsUV[0])*RandTab[randPos+1]);
uvtList[currentPoint] *= scaleFactor;
}
if (ulist)
{
Vector newFaceNormal = (pts[1] - pts[0])*(ptsU[1].y - ptsU[0].y) + (pts[2] - pts[0])*(ptsU[2].y - ptsU[0].y);
newFaceNormal.Normalize();
if (newFaceNormal.x != 0 || newFaceNormal.y != 0 || newFaceNormal.z != 0)
newFaceNormal.Normalize();
else
newFaceNormal = Vector(1,0,0);
ulist[currentPoint] = newFaceNormal;
}
if (randPos >= NB_RAND_ELMTS) randPos = 0;
currentPoint++;
randPos+=2;
stepSurface += density;
if (currentPoint >= number)
return currentPoint;
}
}
}
return currentPoint;
}
void PGENERATOR_OBJ::ProcessParticuleSon(Particules *particulePtr)
{
if (sonMode == 0) return;
if (sonMode == 1 /* On Diing */ &&
particulePtr->alive) return;
if (sonMode == 2 /* On Collide */ &&
!particulePtr->collide) return;
if (!particuleSonPtr) return;
particuleSonPtr->Origin = particulePtr->coordsDest;
particuleSonPtr->Direction = particulePtr->speedDest;
particuleSonPtr->Direction.Normalize();
particuleSonPtr->GenerateFix(1, 0);
}
BOOL PGENERATOR_OBJ::ProcessParticule(int time, Particules *particule)
{
Vector v;
int ParticuleCurLife;
Vector dstCoord;
Vector dstCoordIn;
if (!particule->alive) return false;
if (time <= 0) return true;
if (curTime < particule->creationTime)
ParticuleCurLife = 0;
else
ParticuleCurLife = curTime - particule->creationTime;
if (particule->life != -1 && ParticuleCurLife > particule->life)
goto onDiing;
if (particule->collide)
{
if (forces.collisionFriction != 1.0f)
{
if (forces.collisionFriction < 0)
goto onDiing;
particule->speed *= forces.collisionFriction;
}
if (forces.collisionRandAngle != 0)
{
particule->speed = RotateVector(particule->speed, forces.collisionRandAngle);
}
ProcessParticuleSon(particule);
}
if (forces.Gravity.x != 0 || forces.Gravity.y != 0 || forces.Gravity.z != 0)
{
particule->speed += forces.Gravity*((float)time/1000);
}
if (forces.Frictions != 0.0f)
{
particule->speed *= pow((double)(1-forces.Frictions), (double)time);
}
if (forces.WindForce != 0.0f &&
(forces.WindDirection.x != 0 || forces.WindDirection.y != 0 || forces.WindDirection.z != 0))
{
memset(&v, 0, sizeof(v));
if (forces.WindDirection.x > 0.0f && particule->speed.x < forces.WindDirection.x)
{
v.x = forces.WindForce*time*forces.WindDirection.x;
if (v.x > forces.WindDirection.x - particule->speed.x)
v.x = forces.WindDirection.x - particule->speed.x;
}
if (forces.WindDirection.x < 0.0f && particule->speed.x > forces.WindDirection.x)
{
v.x = forces.WindForce*time*forces.WindDirection.x;
if (v.x < forces.WindDirection.x - particule->speed.x)
v.x = forces.WindDirection.x - particule->speed.x;
}
if (forces.WindDirection.y > 0.0f && particule->speed.y < forces.WindDirection.y)
{
v.y = forces.WindForce*time*forces.WindDirection.y;
if (v.y > forces.WindDirection.y - particule->speed.y)
v.y = forces.WindDirection.y - particule->speed.y;
}
if (forces.WindDirection.y < 0.0f && particule->speed.y > forces.WindDirection.y)
{
v.y = forces.WindForce*time*forces.WindDirection.y;
if (v.y < forces.WindDirection.y - particule->speed.y)
v.y = forces.WindDirection.y - particule->speed.y;
}
if (forces.WindDirection.z > 0.0f && particule->speed.z < forces.WindDirection.z)
{
v.z = forces.WindForce*time*forces.WindDirection.z;
if (v.z > forces.WindDirection.z - particule->speed.z)
v.z = forces.WindDirection.z - particule->speed.z;
}
if (forces.WindDirection.z < 0.0f && particule->speed.z > forces.WindDirection.z)
{
v.z = forces.WindForce*time*forces.WindDirection.z;
if (v.z < forces.WindDirection.z - particule->speed.z)
v.z = forces.WindDirection.z - particule->speed.z;
}
particule->speed += v;
}
if (forces.RotationSpeed != 0.0f || forces.RotationRand != 0.0f)
{
particule->rotAngle += time*VAL_RAND(forces.RotationSpeed, forces.RotationRand)/1000;
if (particule->rotAngle < 0)
particule->rotAngle = particule->rotAngle + 360;
}
if (forces.GrowFor != 0 && ParticuleCurLife < forces.GrowFor)
{
particule->scaleFactor = BARYCENTER(forces.GrowForInit, forces.GrowForEnd, ParticuleCurLife, forces.GrowFor);
} else if (forces.FadeFor != 0 && particule->life > 0 && (particule->life - ParticuleCurLife) < forces.FadeFor)
{
int TimeToDie = (particule->life - ParticuleCurLife);
particule->scaleFactor = BARYCENTER(forces.FadeForEnd, forces.FadeForInit, TimeToDie, forces.FadeFor);
} else if (forces.GrowForEnd != forces.FadeForInit)
{
int TimeTotal = particule->life - forces.GrowFor - forces.FadeFor;
int TimeElapsed = ParticuleCurLife - forces.GrowFor;
if (TimeTotal > 0 && TimeElapsed < TimeTotal)
particule->scaleFactor = BARYCENTER(forces.GrowForEnd, forces.FadeForInit, TimeElapsed, TimeTotal);
else
particule->scaleFactor = forces.GrowForEnd;
} else
particule->scaleFactor = 1.0f;
if (forces.GrowForColor != 0 && ParticuleCurLife < forces.GrowForColor)
{
particule->RGBA = BARYCENTER( forces.GrowForColorInit & 0xFF, forces.GrowForColorEnd & 0xFF, ParticuleCurLife, forces.GrowForColor) << 24 |
(BARYCENTER((forces.GrowForColorInit >> 8) & 0xFF, (forces.GrowForColorEnd >> 8) & 0xFF, ParticuleCurLife, forces.GrowForColor) << 16) |
(BARYCENTER((forces.GrowForColorInit >> 16) & 0xFF, (forces.GrowForColorEnd >> 16) & 0xFF, ParticuleCurLife, forces.GrowForColor) << 8) |
(BARYCENTER((forces.GrowForColorInit >> 24) & 0xFF, (forces.GrowForColorEnd >> 24) & 0xFF, ParticuleCurLife, forces.GrowForColor) << 0);
} else if (forces.FadeForColor != 0 && particule->life > 0 && (particule->life - ParticuleCurLife) < forces.FadeForColor)
{
int TimeToDie = (particule->life - ParticuleCurLife);
particule->RGBA = BARYCENTER( forces.FadeForColorEnd & 0xFF, forces.FadeForColorInit & 0xFF, TimeToDie, forces.FadeForColor) << 24 |
(BARYCENTER((forces.FadeForColorEnd >> 8) & 0xFF, (forces.FadeForColorInit >> 8) & 0xFF, TimeToDie, forces.FadeForColor) << 16) |
(BARYCENTER((forces.FadeForColorEnd >> 16) & 0xFF, (forces.FadeForColorInit >> 16) & 0xFF, TimeToDie, forces.FadeForColor) << 8) |
(BARYCENTER((forces.FadeForColorEnd >> 24) & 0xFF, (forces.FadeForColorInit >> 24) & 0xFF, TimeToDie, forces.FadeForColor) << 0);
} else if (forces.GrowForColorEnd != forces.FadeForColorInit)
{
int TimeTotal = particule->life - forces.GrowForColor - forces.FadeForColor;
int TimeElapsed = ParticuleCurLife - forces.GrowForColor;
if (TimeTotal > 0 && TimeElapsed < TimeTotal)
particule->RGBA = BARYCENTER( forces.GrowForColorEnd & 0xFF, forces.FadeForColorInit & 0xFF, TimeElapsed, TimeTotal) << 24 |
(BARYCENTER((forces.GrowForColorEnd >> 8) & 0xFF, (forces.FadeForColorInit >> 8) & 0xFF, TimeElapsed, TimeTotal) << 16) |
(BARYCENTER((forces.GrowForColorEnd >> 16) & 0xFF, (forces.FadeForColorInit >> 16) & 0xFF, TimeElapsed, TimeTotal) << 8) |
(BARYCENTER((forces.GrowForColorEnd >> 24) & 0xFF, (forces.FadeForColorInit >> 24) & 0xFF, TimeElapsed, TimeTotal) << 0);
else
particule->scaleFactor = -1;
} else
particule->RGBA = (((forces.GrowForColorEnd ) & 0xFF) << 24) |
(((forces.GrowForColorEnd >> 8 ) & 0xFF) << 16) |
(((forces.GrowForColorEnd >> 16) & 0xFF) << 8 ) |
(((forces.GrowForColorEnd >> 24) & 0xFF) << 0 ) ;
if (forces.AnimSpeed != 0)
{
particule->textureIdx = particule->textureIdxBase + (curTime - particule->creationTime)/forces.AnimSpeed;
if (particule->textureIdx >= nbInGrid)
{
if (forces.AnimRepeat)
particule->textureIdx = particule->textureIdx % nbInGrid;
else
particule->textureIdx = nbInGrid - 1;
}
}
particule->coordsDest = particule->coords + particule->speed*(((float)time)/1000);
particule->speedDest = particule->speed;
particule->collide = 0;
return true;
onDiing:
particule->alive = 0;
ProcessParticuleSon(particule);
return false;
}
void PGENERATOR_OBJ::Init()
{
for (int i=0; i<nbParticules; i++)
if (particulesTab[i].luaCollideCallBack)
CC_free(particulesTab[i].luaCollideCallBack);
if (particulesTab)
CC_free(particulesTab);
particulesTab = NULL;
if (OriginList)
CC_free(OriginList);
OriginList = NULL;
if (DirectionList)
CC_free(DirectionList);
DirectionList = NULL;
particulesTab = (Particules *)CC_malloc(maxParticules*sizeof(Particules));
memset(particulesTab, 0, maxParticules*sizeof(Particules));
if (options & 8)
{
OriginList = (Vector *)CC_malloc(genNumber*sizeof(Vector));
DirectionList = (Vector *)CC_malloc(genNumber*sizeof(Vector));
}
nbParticules = 0;
curParticule = -1;
pgTime = timeGetTime();
pgTimeUnused = 0;
particuleSonPtr = NULL;
nbInGrid = TextureGrid.cx*TextureGrid.cy;
}
void PGENERATOR_OBJ::Process(int elapsedTime)
{
int partIdx;
Particules *currentPart;
if (!alive) return;
alive = false;
currentPart = particulesTab;
for (partIdx=0; partIdx<nbParticules; partIdx++, currentPart++)
{
if (ProcessParticule(elapsedTime, currentPart))
alive = true;
}
}
int PGENERATOR_OBJ::GenerateSingle(Vector center, Vector direction, int elapsedTime)
{
Particules *currentPart;
curParticule = (curParticule + 1) % maxParticules;
if (nbParticules < maxParticules) nbParticules++;
currentPart = particulesTab + curParticule;
currentPart->alive = 1;
if (particuleLife < 0)
currentPart->life = -1;
else
currentPart->life = VAL_RAND(particuleLife, particuleLifeRand);
currentPart->creationTime = curTime - elapsedTime;
currentPart->coords = center;
currentPart->speed = RotateVector(direction, genAngleAllowed)*VAL_RAND(genPower, genPowerRand);
if (genSizeRand >= 0 || !genWidth)
{
currentPart->width = VAL_RAND(genWidth, genSizeRand);
currentPart->height = VAL_RAND(genHeight, genSizeRand);
} else
{
currentPart->width = VAL_RAND(genWidth, -genSizeRand);
currentPart->height = currentPart->width*genHeight/genWidth;
}
currentPart->collide= 0;
if (forces.AnimInit != 0)
{
if (forces.AnimInit == -1)
{
currentPart->textureIdx = nbInGrid*rand()/RAND_MAX;
} else {
TextureIdx += forces.AnimInit;
if (TextureIdx >= nbInGrid)
TextureIdx = TextureIdx % nbInGrid;
currentPart->textureIdx = TextureIdx;
}
currentPart->textureIdxBase = currentPart->textureIdx;
} else
currentPart->textureIdxBase = 0;
currentPart->rotAngle = forces.RotationInit;
currentPart->rotAngle += (forces.RotationInit2 - forces.RotationInit)*rand()/RAND_MAX;
ProcessParticule(elapsedTime, currentPart);
return curParticule;
}
void PGENERATOR_OBJ::GenerateFix(int nbPToMake, int life)
{
int partIdx, partIdxIn;
BOOL fromMesh = options & 8;
alive = true;
if (nbPToMake*genNumber > maxParticules)
nbPToMake = maxParticules/genNumber;
for (partIdx=0; partIdx<nbPToMake; partIdx++)
{
for (partIdxIn=0; partIdxIn<genNumber; partIdxIn++)
{
if (fromMesh)
GenerateSingle(OriginList[partIdxIn], DirectionList[partIdxIn], life);
else
GenerateSingle(Origin, Direction, life);
}
}
}
void PGENERATOR_OBJ::GenerateDyn(int elapsedTime)
{
int partIdx, partIdxIn;
float genSpeedIn;
int nbPToMake;
int elapsedTimeIn;
int elapsedTimeGen = elapsedTime + pgTimeUnused;
BOOL fromMesh = options & 8;
if (particuleRepeat || nbParticules < maxParticules)
{
genSpeedIn = VAL_RAND(genSpeed, genSpeedRand);
nbPToMake = (int)(elapsedTimeGen * genSpeedIn / 1000);
pgTimeUnused = elapsedTimeGen - ((float)nbPToMake * 1000 / genSpeedIn);
if (nbPToMake*genNumber > maxParticules)
{
nbPToMake = maxParticules/genNumber;
elapsedTime = nbPToMake*1000/genSpeedIn;
}
alive = true;
} else
return;
if (!particuleRepeat && (nbParticules + nbPToMake) > maxParticules)
{
nbPToMake = maxParticules - nbParticules;
elapsedTime = nbPToMake*1000/genSpeedIn;
}
for (partIdx=0; partIdx<nbPToMake; partIdx++)
{
elapsedTimeIn = (nbPToMake-partIdx)*elapsedTime/nbPToMake;
for (partIdxIn=0; partIdxIn<genNumber; partIdxIn++)
{
if (fromMesh)
GenerateSingle(OriginList[partIdxIn], DirectionList[partIdxIn], elapsedTimeIn);
else
GenerateSingle(Origin, Direction, elapsedTimeIn);
}
}
}
BOOL SetOriginDirection(PGENERATOR_OBJ *PGen, SmallScene *SmSc, float IVal, float JVal, float KVal)
{
MATRIX WM;
int ObjectREF = 0;
_3D_Object *pObj;
if (SmSc == NULL)
return false;
if (PGen->ObjectName[0])
{
ObjectREF = SmSc->ObjectNameDico.IsExist(PGen->ObjectName);
if (ObjectREF == -1 && !strstr(PGen->ObjectName, ".OBJ"))
{
strcat(PGen->ObjectName, ".OBJ");
ObjectREF = SmSc->ObjectNameDico.IsExist(PGen->ObjectName);
}
if (ObjectREF != -1)
{
ObjectREF = SmSc->ObjectNameDico.mpst_Dico[ObjectREF].AssociatedValue;
}
if (ObjectREF == -1)
ObjectREF = 0;
}
pObj = SmSc->ObjectsPtrs[ObjectREF];
WM = pObj->GlobalMatrix;
PGen->Origin = WM.T;
PGen->Origin += pObj->GlobalMatrix.I * pObj->Pivot.x;
PGen->Origin += pObj->GlobalMatrix.J * pObj->Pivot.y;
PGen->Origin += pObj->GlobalMatrix.K * pObj->Pivot.z;
if (IVal == 0 && JVal == 0 && KVal == 0)
PGen->Direction = WM.I;
else
PGen->Direction = WM.I*IVal + WM.J*JVal + WM.K*KVal;
return true;
}
u32 WORLD::LoadPGenerator(s8 *Name, s8 *fileName, s8 *SceneName, s8 *ObjectName, s8 *MassTextureName)
{
u32 ID;
UnicID mUID;
char PGenNameFile[MAX_PATH];
if (PGeneratorDico.IsExist(Name) != -1)
{
PGeneratorDico.GetUnic(&mUID,Name);
ID = PGeneratorDico.mpst_Dico[mUID].AssociatedValue;
if (ID_PGENERATOR[ID])
{
delete ID_PGENERATOR[ID];
ID_PGENERATOR[ID] = NULL;
}
} else
{
PGeneratorDico.GetUnic(&mUID,Name);
ID = PGeneratorCreateID++;
if (ID > MAX_INPMED) return -1;
PGeneratorDico.mpst_Dico[mUID].AssociatedValue = ID;
}
sprintf(PGenNameFile, ".\\Particles\\%s", fileName);
if (GetFileNameExtend(fileName) != '.PGR')
strcat(fileName, ".PGR");
ID_PGENERATOR[ID] = new PGENERATOR_OBJ();
if (LoadPGENERATOR_OBJ(&ID_PGENERATOR[ID],PGenNameFile))
return -1;
ID_PGENERATOR[ID]->alive = true;
strcpy(ID_PGENERATOR[ID]->Name, Name);
strcpy(ID_PGENERATOR[ID]->GeneratorName, fileName);
strcpy(ID_PGENERATOR[ID]->SceneName, SceneName);
strcpy(ID_PGENERATOR[ID]->ObjectName, ObjectName);
strcpy(ID_PGENERATOR[ID]->MassTextureName, MassTextureName);
if (*ID_PGENERATOR[ID]->MassTextureName)
CreateMedia(ID_PGENERATOR[ID]->MassTextureName, 0);
// Code For .MAT in Particles, ABONDONNED
//if (GetFileNameExtend(ID_PGENERATOR[ID]->MediaName) == '.MAT')
//{
// ID_PGENERATOR[ID]->MaterialPtr = (_3D_Material*)CC_malloc(sizeof(_3D_Material));
// memset(ID_PGENERATOR[ID]->MaterialPtr,0,sizeof(_3D_Material));
// FILE *F = fopen(ID_PGENERATOR[ID]->MediaName, "rb");
// if (F)
// {
// UNIC_Dico Dico;
// Dico.Init();
// Load_3D_Material(&ID_PGENERATOR[ID]->MaterialPtr,F, &Dico);
// for (int j = 0 ; j < ID_PGENERATOR[ID]->MaterialPtr->NumberOfLayers ; j++ )
// {
// char Name2[2048];
// Dico.GetName(&ID_PGENERATOR[ID]->MaterialPtr->Layers[j].TextureID,Name2);
// CreateMedia(Name2,0);
// MediaDico.GetUnic(&ID_PGENERATOR[ID]->MaterialPtr->Layers[j].TextureMediaIndex,Name2);
// MediaDico.GetName(&ID_PGENERATOR[ID]->MaterialPtr->Layers[j].TextureMediaIndex,Name2);
// // Trying this ...
// ID_PGENERATOR[ID]->MaterialPtr->Layers[j].TextureID = ID_PGENERATOR[ID]->MaterialPtr->Layers[j].TextureMediaIndex;
// }
// CC_fclose(F);
// } else
// {
// CC_free(ID_PGENERATOR[ID]->MaterialPtr);
// ID_PGENERATOR[ID]->MaterialPtr = NULL;
// }
//} else
//{
// ID_PGENERATOR[ID]->MaterialPtr = NULL;
CreateMedia(ID_PGENERATOR[ID]->MediaName, 0);
//}
ID_PGENERATOR[ID]->ThisID = ID;
ID_PGENERATOR[ID]->Init();
ComputeParticleOptions(ID_PGENERATOR[ID]);
return ID;
}
void WORLD::DeletePGenerator(s8 *Name)
{
u32 ID;
UnicID mUID;
if (PGeneratorDico.IsExist(Name) == -1)
return;
PGeneratorDico.GetUnic(&mUID,Name);
ID = PGeneratorDico.mpst_Dico[mUID].AssociatedValue;
if (ID_PGENERATOR[ID])
{
u32 mediaIndex;
if (GetMediaFromString(ID_PGENERATOR[ID]->MediaName, &mediaIndex))
DestroyMedia(mediaIndex);
if (*ID_PGENERATOR[ID]->MassTextureName && GetMediaFromString(ID_PGENERATOR[ID]->MassTextureName, &mediaIndex))
DestroyMedia(mediaIndex);
delete ID_PGENERATOR[ID];
ID_PGENERATOR[ID] = NULL;
}
PGeneratorDico.DelWord(Name);
}
void WORLD::TouchPGenerator(s8 *BaseName)
{
for (; *BaseName; BaseName++)
{
for (int ID=0; ID<MAX_PGENERATOR; ID++)
{
if (!ID_PGENERATOR[ID]) continue;
if (!strcmp(ID_PGENERATOR[ID]->GeneratorName, BaseName))
{
char Name[MAX_PATH];
char SceneName[MAX_PATH];
char ObjectName[MAX_PATH];
char MassTextureName[MAX_PATH];
strcpy(Name, ID_PGENERATOR[ID]->Name);
strcpy(SceneName, ID_PGENERATOR[ID]->SceneName);
strcpy(ObjectName, ID_PGENERATOR[ID]->ObjectName);
strcpy(MassTextureName, ID_PGENERATOR[ID]->MassTextureName);
DeletePGenerator(Name);
LoadPGenerator(Name, BaseName, SceneName, ObjectName, MassTextureName);
return;
}
}
}
}
void WORLD::SavePGenerator(s8 *Name, s8 *fileName)
{
u32 ID;
UnicID mUID;
if (PGeneratorDico.IsExist(Name) == -1)
return;
PGeneratorDico.GetUnic(&mUID,Name);
ID = PGeneratorDico.mpst_Dico[mUID].AssociatedValue;
if (ID_PGENERATOR[ID])
{
char PGenNameFile[256];
if (fileName && *fileName)
sprintf(PGenNameFile, ".\\Particles\\%s", fileName);
else
sprintf(PGenNameFile, ".\\Particles\\%s", ID_PGENERATOR[ID]->GeneratorName);
if (GetFileNameExtend(PGenNameFile) != '.PGR')
strcat(PGenNameFile, ".PGR");
SavePGENERATOR_OBJ(ID_PGENERATOR[ID],PGenNameFile);
}
}
void WORLD::ComputeParticleOptions(PGENERATOR_OBJ *PGen)
{
if (PGen->sonMode != 0)
{
char sonName[MAX_PATH];
char empty = 0;
u32 sonID;
sprintf(sonName, "%s_Son", PGen->Name);
sonID = LoadPGenerator(sonName, PGen->son, &empty, &empty, &empty);
if (sonID != -1)
PGen->particuleSonPtr = ID_PGENERATOR[sonID];
}
if (PGen->options & 8)
{
SmallScene *SmSc = SmallNameToScene(PGen->SceneName);
if (SmSc != NULL &&
PGen->ObjectName[0])
{
u32 ObjectREF = SmSc->ObjectNameDico.IsExist(PGen->ObjectName);
if (ObjectREF == -1)
{
strcat(PGen->ObjectName, ".OBJ");
ObjectREF = SmSc->ObjectNameDico.IsExist(PGen->ObjectName);
}
if (ObjectREF != -1)
ObjectREF = SmSc->ObjectNameDico.mpst_Dico[ObjectREF].AssociatedValue;
if (ObjectREF != -1)
{
_3D_Object *pObj = SmSc->ObjectsPtrs[ObjectREF];
if (pObj->MeshIndex != -1)
{
Mesh *RenderMesh = SmSc->MeshesPtrs[pObj->MeshIndex];
MAP *massTexture = NULL;
if (*PGen->MassTextureName)
{
int MediaIndex = MediaDico.IsExist(PGen->MassTextureName);
if (MediaIndex != -1)
{
MediaIndex = MediaDico.mpst_Dico[MediaIndex].AssociatedValue;
if (MediaIndex != -1)
{
massTexture = &ID_MEDIA[MediaIndex]->Image;
}
}
}
if (PGen->MeshSurfaceList != NULL)
CC_free(PGen->MeshSurfaceList);
PGen->MeshFaces = RenderMesh->NumberOfFaces;
PGen->MeshSurfaceList = (float *)CC_malloc(RenderMesh->NumberOfFaces*sizeof(float));
PGen->MeshSurface = GetMeshSurface(RenderMesh, NULL, PGen->MeshSurfaceList, massTexture);
}
}
}
}
ParticuleFromMesh = 0;
for (int partIdx = 0; partIdx<MAX_PGENERATOR; partIdx++)
{
if (ID_PGENERATOR[partIdx] && (ID_PGENERATOR[partIdx]->options & 8))
{
ParticuleFromMesh = 1;
break;
}
}
}
void WORLD::ProcessParticules(PGENERATOR_OBJ *PGen, bool ProcessOnly, float IVal, float JVal, float KVal)
{
START_RASTER(ParticuleProcess);
PGen->Collision = CollisionOn;
PGen->curTime = timeGetTime();
PGen->Process(PGen->curTime - PGen->pgTime);
if (!ProcessOnly)
{
if (*PGen->SceneName &&
SetOriginDirection(PGen, SmallNameToScene(PGen->SceneName), IVal, JVal, KVal))
{
PGen->GenerateDyn(PGen->curTime - PGen->pgTime);
}
}
PGen->pgTime = PGen->curTime;
STOP_RASTER(ParticuleProcess);
}
int WORLD::EmitParticule(PGENERATOR_OBJ *PGen, int life, float IVal, float JVal, float KVal, Vector *origin, Vector *direction)
{
if (PGen->options & 8)
{
PGen->GenerateFix(1, life);
return -1;
}
if (origin != NULL && direction != NULL)
{
PGen->Origin = *origin;
PGen->Direction = *direction;
} else
{
if (!*PGen->SceneName ||
!SetOriginDirection(PGen, SmallNameToScene(PGen->SceneName), IVal, JVal, KVal))
return -1;
}
return PGen->GenerateSingle(PGen->Origin, PGen->Direction, life);
}
void WORLD::RenderParticules(PGENERATOR_OBJ *PGen, char *SceneName)
{
if (!PGen->alive) return;
SmallScene *SmSc;
MATRIX MatrixToSet,CP;
float Current_focale;
RS RSToUse;
if (SceneName == NULL || *SceneName == 0)
SmSc = SmallNameToScene(PGen->SceneName);
else
SmSc = SmallNameToScene(SceneName);
if (SmSc == NULL) return;
if (SmSc->fFocalToUseForNextRender == 0)
Current_focale = GetCurrentFocale();
else
Current_focale = SmSc->fFocalToUseForNextRender;
DI->Perspective(Current_focale);
CP = SmSc->CameraPosition;
CP.K *= -1.0f;
CP.Inverse(MatrixToSet);
DI->Matrix(&MatrixToSet);
START_RASTER(ParticuleRender);
Particules *partPtr;
int partIdx;
for (partIdx=0, partPtr=PGen->particulesTab; partIdx<PGen->nbParticules; partIdx++, partPtr++)
{
partPtr->coords = partPtr->coordsDest;
partPtr->speed = partPtr->speedDest;
}
// Code For .MAT in Particles, ABONDONNED
//if (!PGen->MaterialPtr)
//{
int MediaIndex = MediaDico.IsExist((char *)PGen->MediaName);
if (MediaIndex != -1) MediaIndex = MediaDico.mpst_Dico[MediaIndex].AssociatedValue;
if (MediaIndex == -1 || !ID_MEDIA[MediaIndex])
return;
GLOB_SetDefaultRS(&RSToUse);
RSToUse.BACKFACE = 0;
RSToUse.BlendingMode = PGen->BlendMode;
if (PGen->AlphaThreshold < 0)
{
RSToUse.AlphaThreshold = -PGen->AlphaThreshold - 1;
RSToUse.NOZWRITE = 1;
} else
{
RSToUse.AlphaThreshold = PGen->AlphaThreshold;
RSToUse.NOZWRITE = 0;
}
// Force no Z test and ZWrite
RSToUse.NOZWRITE = 0;
RSToUse.ZPASS = 1;
DI->DrawParticules(PGen->particulesTab, PGen->nbParticules, ID_MEDIA[MediaIndex]->ulAssociatedTextureIndex, PGen->TextureGrid, &RSToUse, SmSc->CameraPosition);
// Code For .MAT in Particles, ABONDONNED
//} else
//{
// u32 CurrentColor,MulColor;
// CurrentColor = DI->GetCurrentColor();
// for (int SubLvl = 0 ; SubLvl < PGen->MaterialPtr->NumberOfLayers; SubLvl++)
// {
// u32 MediaIndex,OGLIndex;
// if (PGen->MaterialPtr->Layers[SubLvl].RenderState.SKIPLAYER) continue;
// MulColor = COL_MulColor(CurrentColor,PGen->MaterialPtr->Layers[SubLvl].ColorMultiplier);
// DI->SetCurrentColor(MulColor);
// OGLIndex = -1;
// MediaIndex = PGen->MaterialPtr->Layers[SubLvl].TextureMediaIndex;
// if (MediaIndex != -1)
// {
// MediaIndex = MediaDico.mpst_Dico[PGen->MaterialPtr->Layers[SubLvl].TextureMediaIndex].AssociatedValue;
// if (MediaIndex != -1 && ID_MEDIA[MediaIndex])
// {
// if (ID_MEDIA[MediaIndex]->ulMediaRedirectValue != -1)
// {
// MediaIndex = ID_MEDIA[MediaIndex]->ulMediaRedirectValue;
// }
// OGLIndex = ID_MEDIA[MediaIndex]->ulAssociatedTextureIndex;
// }
// }
// RSToUse = PGen->MaterialPtr->Layers[SubLvl].RenderState;
// DI->SetRS(&RSToUse,OGLIndex);
// DI->DrawParticules(PGen->particulesTab, PGen->nbParticules, ID_MEDIA[MediaIndex]->ulAssociatedTextureIndex, PGen->TextureGrid, &RSToUse, SmSc->CameraPosition);
// DI->SetCurrentColor(CurrentColor);
// }
//}
STOP_RASTER(ParticuleRender);
}
void WORLD::ComputeMeshParticules(char *Name, _3D_Object *obj, Mesh *RenderMesh, MATRIX *global)
{
int beginFace = 0;
int beginRand = 0;
MAP *massTexture = NULL;
for (int partIdx=0; partIdx<MAX_PGENERATOR; partIdx++)
{
if (!ID_PGENERATOR[partIdx] ||
!ID_PGENERATOR[partIdx]->alive ||
!(ID_PGENERATOR[partIdx]->options & 8) ||
!*ID_PGENERATOR[partIdx]->ObjectName) continue;
if (strcmp(ID_PGENERATOR[partIdx]->SceneName, Name))
continue;
SmallScene *SmSc = SmallNameToScene(ID_PGENERATOR[partIdx]->SceneName);
if (SmSc == NULL)
continue;
int ObjectREF = SmSc->ObjectNameDico.IsExist(ID_PGENERATOR[partIdx]->ObjectName);
if (ObjectREF != -1)
ObjectREF = SmSc->ObjectNameDico.mpst_Dico[ObjectREF].AssociatedValue;
if (SmSc->ObjectsPtrs[ObjectREF] != obj)
continue;
float surface = ID_PGENERATOR[partIdx]->MeshSurface;
if (ID_PGENERATOR[partIdx]->options & 16)
{
beginFace = ID_PGENERATOR[partIdx]->MeshFaces * rand() / RAND_MAX;
beginRand = 2 * (NB_RAND_ELMTS / 2 * rand() / RAND_MAX);
}
if (*ID_PGENERATOR[partIdx]->MassTextureName)
{
int MediaIndex = MediaDico.IsExist(ID_PGENERATOR[partIdx]->MassTextureName);
if (MediaIndex != -1)
{
MediaIndex = MediaDico.mpst_Dico[MediaIndex].AssociatedValue;
if (MediaIndex != -1)
{
massTexture = &ID_MEDIA[MediaIndex]->Image;
}
}
}
GetPointRepartition(ID_PGENERATOR[partIdx]->OriginList,
ID_PGENERATOR[partIdx]->DirectionList,
NULL,
NULL,
ID_PGENERATOR[partIdx]->genNumber,
RenderMesh, global, surface/(ID_PGENERATOR[partIdx]->genNumber),
ID_PGENERATOR[partIdx]->MeshSurfaceList, massTexture,
beginFace, beginRand);
}
}
void WORLD::DestroyAllPGenerator()
{
for (u32 Counter = 0 ; Counter < MAX_PGENERATOR; Counter++)
{
if (ID_PGENERATOR[Counter])
{
delete ID_PGENERATOR[Counter];
ID_PGENERATOR[Counter] = NULL;
}
}
PGeneratorDico.Destroy();
PGeneratorCreateID = 0;
}
int WORLD::GetPGeneratorFromString(char *PGeneratorName, u32 *PGeneratorIndex)
{
*PGeneratorIndex = PGeneratorDico.IsExist(PGeneratorName);
if (*PGeneratorIndex == -1) return 0;
*PGeneratorIndex = PGeneratorDico.mpst_Dico[*PGeneratorIndex].AssociatedValue;
return *PGeneratorIndex != -1 && ID_PGENERATOR[*PGeneratorIndex] != NULL;
}
PGENERATOR_OBJ* WORLD::GetPGeneratorPtrFromString(char *PGeneratorName)
{
u32 PGeneratorIndex = PGeneratorDico.IsExist(PGeneratorName);
if (PGeneratorIndex == -1) return NULL;
PGeneratorIndex = PGeneratorDico.mpst_Dico[PGeneratorIndex].AssociatedValue;
return ID_PGENERATOR[PGeneratorIndex];
}