Смекни!
smekni.com

Автоматизированное редактирование частиц в компьютерной графике (стр. 12 из 13)

#define SCALE_END_H_ATTR "scale_end_h"

#define DISPERSION_X_ATTR "dispersion_x"

#define DISPERSION_Y_ATTR "dispersion_y"

#define PS_X_ATTR "ps_x"

#define PS_Y_ATTR "ps_y"

#define PS_SPEED_X_ATTR "ps_speed_x"

#define PS_SPEED_Y_ATTR "ps_speed_y"

#define START_DELAY_ATTR "start_delay"

#define STOP_DELAY_ATTR "stop_delay"

#define ROTATE_ATTR "rotate"

//ctors, destructors, ...

ParticleSystem::ParticleSystem()

{

data.pLifeTime= 1.0;

data.pMaxCount = EXPL_MAX;

data.pCountOnStart = 1;

data.pGravityX = data.pGravityY = 0.0;

//p.speed, dispersion page

data.pMoveSpeedX = 0.0;

data.pMoveSpeedY = 0.0;

data.pKFDispersionX = 0.0;

data.pKFDispersionY = 0.0;

//p.scale page

data.pKFScaleBeginW = 1.0;

data.pKFScaleBeginH = 1.0;

data.pKFScaleEndW = 1.0;

data.pKFScaleEndH = 1.0;

//p.color page

data.pRedBegin = 1.0;

data.pGreenBegin = 1.0;

data.pBlueBegin = 1.0;

data.pAlphaBegin = 1.0;

data.pRedEnd = 1.0;

data.pGreenEnd = 1.0;

data.pBlueEnd = 1.0;

data.pAlphaEnd = 1.0;

//rotate

data.pAngleRotate = 0.0;

//start in, stop in page

data.startDelay = 0.0;

data.stopDelay = 1800.0;

data.pAppearDelay = 0.0;

//PS settings page

MYSize2D sz = {100.0,100.0};

data.pAppearBoxSize = sz;

data.speedChangeX = 0;

data.speedChangeY = 0;

data.initialX = currentX = BOUND_DIMENSION;

data.initialY = currentY = BOUND_DIMENSION;

boundedRectColor = PS_BOUNDED_RECT_COLOR;

particleTexPtr = NULL;

setDefaultParticleTex();

isRunb = false;

isFinishedb = false;

viewMatrixCache = (GLdouble*)malloc(sizeof(GLdouble) * 16);

assert(viewMatrixCache != NULL);

}

ParticleSystem::~ParticleSystem()

{

free(viewMatrixCache);

if(particleTexPtr)

delete particleTexPtr;

}

int ParticleSystem::setParticleTex(const wxString &texture_path)

{

MYTexture* tmp_tex = new MYTexture(texture_path);

int res = tmp_tex->getState();

if(res != TEX_OK)

{

delete tmp_tex;

return res;

}

if(particleTexPtr)

delete particleTexPtr;

particleTexPtr = tmp_tex;

data.particleTexFileName = texture_path;

MYTexCoordPoint *ptrTex = texCoord;

for(int i = 0; i < EXPL_MAX; i++)

{

ptrTex->x = 0.0; ptrTex->y = 0.0;

ptrTex++;

ptrTex->x = particleTexPtr->getMaxS(); ptrTex->y = 0.0;

ptrTex++;

ptrTex->x = particleTexPtr->getMaxS(); ptrTex->y = particleTexPtr->getMaxT();

ptrTex++;

ptrTex->x = 0.0; ptrTex->y = 0.0;

ptrTex++;

ptrTex->x = particleTexPtr->getMaxS(); ptrTex->y = particleTexPtr->getMaxT();

ptrTex++;

ptrTex->x = 0.0; ptrTex->y = particleTexPtr->getMaxT();

ptrTex++;

}

return TEX_OK;

}

void ParticleSystem::setDefaultParticleTex()

{

if(particleTexPtr)

delete particleTexPtr;

GLubyte *buffer = new GLubyte[8 * 8 * 4];

memset(buffer, 255, 8*8*4);//white colour

particleTexPtr = new MYTexture(32,16711680/*third byte pattern*/,65280/*second byte pattern*/,255/*first byte pattern*/

,8,8,buffer);

delete[] buffer;

data.particleTexFileName = wxString("");

}

double ParticleSystem::getX() const

{

return currentX;

}

double ParticleSystem::getY() const

{

return currentY;

}

void ParticleSystem::setX(double x)

{

data.initialX = currentX = x;

}

void ParticleSystem::setY(double y)

{

data.initialY = currentY = y;

}

double ParticleSystem::getSpeedChangeX() const

{

return data.speedChangeX;

}

double ParticleSystem::getSpeedChangeY() const

{

return data.speedChangeY;

}

void ParticleSystem::setSpeedChangeX(double speed)

{

data.speedChangeX = speed;

}

void ParticleSystem::setSpeedChangeY(double speed)

{

data.speedChangeY = speed;

}

double ParticleSystem::getStopDelay() const

{

return data.stopDelay;

}

double ParticleSystem::getStartDelay() const

{

return data.startDelay;

}

void ParticleSystem::setStopDelay(double time)

{

data.stopDelay = time;

}

void ParticleSystem::setStartDelay(double time)

{

data.startDelay = time;

}

double ParticleSystem::getLifeTime() const

{

return data.pLifeTime;

}

void ParticleSystem::setLifeTime(double time)

{

data.pLifeTime = time;

}

double ParticleSystem::getParticleAppearDelay() const

{

return data.pAppearDelay;

}

void ParticleSystem::setParticleAppearDelay(double time)

{

data.pAppearDelay = time;

}

double ParticleSystem::getMoveSpeedX() const

{

return data.pMoveSpeedX;

}

double ParticleSystem::getMoveSpeedY() const

{

return data.pMoveSpeedY;

}

void ParticleSystem::setMoveSpeedX(double speed)

{

data.pMoveSpeedX = speed;

}

void ParticleSystem::setMoveSpeedY(double speed)

{

data.pMoveSpeedY = speed;

}

double ParticleSystem::getGravityX() const

{

return data.pGravityX;

}

double ParticleSystem::getGravityY() const

{

return data.pGravityY;

}

void ParticleSystem::setGravityX(double gravity)

{

data.pGravityX = gravity;

}

void ParticleSystem::setGravityY(double gravity)

{

data.pGravityY = gravity;

}

int ParticleSystem::getMaxCount() const

{

return data.pMaxCount;

}

void ParticleSystem::setMaxCount(int count)

{

data.pMaxCount = count;

if(data.pCountOnStart > data.pMaxCount)

data.pCountOnStart = data.pMaxCount;

}

int ParticleSystem::getCountOnStart() const

{

return data.pCountOnStart;

}

void ParticleSystem::setCountOnStart(int count)

{

data.pCountOnStart = count;

}

MYSize2D ParticleSystem::getAppearBoxSize() const

{

return data.pAppearBoxSize;

}

void ParticleSystem::setAppearBoxSize(MYSize2D box)

{

data.pAppearBoxSize = box;

}

double ParticleSystem::getRedBegin() const

{

return data.pRedBegin;

}

double ParticleSystem::getGreenBegin() const

{

return data.pGreenBegin;

}

double ParticleSystem::getBlueBegin() const

{

return data.pBlueBegin;

}

double ParticleSystem::getAlphaBegin() const

{

return data.pAlphaBegin;

}

void ParticleSystem::setRedBegin(double red)

{

data.pRedBegin = red;

}

void ParticleSystem::setGreenBegin(double green)

{

data.pGreenBegin = green;

}

void ParticleSystem::setBlueBegin(double blue)

{

data.pBlueBegin = blue;

}

void ParticleSystem::setAlphaBegin(double alpha)

{

data.pAlphaBegin = alpha;

}

double ParticleSystem::getRedEnd() const

{

return data.pRedEnd;

}

double ParticleSystem::getGreenEnd() const

{

return data.pGreenEnd;

}

double ParticleSystem::getBlueEnd() const

{

return data.pBlueEnd;

}

double ParticleSystem::getAlphaEnd() const

{

return data.pAlphaEnd;

}

void ParticleSystem::setRedEnd(double red)

{

data.pRedEnd = red;

}

void ParticleSystem::setGreenEnd(double green)

{

data.pGreenEnd = green;

}

void ParticleSystem::setBlueEnd(double blue)

{

data.pBlueEnd = blue;

}

void ParticleSystem::setAlphaEnd(double alpha)

{

data.pAlphaEnd = alpha;

}

double ParticleSystem::getRotateAngle() const

{

return data.pAngleRotate;

}

void ParticleSystem::setRotateAngle(double angle)

{

data.pAngleRotate = angle;

}

double ParticleSystem::getKFScaleBeginW() const

{

return data.pKFScaleBeginW;

}

double ParticleSystem::getKFScaleBeginH() const

{

return data.pKFScaleBeginH;

}

void ParticleSystem::setKFScaleBeginW(double scale)

{

data.pKFScaleBeginW = scale;

}

void ParticleSystem::setKFScaleBeginH(double scale)

{

data.pKFScaleBeginH = scale;

}

double ParticleSystem::getKFScaleEndW() const

{

return data.pKFScaleEndW;

}

double ParticleSystem::getKFScaleEndH() const

{

return data.pKFScaleEndH;

}

void ParticleSystem::setKFScaleEndW(double scale)

{

data.pKFScaleEndW = scale;

}

void ParticleSystem::setKFScaleEndH(double scale)

{

data.pKFScaleEndH = scale;

}

double ParticleSystem::getKFDispersionX() const

{

return data.pKFDispersionX;

}

double ParticleSystem::getKFDispersionY() const

{

return data.pKFDispersionY;

}

void ParticleSystem::setKFDispersionX(double disp)

{

data.pKFDispersionX = disp;

}

void ParticleSystem::setKFDispersionY(double disp)

{

data.pKFDispersionY = disp;

}

wxString ParticleSystem::getParticleTexFileName() const

{

return data.particleTexFileName;

}

void ParticleSystem::copyDataFromParticleSystem(ParticleSystem* sys_from)

{

if(!sys_from)

return;

data.pLifeTime = sys_from->data.pLifeTime;

data.pMaxCount = sys_from->data.pMaxCount;

data.pCountOnStart = sys_from->data.pCountOnStart;

data.pGravityX = sys_from->data.pGravityX;

data.pGravityY = sys_from->data.pGravityY;

//p.speed, dispersion page

data.pMoveSpeedX = sys_from->data.pMoveSpeedX;

data.pMoveSpeedY = sys_from->data.pMoveSpeedY;

data.pKFDispersionX = sys_from->data.pKFDispersionX;

data.pKFDispersionY = sys_from->data.pKFDispersionY;

//p.scale page

data.pKFScaleBeginW = sys_from->data.pKFScaleBeginW;

data.pKFScaleBeginH = sys_from->data.pKFScaleBeginH;

data.pKFScaleEndW = sys_from->data.pKFScaleEndW;

data.pKFScaleEndH = sys_from->data.pKFScaleEndH;

//p.color page

data.pRedBegin = sys_from->data.pRedBegin;

data.pGreenBegin = sys_from->data.pGreenBegin;

data.pBlueBegin = sys_from->data.pBlueBegin;

data.pAlphaBegin = sys_from->data.pAlphaBegin;

data.pRedEnd = sys_from->data.pRedEnd;

data.pGreenEnd = sys_from->data.pGreenEnd;

data.pBlueEnd = sys_from->data.pBlueEnd;

data.pAlphaEnd = sys_from->data.pAlphaEnd;

//rotate

data.pAngleRotate = sys_from->data.pAngleRotate;

//start in, stop in page

data.startDelay = sys_from->data.startDelay;

data.stopDelay = sys_from->data.stopDelay;

data.pAppearDelay = sys_from->data.pAppearDelay;

//PS settings page

data.pAppearBoxSize = sys_from->data.pAppearBoxSize;

data.speedChangeX = sys_from->data.speedChangeX;

data.speedChangeY = sys_from->data.speedChangeY;

setX(sys_from->data.initialX);

setY(sys_from->data.initialY);

if(sys_from->data.particleTexFileName == "")

setDefaultParticleTex();

else

setParticleTex(sys_from->data.particleTexFileName);

}

bool ParticleSystem::isRun() const

{

return isRunb;

}

bool ParticleSystem::isFinished() const

{

return isFinishedb;

}

void ParticleSystem::start()

{

isRunb = true;

isFinishedb = false;

restart();

}

void ParticleSystem::stop()

{

isRunb = false;

}

void ParticleSystem::stopExtra()

{

isRunb = false;

finish();

}

void ParticleSystem::finish()

{

isFinishedb = true;

currentX = data.initialX;

currentY = data.initialY;

}

void ParticleSystem::restart()

{

startInTime = data.startDelay;

stopInTime = data.stopDelay;

timeForNextParticle = data.pAppearDelay;

int count = data.pCountOnStart;

for (int i=0; i<EXPL_MAX; i++)

{

if (count > 0)

{

initParticleAtIndex(i);

count--;

}

else

{

pTM[i] = 0;

}

}

}

void ParticleSystem::initParticleAtIndex(int i)

{

assert(i >= 0 && i < EXPL_MAX);

pTM[i] = data.pLifeTime;

pX[i] = fmod(rand(), data.pAppearBoxSize.width);

pY[i] = fmod(rand(), data.pAppearBoxSize.height);

double speedDeltaX = fmod(rand(), data.pKFDispersionX * 2 + 1) - data.pKFDispersionX;

pDx[i] = data.pMoveSpeedX + speedDeltaX;

double speedDeltaY = fmod(rand(), data.pKFDispersionY * 2 + 1) - data.pKFDispersionY;

pDy[i] = data.pMoveSpeedY + speedDeltaY;

}

void ParticleSystem::drawBound()

{

double appear_w = data.pAppearBoxSize.width;

double appear_h = data.pAppearBoxSize.height;

//draw bound itself

glColor4d(boundColor.Red()/255.0, boundColor.Green()/255.0, boundColor.Blue()/255.0, boundColor.Alpha()/255.0);

glBegin(GL_POLYGON);

glVertex2d(currentX - BOUND_DIMENSION, currentY - BOUND_DIMENSION);

glVertex2d(currentX + appear_w + BOUND_DIMENSION, currentY - BOUND_DIMENSION);

glVertex2d(currentX + appear_w + BOUND_DIMENSION, currentY + appear_h + BOUND_DIMENSION);

glVertex2d(currentX - BOUND_DIMENSION, currentY + appear_h + BOUND_DIMENSION);

glEnd();

//draw inner part of bound

glColor4d(boundedRectColor.Red()/255.0, boundedRectColor.Green()/255.0, boundedRectColor.Blue()/255.0,

boundedRectColor.Alpha()/255.0);

glBegin(GL_POLYGON);

glVertex2d(currentX, currentY);

glVertex2d(currentX + appear_w, currentY);

glVertex2d(currentX + appear_w, currentY + appear_h);

glVertex2d(currentX, currentY + appear_h);

glEnd();

if(!particleTexPtr)

return;

//draw texture on left-top

double tex_w = particleTexPtr->getWidth();

double tex_h = particleTexPtr->getHeight();

glEnable(GL_TEXTURE_2D);

GLint binded;

glGetIntegerv(GL_TEXTURE_BINDING_2D,&binded);

glBindTexture(GL_TEXTURE_2D, particleTexPtr->getName());

glColor4d(1.0,1.0,1.0,1.0);

double real_tex_w, real_tex_h;

real_tex_w = min(appear_w, tex_w);

real_tex_h = min(appear_h, tex_h);

double real_tex_s, real_tex_t;

real_tex_s = particleTexPtr->getMaxS() * ((double)real_tex_w) / ((double)tex_w);

real_tex_t = particleTexPtr->getMaxT() * ((double)real_tex_h) / ((double)tex_h);

glBegin(GL_POLYGON);

glTexCoord2d(0.0, 0.0);

glVertex2d(currentX, currentY);

glTexCoord2d(real_tex_s, 0.0);//texCoord[0].x,texCoord[0].y);

glVertex2d(currentX + real_tex_w, currentY);

glTexCoord2d(real_tex_s, real_tex_t);//texCoord[1].x,texCoord[1].y);

glVertex2d(currentX + real_tex_w, currentY + real_tex_h);

glTexCoord2d(0.0, real_tex_t);

glVertex2d(currentX, currentY + real_tex_h);

glEnd();

glBindTexture(GL_TEXTURE_2D, binded);

glDisable(GL_TEXTURE_2D);

}

void ParticleSystem::draw()

{

if(!particleTexPtr)

return;

if (isFinishedb)

return;

//if (int(startInTime*maj_kof) > 0)

if(startInTime > 0.0)

return;

glMatrixMode(GL_MODELVIEW);

MYPoint2D *ptrVert = verCoord;

MYParticleColor *ptrColor = color;

int count = 0;

double progress, x, y, w, h, r, g, b, a;

bool is_rotate = (data.pAngleRotate != 0.0);

for (int i = 0; i < EXPL_MAX; ++i)

{

progress = pTM[i];

x = pX[i];

y = pY[i];

if(progress > 0.0)

{

progress /= data.pLifeTime;

w = (data.pKFScaleEndW + progress * (data.pKFScaleBeginW - data.pKFScaleEndW)) * particleTexPtr->getWidth();

h = (data.pKFScaleEndH + progress * (data.pKFScaleBeginH - data.pKFScaleEndH)) * particleTexPtr->getHeight();

if(is_rotate)

{

double real_alpha = fmod(data.pAngleRotate * 360.0 * progress, 360.0);

glPushMatrix();

glTranslated(x, y, 0.0);

glRotated(real_alpha, 0.0, 0.0, 1.0);//clock wise direction

x = y = 0.0;

}

x -= w/2.0;//only CENTERS of particles initially placed in AppearingBox (0.5,0.5 origin)

y -= h/2.0;//only CENTERS of particles initially placed in AppearingBox (0.5,0.5 origin)

r = data.pRedEnd + progress * (data.pRedBegin - data.pRedEnd);

g = data.pGreenEnd + progress * (data.pGreenBegin - data.pGreenEnd);

b = data.pBlueEnd + progress * (data.pBlueBegin - data.pBlueEnd);

a = data.pAlphaEnd + progress * (data.pAlphaBegin - data.pAlphaEnd);

ptrColor->r = r; ptrColor->g = g; ptrColor->b = b; ptrColor->a = a; ptrColor++;

ptrColor->r = r; ptrColor->g = g; ptrColor->b = b; ptrColor->a = a; ptrColor++;