bool CScreensaverPlasma::Start() { int speed = kodi::GetSettingInt("speed"); m_zoom = kodi::GetSettingInt("zoom"); m_focus = float(kodi::GetSettingInt("focus")) / 50.0f + 0.3f; m_maxdiff = 0.004f * float(speed); m_resolution = kodi::GetSettingInt("resolution"); m_aspectRatio = float(Width()) / float(Height()); std::string fraqShader = kodi::GetAddonPath("resources/shaders/frag.glsl"); std::string vertShader = kodi::GetAddonPath("resources/shaders/vert.glsl"); if (!LoadShaderFiles(vertShader, fraqShader) || !CompileAndLink()) return false; glGenBuffers(1, &m_vertexVBO); // Initialize pseudorandom number generator srand((unsigned)time(nullptr)); // Initialize constants for (int i = 0; i < NUMCONSTS; i++) { m_ct[i] = rsRandf(PIx2); m_cv[i] = rsRandf(0.005f * float(speed)) + 0.0001f; } m_projMat = glm::mat4(1.0f); m_modelMat = glm::mat4(1.0f); SetPlasmaSize(); return true; }
void starBurst::restart(float* position){ int i; for(i=0; i<SB_NUM_STARS; i++){ // don't restart if any star is still active if(stars_active[i]) return; } if(size < 3.0f) // or if flare hasn't faded out completely return; float color[3]; color[0] = rsRandf(1.0f); color[1] = rsRandf(1.0f); color[2] = rsRandf(1.0f); color[rsRandi(3)] = 1.0f; for(i=0; i<SB_NUM_STARS; i++){ stars_active[i] = 1; stars[i]->pos[0] = position[0]; stars[i]->pos[1] = position[1]; stars[i]->pos[2] = position[2]; stars[i]->color[0] = color[0]; stars[i]->color[1] = color[1]; stars[i]->color[2] = color[2]; } size = 0.0f; pos[0] = position[0]; pos[1] = position[1]; pos[2] = position[2]; }
void CParticle::Init() { m_width = rsRandf(0.8f) + 0.2f; m_step = 0.0f; m_spinAngle = rsRandf(360); hsl2rgb(m_cy->m_hsl[0], m_cy->m_hsl[1],m_cy->m_hsl[2], m_r, m_g, m_b); }
starBurst::starBurst(){ int i, j; float vel[3]; float normalizer; // initialize stars stars = new stretchedParticle*[SB_NUM_STARS]; stars_active = new bool[SB_NUM_STARS]; stars_velocity = new float*[SB_NUM_STARS]; for(i=0; i<SB_NUM_STARS; i++){ stars[i] = new stretchedParticle; stars_active[i] = 0; stars_velocity[i] = new float[3]; vel[0] = rsRandf(1.0f) - 0.5f; vel[1] = rsRandf(1.0f) - 0.5f; vel[2] = rsRandf(1.0f) - 0.5f; normalizer = (rsRandf(0.75f) + 0.25f) / sqrtf(vel[0] * vel[0] + vel[1] * vel[1] + vel[2] * vel[2]); stars_velocity[i][0] = vel[0] * normalizer; stars_velocity[i][1] = vel[1] * normalizer; stars_velocity[i][2] = vel[2] * normalizer; } float xyz[3]; float ci, si, cj, sj, cjj, sjj; call_list = glGenLists(1); glNewList(call_list, GL_COMPILE); for(j=0; j<32; j++){ cj = cosf(float(j) * RS_PIx2 / 32.0f); sj = sinf(float(j) * RS_PIx2 / 32.0f); cjj = cosf(float(j+1) * RS_PIx2 / 32.0f); sjj = sinf(float(j+1) * RS_PIx2 / 32.0f); glBegin(GL_TRIANGLE_STRIP); for(i=0; i<=32; i++){ ci = cosf(float(i) * RS_PIx2 / 32.0f); si = sinf(float(i) * RS_PIx2 / 32.0f); xyz[0] = sj * ci; xyz[1] = cj; xyz[2] = sj * si; glNormal3fv(xyz); glVertex3fv(xyz); xyz[0] = sjj * ci; xyz[1] = cjj; xyz[2] = sjj * si; glNormal3fv(xyz); glVertex3fv(xyz); } glEnd(); } glEndList(); size = 4.0f; }
ion::ion () { float temp; pos = rsVec (0.0f, 0.0f, 0.0f); rgb = rsVec (0.0f, 0.0f, 0.0f); temp = rsRandf (2.0f) + 0.4f; size = float (dSize) * temp; speed = float (dSpeed) * 12.0f / temp; }
void changeSettings () { do { equationBase = rsRandf (10) - 5; } while (equationBase <= 2 && equationBase >= -2); // we don't want between 1 and -1 blurColor[0] = rsRandi (100) / 50.0; blurColor[1] = rsRandi (100) / 50.0; blurColor[2] = rsRandi (100) / 50.0; lineColor[0] = rsRandi (100) / 50.0; lineColor[1] = rsRandi (100) / 50.0; lineColor[2] = rsRandi (100) / 50.0; SUBLOOPS = rsRandi (3) + 2; graphTo = rsRandi (16) + 15; speed = (rsRandi (225) + 75) / 1000000.0; if (rsRandi (2) == 1) { speed *= -1; } }
void CCyclone::Update(CScreensaverCyclone* base) { int i; int temp; float between; float diff; int direction; float point[3]; float step; float blend; // update cyclone's path temp = gCycloneSettings.dComplexity + 2; if (m_xyzChange[temp][0] >= m_xyzChange[temp][1]) { m_oldxyz[temp][0] = m_xyz[temp][0]; m_oldxyz[temp][1] = m_xyz[temp][1]; m_oldxyz[temp][2] = m_xyz[temp][2]; m_targetxyz[temp][0] = rsRandf(float(WIDTH*2)) - float(WIDTH); m_targetxyz[temp][1] = float(HIGHT); m_targetxyz[temp][2] = rsRandf(float(WIDTH*2)) - float(WIDTH); m_xyzChange[temp][0] = 0.0f; m_xyzChange[temp][1] = rsRandf(150.0f / float(gCycloneSettings.dSpeed)) + 75.0f / float(gCycloneSettings.dSpeed); } temp = gCycloneSettings.dComplexity + 1; if (m_xyzChange[temp][0] >= m_xyzChange[temp][1]) { m_oldxyz[temp][0] = m_xyz[temp][0]; m_oldxyz[temp][1] = m_xyz[temp][1]; m_oldxyz[temp][2] = m_xyz[temp][2]; m_targetxyz[temp][0] = m_xyz[temp+1][0]; m_targetxyz[temp][1] = rsRandf(float(HIGHT / 3)) + float(HIGHT / 4); m_targetxyz[temp][2] = m_xyz[temp+1][2]; m_xyzChange[temp][0] = 0.0f; m_xyzChange[temp][1] = rsRandf(100.0f / float(gCycloneSettings.dSpeed)) + 75.0f / float(gCycloneSettings.dSpeed); } for (i = gCycloneSettings.dComplexity; i > 1; i--) { if (m_xyzChange[i][0] >= m_xyzChange[i][1]) { m_oldxyz[i][0] = m_xyz[i][0]; m_oldxyz[i][1] = m_xyz[i][1]; m_oldxyz[i][2] = m_xyz[i][2]; m_targetxyz[i][0] = m_targetxyz[i+1][0] + (m_targetxyz[i+1][0] - m_targetxyz[i+2][0]) / 2.0f + rsRandf(float(WIDTH / 2)) - float(WIDTH / 4); m_targetxyz[i][1] = (m_targetxyz[i+1][1] + m_targetxyz[i-1][1]) / 2.0f + rsRandf(float(HIGHT / 8)) - float(HIGHT / 16); m_targetxyz[i][2] = m_targetxyz[i+1][2] + (m_targetxyz[i+1][2] - m_targetxyz[i+2][2]) / 2.0f + rsRandf(float(WIDTH / 2)) - float(WIDTH / 4); if (m_targetxyz[i][1] > HIGHT) m_targetxyz[i][1] = HIGHT; if (m_targetxyz[i][1] < -HIGHT) m_targetxyz[i][1] = -HIGHT; m_xyzChange[i][0] = 0.0f; m_xyzChange[i][1] = rsRandf(75.0f / float(gCycloneSettings.dSpeed)) + 50.0f / float(gCycloneSettings.dSpeed); } } if (m_xyzChange[1][0] >= m_xyzChange[1][1]) { m_oldxyz[1][0] = m_xyz[1][0]; m_oldxyz[1][1] = m_xyz[1][1]; m_oldxyz[1][2] = m_xyz[1][2]; m_targetxyz[1][0] = m_targetxyz[2][0] + rsRandf(float(WIDTH / 2)) - float(WIDTH / 4); m_targetxyz[1][1] = -rsRandf(float(HIGHT / 2)) - float(HIGHT / 4); m_targetxyz[1][2] = m_targetxyz[2][2] + rsRandf(float(WIDTH / 2)) - float(WIDTH / 4); m_xyzChange[1][0] = 0.0f; m_xyzChange[1][1] = rsRandf(50.0f / float(gCycloneSettings.dSpeed)) + 30.0f / float(gCycloneSettings.dSpeed); } if (m_xyzChange[0][0] >= m_xyzChange[0][1]) { m_oldxyz[0][0] = m_xyz[0][0]; m_oldxyz[0][1] = m_xyz[0][1]; m_oldxyz[0][2] = m_xyz[0][2]; m_targetxyz[0][0] = m_xyz[1][0] + rsRandf(float(WIDTH / 8)) - float(WIDTH / 16); m_targetxyz[0][1] = float(-HIGHT); m_targetxyz[0][2] = m_xyz[1][2] + rsRandf(float(WIDTH / 8)) - float(WIDTH / 16); m_xyzChange[0][0] = 0.0f; m_xyzChange[0][1] = rsRandf(100.0f / float(gCycloneSettings.dSpeed)) + 75.0f / float(gCycloneSettings.dSpeed); } for (i = 0; i < (gCycloneSettings.dComplexity+3); i++) { between = m_xyzChange[i][0] / m_xyzChange[i][1] * (2 * M_PI); between = (1.0f - float(cos(between))) / 2.0f; m_xyz[i][0] = ((m_targetxyz[i][0] - m_oldxyz[i][0]) * between) + m_oldxyz[i][0]; m_xyz[i][1] = ((m_targetxyz[i][1] - m_oldxyz[i][1]) * between) + m_oldxyz[i][1]; m_xyz[i][2] = ((m_targetxyz[i][2] - m_oldxyz[i][2]) * between) + m_oldxyz[i][2]; m_xyzChange[i][0] += base->FrameTime(); } // Update cyclone's widths temp = gCycloneSettings.dComplexity + 2; if (m_widthChange[temp][0] >= m_widthChange[temp][1]) { m_oldWidth[temp] = m_width[temp]; m_targetWidth[temp] = rsRandf(225.0f) + 75.0f; m_widthChange[temp][0] = 0.0f; m_widthChange[temp][1] = rsRandf(50.0f / float(gCycloneSettings.dSpeed)) + 50.0f / float(gCycloneSettings.dSpeed); } temp = gCycloneSettings.dComplexity + 1; if (m_widthChange[temp][0] >= m_widthChange[temp][1]) { m_oldWidth[temp] = m_width[temp]; m_targetWidth[temp] = rsRandf(100.0f) + 15.0f; m_widthChange[temp][0] = 0.0f; m_widthChange[temp][1] = rsRandf(50.0f / float(gCycloneSettings.dSpeed)) + 50.0f / float(gCycloneSettings.dSpeed); } for (i = gCycloneSettings.dComplexity; i > 1; i--) { if (m_widthChange[i][0] >= m_widthChange[i][1]) { m_oldWidth[i] = m_width[i]; m_targetWidth[i] = rsRandf(50.0f) + 15.0f; m_widthChange[i][0] = 0.0f; m_widthChange[i][1] = rsRandf(50.0f / float(gCycloneSettings.dSpeed)) + 40.0f / float(gCycloneSettings.dSpeed); } } if (m_widthChange[1][0] >= m_widthChange[1][1]) { m_oldWidth[1] = m_width[1]; m_targetWidth[1] = rsRandf(40.0f) + 5.0f; m_widthChange[1][0] = 0.0f; m_widthChange[1][1] = rsRandf(50.0f / float(gCycloneSettings.dSpeed)) + 30.0f / float(gCycloneSettings.dSpeed); } if (m_widthChange[0][0] >= m_widthChange[0][1]) { m_oldWidth[0] = m_width[0]; m_targetWidth[0] = rsRandf(30.0f) + 5.0f; m_widthChange[0][0] = 0.0f; m_widthChange[0][1] = rsRandf(50.0f / float(gCycloneSettings.dSpeed)) + 20.0f / float(gCycloneSettings.dSpeed); } for (i = 0; i < (gCycloneSettings.dComplexity+3); i++) { between = m_widthChange[i][0] / m_widthChange[i][1]; m_width[i] = ((m_targetWidth[i] - m_oldWidth[i]) * between) + m_oldWidth[i]; m_widthChange[i][0] += base->FrameTime(); } // Update cyclones color if (m_hslChange[0] >= m_hslChange[1]) { m_oldhsl[0] = m_hsl[0]; m_oldhsl[1] = m_hsl[1]; m_oldhsl[2] = m_hsl[2]; m_targethsl[0] = rsRandf(1.0f); m_targethsl[1] = rsRandf(1.0f); m_targethsl[2] = rsRandf(1.0f) + 0.5f; if (m_targethsl[2] > 1.0f) m_targethsl[2] = 1.0f; m_hslChange[0] = 0.0f; m_hslChange[1] = rsRandf(30.0f) + 2.0f; } between = m_hslChange[0] / m_hslChange[1]; diff = m_targethsl[0] - m_oldhsl[0]; direction = 0; if ((m_targethsl[0] > m_oldhsl[0] && diff > 0.5f) || (m_targethsl[0] < m_oldhsl[0] && diff < -0.5f)) if (diff > 0.5f) direction = 1; hslTween(m_oldhsl[0], m_oldhsl[1], m_oldhsl[2], m_targethsl[0], m_targethsl[1], m_targethsl[2], between, direction, m_hsl[0], m_hsl[1], m_hsl[2]); m_hslChange[0] += base->FrameTime(); if (gCycloneSettings.dShowCurves) { unsigned int ptr = 0; sLight curves[std::max(gCycloneSettings.dComplexity+3, 50)]; base->m_lightingEnabled = 0; for (step=0.0; step<1.0; step+=0.02f) { point[0] = point[1] = point[2] = 0.0f; for (i = 0; i < (gCycloneSettings.dComplexity+3); i++) { blend = base->m_fact[gCycloneSettings.dComplexity+2] / (base->m_fact[i] * base->m_fact[gCycloneSettings.dComplexity+2-i]) * powf(step, float(i)) * powf((1.0f - step), float(gCycloneSettings.dComplexity+2-i)); point[0] += m_xyz[i][0] * blend; point[1] += m_xyz[i][1] * blend; point[2] += m_xyz[i][2] * blend; } curves[ptr ].color = sColor(0.0f, 1.0f, 0.0f); curves[ptr++].vertex = sPosition(point); } base->DrawEntry(GL_LINE_STRIP, curves, ptr); ptr = 0; for (i = 0; i < (gCycloneSettings.dComplexity+3); i++) { curves[ptr ].color = sColor(1.0f, 0.0f, 0.0f); curves[ptr++].vertex = sPosition(&m_xyz[i][0]); } base->DrawEntry(GL_LINE_STRIP, curves, ptr); base->m_lightingEnabled = 1; } }
CCyclone::CCyclone() { int i; // Initialize position stuff m_targetxyz = new float*[gCycloneSettings.dComplexity+3]; m_xyz = new float*[gCycloneSettings.dComplexity+3]; m_oldxyz = new float*[gCycloneSettings.dComplexity+3]; for (i = 0; i < int(gCycloneSettings.dComplexity)+3; i++) { m_targetxyz[i] = new float[3]; m_xyz[i] = new float[3]; m_oldxyz[i] = new float[3]; } m_xyz[gCycloneSettings.dComplexity+2][0] = rsRandf(float(WIDTH*2)) - float(WIDTH); m_xyz[gCycloneSettings.dComplexity+2][1] = float(HIGHT); m_xyz[gCycloneSettings.dComplexity+2][2] = rsRandf(float(WIDTH*2)) - float(WIDTH); m_xyz[gCycloneSettings.dComplexity+1][0] = m_xyz[gCycloneSettings.dComplexity+2][0]; m_xyz[gCycloneSettings.dComplexity+1][1] = rsRandf(float(HIGHT / 3)) + float(HIGHT / 4); m_xyz[gCycloneSettings.dComplexity+1][2] = m_xyz[gCycloneSettings.dComplexity+2][2]; for (i = gCycloneSettings.dComplexity; i > 1; i--) { m_xyz[i][0] = m_xyz[i+1][0] + rsRandf(float(WIDTH)) - float(WIDTH / 2); m_xyz[i][1] = rsRandf(float(HIGHT * 2)) - float(HIGHT); m_xyz[i][2] = m_xyz[i+1][2] + rsRandf(float(WIDTH)) - float(WIDTH / 2); } m_xyz[1][0] = m_xyz[2][0] + rsRandf(float(WIDTH / 2)) - float(WIDTH / 4); m_xyz[1][1] = -rsRandf(float(HIGHT / 2)) - float(HIGHT / 4); m_xyz[1][2] = m_xyz[2][2] + rsRandf(float(WIDTH / 2)) - float(WIDTH / 4); m_xyz[0][0] = m_xyz[1][0] + rsRandf(float(WIDTH / 8)) - float(WIDTH / 16); m_xyz[0][1] = float(-HIGHT); m_xyz[0][2] = m_xyz[1][2] + rsRandf(float(WIDTH / 8)) - float(WIDTH / 16); // Initialize width stuff m_targetWidth = new float[gCycloneSettings.dComplexity+3]; m_width = new float[gCycloneSettings.dComplexity+3]; m_oldWidth = new float[gCycloneSettings.dComplexity+3]; m_width[gCycloneSettings.dComplexity+2] = rsRandf(175.0f) + 75.0f; m_width[gCycloneSettings.dComplexity+1] = rsRandf(60.0f) + 15.0f; for (i = gCycloneSettings.dComplexity; i > 1; i--) m_width[i] = rsRandf(25.0f) + 15.0f; m_width[1] = rsRandf(25.0f) + 5.0f; m_width[0] = rsRandf(15.0f) + 5.0f; // Initialize transition stuff m_xyzChange = new float*[gCycloneSettings.dComplexity + 3]; m_widthChange = new float*[gCycloneSettings.dComplexity + 3]; for (i = 0; i < (gCycloneSettings.dComplexity+3); i++) { m_xyzChange[i] = new float[2]; // 0 = step 1 = total steps m_widthChange[i] = new float[2]; m_xyzChange[i][0] = 0.0f; m_xyzChange[i][1] = 0.0f; m_widthChange[i][0] = 0.0f; m_widthChange[i][1] = 0.0f; } // Initialize color stuff m_hsl[0] = m_oldhsl[0] = rsRandf(1.0f); m_hsl[1] = m_oldhsl[1] = rsRandf(1.0f); m_hsl[2] = m_oldhsl[2] = 0.0f; // start out dark m_targethsl[0] = rsRandf(1.0f); m_targethsl[1] = rsRandf(1.0f); m_targethsl[2] = 1.0f; m_hslChange[0] = 0.0f; m_hslChange[1] = 10.0f; }
emitter::emitter () { pos = rsVec (rsRandf (1000.0f) - 500.0f, rsRandf (1000.0f) - 500.0f, rsRandf (1000.0f) - 500.0f); }
void reconfigure () { int i, j; int newBorder, positive; /* * End of old path = start of new path */ for (i = 0; i < 6; i++) path[0][i] = path[segments][i]; /* * determine if direction of motion is positive or negative */ /* * update global position */ if (lastBorder < 6) { if ((path[0][3] + path[0][4] + path[0][5]) > 0.0f) { positive = 1; globalxyz[lastBorder / 2]++; } else { positive = 0; globalxyz[lastBorder / 2]--; } } else { if (path[0][3] > 0.0f) { positive = 1; globalxyz[0]++; } else { positive = 0; globalxyz[0]--; } if (path[0][4] > 0.0f) globalxyz[1]++; else globalxyz[1]--; if (path[0][5] > 0.0f) globalxyz[2]++; else globalxyz[2]--; } if (!rsRandi (11 - dPathrand)) { /* Change directions */ if (!positive) lastBorder += 10; newBorder = transitions[lastBorder][rsRandi (6)]; positive = 0; if (newBorder < 10) positive = 1; else newBorder -= 10; for (i = 0; i < 6; i++) /* set the new border point */ path[1][i] = bPnt[newBorder][i]; if (!positive) { /* flip everything if direction is * negative */ if (newBorder < 6) path[1][newBorder / 2] *= -1.0f; else for (i = 0; i < 3; i++) path[1][i] *= -1.0f; for (i = 3; i < 6; i++) path[1][i] *= -1.0f; } for (i = 0; i < 3; i++) /* reposition the new border */ path[1][i] += globalxyz[i]; lastBorder = newBorder; segments = 1; } else { /* Just keep going straight */ newBorder = lastBorder; for (i = 0; i < 6; i++) path[1][i] = bPnt[newBorder][i]; i = newBorder / 2; if (!positive) { if (newBorder < 6) path[1][i] *= -1.0f; else { path[1][0] *= -1.0f; path[1][1] *= -1.0f; path[1][2] *= -1.0f; } path[1][3] *= -1.0f; path[1][4] *= -1.0f; path[1][5] *= -1.0f; } for (j = 0; j < 3; j++) { path[1][j] += globalxyz[j]; if ((newBorder < 6) && (j != 1)) path[1][j] += rsRandf (0.15f) - 0.075f; } if (newBorder >= 6) path[1][0] += rsRandf (0.1f) - 0.05f; segments = 1; } }
void initSaver(HWND hwnd){ RECT rect; // Window initialization hdc = GetDC(hwnd); setBestPixelFormat(hdc); hglrc = wglCreateContext(hdc); GetClientRect(hwnd, &rect); wglMakeCurrent(hdc, hglrc); // setup viewport //viewport[0] = rect.left; //viewport[1] = rect.top; //viewport[2] = rect.right - rect.left; //viewport[3] = rect.bottom - rect.top; // initialize extensions if(!initExtensions()) dShaders = 0; reshape(rect.right, rect.bottom); #endif //#ifdef RS_XSCREENSAVER void initSaver(HyperspaceSaverSettings *inSettings){ //#endif // Seed random number generator srand((unsigned)time(NULL)); // Limit memory consumption because the Windows previewer is just too darn slow /*if(doingPreview){ dResolution = 6; if(dDepth > 3) dDepth = 3; };*/ // Set up some other inSettings defaults... inSettings->camPos[0] = 0.0f; inSettings->camPos[1] = 0.0f; inSettings->camPos[2] = 0.0f; inSettings->numAnimTexFrames = 20; inSettings->whichTexture = 0; glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); initFlares(inSettings); inSettings->thePath = new splinePath((inSettings->dDepth * 2) + 6); if(inSettings->dUseTunnels) inSettings->theTunnel = new tunnel(inSettings->thePath, 20); // To avoid popping, depth, which will be used for fogging, is set to // dDepth * goo grid size - size of one goo cubelet inSettings->depth = float(inSettings->dDepth) * 2.0f - 2.0f / float(inSettings->dResolution); if(inSettings->dUseGoo) inSettings->theGoo = new goo(inSettings->dResolution, inSettings->depth); inSettings->stars = new stretchedParticle*[inSettings->dStars]; for(int i=0; i<inSettings->dStars; i++){ inSettings->stars[i] = new stretchedParticle; inSettings->stars[i]->radius = rsRandf(float(inSettings->dStarSize) * 0.0005f) + float(inSettings->dStarSize) * 0.0005f; if(i % 10){ // usually bland stars inSettings->stars[i]->color[0] = 0.8f + rsRandf(0.2f); inSettings->stars[i]->color[1] = 0.8f + rsRandf(0.2f); inSettings->stars[i]->color[2] = 0.8f + rsRandf(0.2f); } else{ // occasionally a colorful one inSettings->stars[i]->color[0] = 0.3f + rsRandf(0.7f); inSettings->stars[i]->color[1] = 0.3f + rsRandf(0.7f); inSettings->stars[i]->color[2] = 0.3f + rsRandf(0.7f); inSettings->stars[i]->color[rsRandi(3)] = 1.0f; } inSettings->stars[i]->color[rsRandi(3)] = 1.0f; inSettings->stars[i]->pos[0] = rsRandf(2.0f * inSettings->depth) - inSettings->depth; inSettings->stars[i]->pos[1] = rsRandf(4.0f) - 2.0f; inSettings->stars[i]->pos[2] = rsRandf(2.0f * inSettings->depth) - inSettings->depth; inSettings->stars[i]->fov = float(inSettings->dFov); } inSettings->sunStar = new stretchedParticle; inSettings->sunStar->radius = float(inSettings->dStarSize) * 0.004f; inSettings->sunStar->pos[0] = 0.0f; inSettings->sunStar->pos[1] = 2.0f; inSettings->sunStar->pos[2] = 0.0f; inSettings->sunStar->fov = float(inSettings->dFov); inSettings->theStarBurst = new starBurst; for(int i=0; i<SB_NUM_STARS; i++) inSettings->theStarBurst->stars[i]->radius = rsRandf(float(inSettings->dStarSize) * 0.001f) + float(inSettings->dStarSize) * 0.001f; glGenTextures(1, &inSettings->nebulatex); if(inSettings->dShaders){ initShaders(); inSettings->numAnimTexFrames = 20; glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, inSettings->nebulatex); glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 3, NEBULAMAPSIZE, NEBULAMAPSIZE, GL_RGB, GL_UNSIGNED_BYTE, nebulamap); gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 3, NEBULAMAPSIZE, NEBULAMAPSIZE, GL_RGB, GL_UNSIGNED_BYTE, nebulamap); gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 3, NEBULAMAPSIZE, NEBULAMAPSIZE, GL_RGB, GL_UNSIGNED_BYTE, nebulamap); gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 3, NEBULAMAPSIZE, NEBULAMAPSIZE, GL_RGB, GL_UNSIGNED_BYTE, nebulamap); gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 3, NEBULAMAPSIZE, NEBULAMAPSIZE, GL_RGB, GL_UNSIGNED_BYTE, nebulamap); gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 3, NEBULAMAPSIZE, NEBULAMAPSIZE, GL_RGB, GL_UNSIGNED_BYTE, nebulamap); } else{ //unsigned char spheremap[NEBULAMAPSIZE][NEBULAMAPSIZE][3] = nebulamap; inSettings->numAnimTexFrames = 60; float x, y, temp; const int halfsize(NEBULAMAPSIZE / 2); for(int i=0; i<NEBULAMAPSIZE; ++i){ for(int j=0; j<NEBULAMAPSIZE; ++j){ x = float(i - halfsize) / float(halfsize); y = float(j - halfsize) / float(halfsize); temp = (x * x) + (y * y); if(temp > 1.0f) temp = 1.0f; if(temp < 0.0f) temp = 0.0f; temp = temp * temp; temp = temp * temp; nebulamap[i][j][0] = GLubyte(float(nebulamap[i][j][0]) * temp); nebulamap[i][j][1] = GLubyte(float(nebulamap[i][j][1]) * temp); nebulamap[i][j][2] = GLubyte(float(nebulamap[i][j][2]) * temp); } } glEnable(GL_NORMALIZE); glBindTexture(GL_TEXTURE_2D, inSettings->nebulatex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); gluBuild2DMipmaps(GL_TEXTURE_2D, 3, NEBULAMAPSIZE, NEBULAMAPSIZE, GL_RGB, GL_UNSIGNED_BYTE, nebulamap); } glEnable(GL_FOG); float fog_color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; glFogfv(GL_FOG_COLOR, fog_color); glFogf(GL_FOG_MODE, GL_LINEAR); glFogf(GL_FOG_START, inSettings->depth * 0.7f); glFogf(GL_FOG_END, inSettings->depth); // Initialize text inSettings->textwriter = new rsText; //outfile.open("outfile"); inSettings->readyToDraw = 1; }
void draw(HyperspaceSaverSettings *inSettings){ if(inSettings->first){ if(inSettings->dUseTunnels){ // only tunnels use caustic textures glDisable(GL_FOG); // Caustic textures can only be created after rendering context has been created // because they have to be drawn and then read back from the framebuffer. #ifdef WIN32 if(doingPreview) // super fast for Windows previewer inSettings->theCausticTextures = new causticTextures(8, inSettings->numAnimTexFrames, 32, 32, 1.0f, 0.01f, 10.0f); else // normal #endif inSettings->theCausticTextures = new causticTextures(8, inSettings->numAnimTexFrames, 100, 256, 1.0f, 0.01f, 20.0f); glEnable(GL_FOG); } if(inSettings->dShaders){ #ifdef WIN32 if(doingPreview) // super fast for Windows previewer inSettings->theWNCM = new wavyNormalCubeMaps(inSettings->numAnimTexFrames, 32); else // normal #endif inSettings->theWNCM = new wavyNormalCubeMaps(inSettings->numAnimTexFrames, 128); } glViewport(inSettings->viewport[0], inSettings->viewport[1], inSettings->viewport[2], inSettings->viewport[3]); inSettings->first = 0; } // Variables for printing text static float computeTime = 0.0f; static float drawTime = 0.0f; //static rsTimer computeTimer, drawTimer; // start compute time timer //computeTimer.tick(); glMatrixMode(GL_MODELVIEW); // Camera movements static float camHeading[3] = {0.0f, 0.0f, 0.0f}; // current, target, and last static int changeCamHeading = 1; static float camHeadingChangeTime[2] = {20.0f, 0.0f}; // total, elapsed static float camRoll[3] = {0.0f, 0.0f, 0.0f}; // current, target, and last static int changeCamRoll = 1; static float camRollChangeTime[2] = {1.0f, 0.0f}; // total, elapsed camHeadingChangeTime[1] += inSettings->frameTime; if(camHeadingChangeTime[1] >= camHeadingChangeTime[0]){ // Choose new direction camHeadingChangeTime[0] = rsRandf(15.0f) + 5.0f; camHeadingChangeTime[1] = 0.0f; camHeading[2] = camHeading[1]; // last = target if(changeCamHeading){ // face forward most of the time if(rsRandi(6)) camHeading[1] = 0.0f; // face backward the rest of the time else if(rsRandi(2)) camHeading[1] = RS_PI; else camHeading[1] = -RS_PI; changeCamHeading = 0; } else changeCamHeading = 1; } float t = camHeadingChangeTime[1] / camHeadingChangeTime[0]; t = 0.5f * (1.0f - cosf(RS_PI * t)); camHeading[0] = camHeading[1] * t + camHeading[2] * (1.0f - t); camRollChangeTime[1] += inSettings->frameTime; if(camRollChangeTime[1] >= camRollChangeTime[0]){ // Choose new roll angle camRollChangeTime[0] = rsRandf(5.0f) + 10.0f; camRollChangeTime[1] = 0.0f; camRoll[2] = camRoll[1]; // last = target if(changeCamRoll){ camRoll[1] = rsRandf(RS_PIx2*2) - RS_PIx2; changeCamRoll = 0; } else changeCamRoll = 1; } t = camRollChangeTime[1] / camRollChangeTime[0]; t = 0.5f * (1.0f - cosf(RS_PI * t)); camRoll[0] = camRoll[1] * t + camRoll[2] * (1.0f - t); static float pathDir[3] = {0.0f, 0.0f, -1.0f}; inSettings->thePath->moveAlongPath(float(inSettings->dSpeed) * inSettings->frameTime * 0.04f); inSettings->thePath->update(inSettings->frameTime); inSettings->thePath->getPoint(inSettings->dDepth + 2, inSettings->thePath->step, inSettings->camPos); inSettings->thePath->getBaseDirection(inSettings->dDepth + 2, inSettings->thePath->step, pathDir); float pathAngle = atan2f(-pathDir[0], -pathDir[2]); glLoadIdentity(); glRotatef((pathAngle + camHeading[0]) * RS_RAD2DEG, 0, 1, 0); glRotatef(camRoll[0] * RS_RAD2DEG, 0, 0, 1); glGetFloatv(GL_MODELVIEW_MATRIX, inSettings->billboardMat); glLoadIdentity(); glRotatef(-camRoll[0] * RS_RAD2DEG, 0, 0, 1); glRotatef((-pathAngle - camHeading[0]) * RS_RAD2DEG, 0, 1, 0); glTranslatef(inSettings->camPos[0]*-1, inSettings->camPos[1]*-1, inSettings->camPos[2]*-1); glGetDoublev(GL_MODELVIEW_MATRIX, inSettings->modelMat); inSettings->unroll = camRoll[0] * RS_RAD2DEG; if(inSettings->dUseGoo){ // calculate diagonal fov float diagFov = 0.5f * float(inSettings->dFov) / RS_RAD2DEG; diagFov = tanf(diagFov); diagFov = sqrtf(diagFov * diagFov + (diagFov * inSettings->aspectRatio * diagFov * inSettings->aspectRatio)); diagFov = 2.0f * atanf(diagFov); inSettings->theGoo->update(inSettings->camPos[0], inSettings->camPos[2], pathAngle + camHeading[0], diagFov, inSettings); } // measure compute time //computeTime += computeTimer.tick(); // start draw time timer //drawTimer.tick(); // clear glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // draw stars glCullFace(GL_BACK); glEnable(GL_CULL_FACE); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glBlendFunc(GL_SRC_ALPHA, GL_ONE); glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); glActiveTextureARB(GL_TEXTURE2_ARB); glBindTexture(GL_TEXTURE_2D, NULL); glActiveTextureARB(GL_TEXTURE1_ARB); glBindTexture(GL_TEXTURE_2D, NULL); glActiveTextureARB(GL_TEXTURE0_ARB); glBindTexture(GL_TEXTURE_2D, inSettings->flaretex[0]); static float temppos[2]; for(int i=0; i<inSettings->dStars; i++){ temppos[0] = inSettings->stars[i]->pos[0] - inSettings->camPos[0]; temppos[1] = inSettings->stars[i]->pos[2] - inSettings->camPos[2]; if(temppos[0] > inSettings->depth){ inSettings->stars[i]->pos[0] -= inSettings->depth * 2.0f; inSettings->stars[i]->lastPos[0] -= inSettings->depth * 2.0f; } if(temppos[0] < inSettings->depth*-1){ inSettings->stars[i]->pos[0] += inSettings->depth * 2.0f; inSettings->stars[i]->lastPos[0] += inSettings->depth * 2.0f; } if(temppos[1] > inSettings->depth){ inSettings->stars[i]->pos[2] -= inSettings->depth * 2.0f; inSettings->stars[i]->lastPos[2] -= inSettings->depth * 2.0f; } if(temppos[1] < inSettings->depth*-1){ inSettings->stars[i]->pos[2] += inSettings->depth * 2.0f; inSettings->stars[i]->lastPos[2] += inSettings->depth * 2.0f; } inSettings->stars[i]->draw(inSettings->camPos, inSettings->unroll, inSettings->modelMat, inSettings->projMat, inSettings->viewport); } glDisable(GL_CULL_FACE); // pick animated texture frame static float textureTime = 0.0f; textureTime += inSettings->frameTime; // loop frames every 2 seconds const float texFrameTime(2.0f / float(inSettings->numAnimTexFrames)); while(textureTime > texFrameTime){ textureTime -= texFrameTime; inSettings->whichTexture ++; } while(inSettings->whichTexture >= inSettings->numAnimTexFrames) inSettings->whichTexture -= inSettings->numAnimTexFrames; // alpha component gets normalmap lerp value const float lerp = textureTime / texFrameTime; // draw goo if(inSettings->dUseGoo){ // calculate color static float goo_rgb_phase[3] = {-0.1f, -0.1f, -0.1f}; static float goo_rgb_speed[3] = {rsRandf(0.02f) + 0.02f, rsRandf(0.02f) + 0.02f, rsRandf(0.02f) + 0.02f}; float goo_rgb[4]; for(int i=0; i<3; i++){ goo_rgb_phase[i] += goo_rgb_speed[i] * inSettings->frameTime; if(goo_rgb_phase[i] >= RS_PIx2) goo_rgb_phase[i] -= RS_PIx2; goo_rgb[i] = sinf(goo_rgb_phase[i]); if(goo_rgb[i] < 0.0f) goo_rgb[i] = 0.0f; } // setup textures if(inSettings->dShaders){ goo_rgb[3] = lerp; glDisable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_CUBE_MAP_ARB); glActiveTextureARB(GL_TEXTURE2_ARB); glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, inSettings->nebulatex); glActiveTextureARB(GL_TEXTURE1_ARB); glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, inSettings->theWNCM->texture[(inSettings->whichTexture + 1) % inSettings->numAnimTexFrames]); glActiveTextureARB(GL_TEXTURE0_ARB); glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, inSettings->theWNCM->texture[inSettings->whichTexture]); glUseProgramObjectARB(gooProgram); } else{ goo_rgb[3] = 1.0f; glBindTexture(GL_TEXTURE_2D, inSettings->nebulatex); glEnable(GL_TEXTURE_2D); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); } // draw it glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glBlendFunc(GL_SRC_ALPHA, GL_ONE); glEnable(GL_BLEND); glColor4fv(goo_rgb); inSettings->theGoo->draw(); if(inSettings->dShaders){ glDisable(GL_TEXTURE_CUBE_MAP_ARB); glUseProgramObjectARB(0); } else{ glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); } } // update starburst static float starBurstTime = 300.0f; // burst after 5 minutes starBurstTime -= inSettings->frameTime; if(starBurstTime <= 0.0f){ float pos[] = {inSettings->camPos[0] + (pathDir[0] * inSettings->depth * (0.5f + rsRandf(0.5f))), rsRandf(2.0f) - 1.0f, inSettings->camPos[2] + (pathDir[2] * inSettings->depth * (0.5f + rsRandf(0.5f)))}; inSettings->theStarBurst->restart(pos); // it won't actually restart unless it's ready to starBurstTime = rsRandf(240.0f) + 60.0f; // burst again within 1-5 minutes } if(inSettings->dShaders) inSettings->theStarBurst->draw(lerp, inSettings); else inSettings->theStarBurst->draw(inSettings); // draw tunnel if(inSettings->dUseTunnels){ inSettings->theTunnel->make(inSettings->frameTime, inSettings->dShaders); glCullFace(GL_BACK); glEnable(GL_CULL_FACE); glEnable(GL_TEXTURE_2D); if(inSettings->dShaders){ glActiveTextureARB(GL_TEXTURE1_ARB); glBindTexture(GL_TEXTURE_2D, inSettings->theCausticTextures->caustictex[(inSettings->whichTexture + 1) % inSettings->numAnimTexFrames]); glActiveTextureARB(GL_TEXTURE0_ARB); glBindTexture(GL_TEXTURE_2D, inSettings->theCausticTextures->caustictex[inSettings->whichTexture]); glUseProgramObjectARB(tunnelProgram); inSettings->theTunnel->draw(lerp); glUseProgramObjectARB(0); } else{ glBindTexture(GL_TEXTURE_2D, inSettings->theCausticTextures->caustictex[inSettings->whichTexture]); inSettings->theTunnel->draw(); } glDisable(GL_CULL_FACE); } // draw sun with lens flare glDisable(GL_FOG); float flarepos[3] = {0.0f, 2.0f, 0.0f}; glBindTexture(GL_TEXTURE_2D, inSettings->flaretex[0]); inSettings->sunStar->draw(inSettings->camPos, inSettings->unroll, inSettings->modelMat, inSettings->projMat, inSettings->viewport); float diff[3] = {flarepos[0] - inSettings->camPos[0], flarepos[1] - inSettings->camPos[1], flarepos[2] - inSettings->camPos[2]}; float alpha = 0.5f - 0.005f * sqrtf(diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2]); if(alpha > 0.0f) flare(flarepos, 1.0f, 1.0f, 1.0f, alpha, inSettings); glEnable(GL_FOG); // measure draw time //drawTime += drawTimer.tick(); // write text static float totalTime = 0.0f; totalTime += inSettings->frameTime; static std::vector<std::string> strvec; static int frames = 0; ++frames; if(frames == 60){ strvec.clear(); std::string str1 = " FPS = " + to_string(60.0f / totalTime); strvec.push_back(str1); std::string str2 = "compute time = " + to_string(computeTime / 60.0f); strvec.push_back(str2); std::string str3 = " draw time = " + to_string(drawTime / 60.0f); strvec.push_back(str3); totalTime = 0.0f; computeTime = 0.0f; drawTime = 0.0f; frames = 0; } if(inSettings->kStatistics){ glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0.0f, 50.0f * inSettings->aspectRatio, 0.0f, 50.0f, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glTranslatef(1.0f, 48.0f, 0.0f); glColor3f(1.0f, 0.6f, 0.0f); inSettings->textwriter->draw(strvec); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); } #ifdef WIN32 wglSwapLayerBuffers(hdc, WGL_SWAP_MAIN_PLANE); #endif #ifdef RS_XSCREENSAVER glXSwapBuffers(xdisplay, xwindow); #endif }
void hack_draw (xstuff_t * XStuff, double currentTime, float frameTime) { int i; static int ionsReleased = 0; static float releaseTime = 0.0f; Display *dpy = XStuff->display; #ifdef BENCHMARK static int a = 1; #endif Window window = XStuff->window; elapsedTime = frameTime; #ifdef BENCHMARK if (a++ == 1000) exit(0); elapsedTime = 0.1f; #endif // Camera movements // first do translation (distance from center) static float oldCameraDistance; static float cameraDistance; static float targetCameraDistance = -1000.0f; static float preCameraInterp = PI; float cameraInterp; preCameraInterp += float (dCameraspeed) * elapsedTime * 0.01f; cameraInterp = 0.5f - (0.5f * cos (preCameraInterp)); cameraDistance = (1.0f - cameraInterp) * oldCameraDistance + cameraInterp * targetCameraDistance; if (preCameraInterp >= PI) { oldCameraDistance = targetCameraDistance; targetCameraDistance = -rsRandf (1300.0f) - 200.0f; preCameraInterp = 0.0f; } glMatrixMode (GL_MODELVIEW); glLoadIdentity (); glTranslatef (0.0, 0.0, cameraDistance); // then do rotation static rsVec radialVel = rsVec (0.0f, 0.0f, 0.0f); static rsVec targetRadialVel = radialVel; static rsQuat rotQuat = rsQuat (0.0f, 0.0f, 0.0f, 1.0f); rsVec radialVelDiff = targetRadialVel - radialVel; float changeRemaining = radialVelDiff.normalize (); float change = float (dCameraspeed) * 0.0002f * elapsedTime; if (changeRemaining > change) { radialVelDiff *= change; radialVel += radialVelDiff; } else { radialVel = targetRadialVel; if (rsRandi (2)) { targetRadialVel = rsVec (rsRandf (1.0f), rsRandf (1.0f), rsRandf (1.0f)); targetRadialVel.normalize (); targetRadialVel *= float (dCameraspeed) * rsRandf (0.002f); } else targetRadialVel = rsVec (0.0f, 0.0f, 0.0f); } rsVec tempRadialVel = radialVel; float angle = tempRadialVel.normalize (); rsQuat radialQuat; radialQuat.make (angle, tempRadialVel[0], tempRadialVel[1], tempRadialVel[2]); rotQuat.preMult (radialQuat); rsMatrix rotMat; rotMat.fromQuat (rotQuat); // make billboard matrix for rotating particles when they are drawn rotMat.get (billboardMat); // Calculate new color static rsVec oldHsl, newHsl = rsVec (rsRandf (1.0f), 1.0f, 1.0f), targetHsl; static float colorInterp = 1.0f, colorChange; colorInterp += elapsedTime * colorChange; if (colorInterp >= 1.0f) { if (!rsRandi (3) && dIons >= 100) // change color suddenly newHsl = rsVec (rsRandf (1.0f), 1.0f - (rsRandf (1.0f) * rsRandf (1.0f)), 1.0f); oldHsl = newHsl; targetHsl = rsVec (rsRandf (1.0f), 1.0f - (rsRandf (1.0f) * rsRandf (1.0f)), 1.0f); colorInterp = 0.0f; // amount by which to change colorInterp each second colorChange = rsRandf (0.005f * float (dSpeed)) + (0.002f * float (dSpeed)); } else { float diff = targetHsl[0] - oldHsl[0]; if (diff < -0.5f || (diff > 0.0f && diff < 0.5f)) newHsl[0] = oldHsl[0] + colorInterp * diff; else newHsl[0] = oldHsl[0] - colorInterp * diff; diff = targetHsl[1] - oldHsl[1]; newHsl[1] = oldHsl[1] + colorInterp * diff; if (newHsl[0] < 0.0f) newHsl[0] += 1.0f; if (newHsl[0] > 1.0f) newHsl[0] -= 1.0f; hsl2rgb (newHsl[0], newHsl[1], 1.0f, newRgb[0], newRgb[1], newRgb[2]); } // Release ions if (ionsReleased < dIons) { releaseTime -= elapsedTime; while (ionsReleased < dIons && releaseTime <= 0.0f) { ilist[ionsReleased].start (); ionsReleased++; // all ions released after 2 minutes releaseTime += 120.0f / float (dIons); } } // Set interpolation value for emitters and attracters static float wait = 0.0f; static float preinterp = PI, interp; static float interpconst = 0.001f; wait -= elapsedTime; if (wait <= 0.0f) { preinterp += elapsedTime * float (dSpeed) * interpconst; interp = 0.5f - (0.5f * cos (preinterp)); } if (preinterp >= PI) { // select new taget points (not the same pattern twice in a row) static int newTarget = 0, lastTarget; lastTarget = newTarget; newTarget = rsRandi (10); if (newTarget == lastTarget) newTarget++; setTargets (newTarget); preinterp = 0.0f; interp = 0.0f; wait = 10.0f; // pause after forming each new pattern interpconst = 0.001f; if (!rsRandi (4)) // interpolate really fast sometimes interpconst = 0.1f; } // Update particles for (i = 0; i < dEmitters; i++) { elist[i].interppos (interp); elist[i].update (); } for (i = 0; i < dAttracters; i++) { alist[i].interppos (interp); alist[i].update (); } for (i = 0; i < ionsReleased; i++) ilist[i].update (); // Calculate surface if (dSurface) { for (i = 0; i < dEmitters; i++) spheres[i].setPosition (elist[i].pos[0], elist[i].pos[1], elist[i].pos[2]); for (i = 0; i < dAttracters; i++) spheres[dEmitters + i].setPosition (alist[i].pos[0], alist[i].pos[1], alist[i].pos[2]); impCrawlPointVector cpv; for(i=0; i<dEmitters+dAttracters; i++) spheres[i].addCrawlPoint(cpv); surface->reset (); static float valuetrig = 0.0f; valuetrig += elapsedTime; volume->setSurfaceValue(0.45f + 0.05f * cosf(valuetrig)); volume->makeSurface(cpv); } // Draw // clear the screen if (dBlur) { // partially glMatrixMode (GL_PROJECTION); glPushMatrix (); glLoadIdentity(); glOrtho(0.0, 1.0, 0.0, 1.0, 1.0, -1.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4f(0.0f, 0.0f, 0.0f, 0.5f - (float(sqrtf(sqrtf(float(dBlur)))) * 0.15495f)); glBegin(GL_TRIANGLE_STRIP); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(1.0f, 0.0f, 0.0f); glVertex3f(0.0f, 1.0f, 0.0f); glVertex3f(1.0f, 1.0f, 0.0f); glEnd(); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); } else // completely glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Draw ions glMatrixMode(GL_MODELVIEW); glBlendFunc (GL_ONE, GL_ONE); glBindTexture (GL_TEXTURE_2D, 1); for (i = 0; i < ionsReleased; i++) ilist[i].draw (); // Draw surfaces float brightFactor = 0; float surfaceColor[3] = { 0.0f, 0.0f, 0.0f }; if (dSurface) { glBindTexture (GL_TEXTURE_2D, 2); glEnable (GL_TEXTURE_GEN_S); glEnable (GL_TEXTURE_GEN_T); // find color for surfaces if (dIons >= 100) { if (dWireframe) brightFactor = 2.0f / (float (dBlur + 30) * float (dBlur + 30)); else brightFactor = 4.0f / (float (dBlur + 30) * float (dBlur + 30)); for (i = 0; i < 100; i++) { surfaceColor[0] += ilist[i].rgb[0] * brightFactor; surfaceColor[1] += ilist[i].rgb[1] * brightFactor; surfaceColor[2] += ilist[i].rgb[2] * brightFactor; } glColor3fv (surfaceColor); } else { if (dWireframe) brightFactor = 200.0f / (float (dBlur + 30) * float (dBlur + 30)); else brightFactor = 400.0f / (float (dBlur + 30) * float (dBlur + 30)); glColor3f (newRgb[0] * brightFactor, newRgb[1] * brightFactor, newRgb[2] * brightFactor); } // draw the surface glPushMatrix (); glMultMatrixf (billboardMat); if (dWireframe) { glDisable (GL_TEXTURE_2D); surface->draw_wireframe (); glEnable (GL_TEXTURE_2D); } else surface->draw (); glPopMatrix (); glDisable (GL_TEXTURE_GEN_S); glDisable (GL_TEXTURE_GEN_T); } // If graphics card does a true buffer swap instead of a copy swap // then everything must get drawn on both buffers if (dBlur & pfd_swap_exchange) { glXSwapBuffers (dpy, window); // wglSwapLayerBuffers(hdc, WGL_SWAP_MAIN_PLANE); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4f (0.0f, 0.0f, 0.0f, 0.5f - (float (sqrt (sqrt (double (dBlur)))) * 0.15495f)); glPushMatrix (); glLoadIdentity (); glBegin (GL_TRIANGLE_STRIP); glVertex3f (-5.0f, -4.0f, -3.0f); glVertex3f (5.0f, -4.0f, -3.0f); glVertex3f (-5.0f, 4.0f, -3.0f); glVertex3f (5.0f, 4.0f, -3.0f); glEnd (); glPopMatrix (); // Draw ions glBlendFunc (GL_ONE, GL_ONE); glBindTexture (GL_TEXTURE_2D, 1); for (i = 0; i < ionsReleased; i++) ilist[i].draw (); // Draw surfaces if (dSurface) { glBindTexture (GL_TEXTURE_2D, 2); glEnable (GL_TEXTURE_GEN_S); glEnable (GL_TEXTURE_GEN_T); if (dIons >= 100) glColor3fv (surfaceColor); else glColor3f (newRgb[0] * brightFactor, newRgb[1] * brightFactor, newRgb[2] * brightFactor); glPushMatrix (); glMultMatrixf (billboardMat); if (dWireframe) { glDisable (GL_TEXTURE_2D); surface->draw_wireframe (); glEnable (GL_TEXTURE_2D); } else surface->draw (); glPopMatrix (); glDisable (GL_TEXTURE_GEN_S); glDisable (GL_TEXTURE_GEN_T); } } }
void setTargets (int whichTarget) { int i; switch (whichTarget) { case 0: // random for (i = 0; i < dEmitters; i++) elist[i].settargetpos (rsVec (rsVec (rsRandf (1000.0f) - 500.0f, rsRandf (1000.0f) - 500.0f, rsRandf (1000.0f) - 500.0f))); for (i = 0; i < dAttracters; i++) alist[i].settargetpos (rsVec (rsVec (rsRandf (1000.0f) - 500.0f, rsRandf (1000.0f) - 500.0f, rsRandf (1000.0f) - 500.0f))); break; case 1: { // line (all emitters on one side, all attracters on the other) float position = -500.0f, change = 1000.0f / float (dEmitters + dAttracters - 1); for (i = 0; i < dEmitters; i++) { elist[i].settargetpos (rsVec (rsVec (position, position * 0.5f, 0.0f))); position += change; } for (i = 0; i < dAttracters; i++) { alist[i].settargetpos (rsVec (rsVec (position, position * 0.5f, 0.0f))); position += change; } break; } case 2: { // line (emitters and attracters staggered) float change; if (dEmitters > dAttracters) { change = 1000.0f / float (dEmitters * 2 - 1); } else { change = 1000.0f / float (dAttracters * 2 - 1); } float position = -500.0f; for (i = 0; i < dEmitters; i++) { elist[i].settargetpos (rsVec (rsVec (position, position * 0.5f, 0.0f))); position += change * 2.0f; } position = -500.0f + change; for (i = 0; i < dAttracters; i++) { alist[i].settargetpos (rsVec (rsVec (position, position * 0.5f, 0.0f))); position += change * 2.0f; } break; } case 3: { // 2 lines (parallel) float change = 1000.0f / float (dEmitters * 2 - 1); float position = -500.0f; float height = -525.0f + float (dEmitters * 25); for (i = 0; i < dEmitters; i++) { elist[i].settargetpos (rsVec (rsVec (position, height, -50.0f))); position += change * 2.0f; } change = 1000.0f / float (dAttracters * 2 - 1); position = -500.0f; height = 525.0f - float (dAttracters * 25); for (i = 0; i < dAttracters; i++) { alist[i].settargetpos (rsVec (rsVec (position, height, 50.0f))); position += change * 2.0f; } break; } case 4: { // 2 lines (skewed) float change = 1000.0f / float (dEmitters * 2 - 1); float position = -500.0f; float height = -525.0f + float (dEmitters * 25); for (i = 0; i < dEmitters; i++) { elist[i].settargetpos (rsVec (rsVec (position, height, 0.0f))); position += change * 2.0f; } change = 1000.0f / float (dAttracters * 2 - 1); position = -500.0f; height = 525.0f - float (dAttracters * 25); for (i = 0; i < dAttracters; i++) { alist[i].settargetpos (rsVec (rsVec (10.0f, height, position))); position += change * 2.0f; } break; } case 5: // random distribution across a plane for (i = 0; i < dEmitters; i++) elist[i].settargetpos (rsVec (rsVec (rsRandf (1000.0f) - 500.0f, 0.0f, rsRandf (1000.0f) - 500.0f))); for (i = 0; i < dAttracters; i++) alist[i].settargetpos (rsVec (rsVec (rsRandf (1000.0f) - 500.0f, 0.0f, rsRandf (1000.0f) - 500.0f))); break; case 6: { // random distribution across 2 planes float height = -525.0f + float (dEmitters * 25); for (i = 0; i < dEmitters; i++) elist[i].settargetpos (rsVec (rsVec (rsRandf (1000.0f) - 500.0f, height, rsRandf (1000.0f) - 500.0f))); height = 525.0f - float (dAttracters * 25); for (i = 0; i < dAttracters; i++) alist[i].settargetpos (rsVec (rsVec (rsRandf (1000.0f) - 500.0f, height, rsRandf (1000.0f) - 500.0f))); break; } case 7: { // 2 rings (1 inside and 1 outside) float angle = 0.5f, cosangle, sinangle; float change = PIx2 / float (dEmitters); for (i = 0; i < dEmitters; i++) { angle += change; cosangle = cos (angle) * 200.0f; sinangle = sin (angle) * 200.0f; elist[i].settargetpos (rsVec (rsVec (cosangle, sinangle, 0.0f))); } angle = 1.5f; change = PIx2 / float (dAttracters); for (i = 0; i < dAttracters; i++) { angle += change; cosangle = cos (angle) * 500.0f; sinangle = sin (angle) * 500.0f; alist[i].settargetpos (rsVec (rsVec (cosangle, sinangle, 0.0f))); } break; } case 8: { // ring (all emitters on one side, all attracters on the other) float angle = 0.5f, cosangle, sinangle; float change = PIx2 / float (dEmitters + dAttracters); for (i = 0; i < dEmitters; i++) { angle += change; cosangle = cos (angle) * 500.0f; sinangle = sin (angle) * 500.0f; elist[i].settargetpos (rsVec (rsVec (cosangle, sinangle, 0.0f))); } for (i = 0; i < dAttracters; i++) { angle += change; cosangle = cos (angle) * 500.0f; sinangle = sin (angle) * 500.0f; alist[i].settargetpos (rsVec (rsVec (cosangle, sinangle, 0.0f))); } break; } case 9: { // ring (emitters and attracters staggered) float change; if (dEmitters > dAttracters) { change = PIx2 / float (dEmitters * 2); } else { change = PIx2 / float (dAttracters * 2); } float angle = 0.5f, cosangle, sinangle; for (i = 0; i < dEmitters; i++) { cosangle = cos (angle) * 500.0f; sinangle = sin (angle) * 500.0f; elist[i].settargetpos (rsVec (rsVec (cosangle, sinangle, 0.0f))); angle += change * 2.0f; } angle = 0.5f + change; for (i = 0; i < dAttracters; i++) { cosangle = cos (angle) * 500.0f; sinangle = sin (angle) * 500.0f; alist[i].settargetpos (rsVec (rsVec (cosangle, sinangle, 0.0f))); angle += change * 2.0f; } break; } case 10: // 2 points for (i = 0; i < dEmitters; i++) elist[i].settargetpos (rsVec (rsVec (500.0f, 100.0f, 50.0f))); for (i = 0; i < dAttracters; i++) alist[i].settargetpos (rsVec (rsVec (-500.0f, -100.0f, -50.0f))); break; } }
attracter::attracter () { pos = rsVec (rsRandf (1000.0f) - 500.0f, rsRandf (1000.0f) - 500.0f, rsRandf (1000.0f) - 500.0f); }
void SceneManager::FrameMove() { //更新时间 static int index = 0; if(m_Stop)return;//暂停动画 frameTime = m_Timer.tick(); //更新粒子系统 // Slows fireworks, but not camera if(kSlowMotion) frameTime *= 0.5f; if(m_Fps!=0) { frameTime = 1/(float)m_Fps; } //更新照像机 m_Camera.Update(m_ParticleSystem.particles,frameTime,m_ParticleSystem.last_particle); m_ParticleSystem.AllocNewParticle();//增加新粒子空间 //是否暂停动画 if(!kFireworks) return; //如果暂停动画返回 //更新世界 theWorld.update(frameTime); //减淡 static float ambientlight = float(dAmbient) * 0.01f; for(unsigned int i=0; i<m_ParticleSystem.last_particle; ++i) { Particle* darkener(&(m_ParticleSystem.particles[i])); if(darkener->type == SMOKE) darkener->rgb[0] = darkener->rgb[1] = darkener->rgb[2] = ambientlight; } //改变火箭发射速率 static float rocketTimer[6] = {0,0,0,0,0,0}; static float rocketTimeConst[6] = {5.0f,25,40,35,50,55}; static float changeRocketTimeConst[6] ={25,50,65,65,50,50}; for(int i=0;i<6;i++) { changeRocketTimeConst[i] -= frameTime; if(changeRocketTimeConst[i] <= 0.0f) { float temp = rsRandf(4.0f); //rocketTimeConst[i] = (temp * temp) + (10.0f / float(dMaxrockets)); changeRocketTimeConst[i] = rsRandf(30.0f) + 10.0f; } rocketTimer[i] -= frameTime; } //发射火箭 if(rocketTimer[0] <= 0.0f)//生存期结束 { Particle* rock = m_ParticleSystem.AddParticle();//火箭粒子 //初始化火箭 //确定火箭类型 rock->xyz[0] = rsRandf(20.0f);// - 900.0f; rock->xyz[1] = 5.0f; rock->xyz[2] = rsRandf(20.0f);// - 900.0f; rock->initRocket(); int y =rsRandi(8); if(index==2) { rock->explosiontype =6; } else if(index==5) { rock->explosiontype =6; } else if(index==8) { rock->explosiontype =6; } else { rock->m_Fire = &m_CFire[index]; m_CFire[index].m_Exploded = false;//未爆炸 m_CFire[index].m_Boom = false; rock->explosiontype =22; } index++; index = index%11; if(dMaxrockets) rocketTimer[0] = rocketTimeConst[0];//火箭时间 else rocketTimer[0] = 60.0f; // arbitrary number since no rockets ever fire } /*if(rocketTimer[1] <= 0.0f)//生存期结束 { Particle* rock = m_ParticleSystem.AddParticle();//火箭粒子 //初始化火箭 //确定火箭类型 rock->xyz[0] = rsRandf(200.0f);// + 800.0f; rock->xyz[1] = 5.0f; rock->xyz[2] = rsRandf(200.0f);// + 500.0f; rock->initRocket(); if(rsRandi(2)) rock->m_Fire = &m_CFire[1]; else rock->m_Fire = &m_CFire[5]; rock->explosiontype = 22; if(dMaxrockets) rocketTimer[1] = rsRandf(rocketTimeConst[1]);//火箭时间 else rocketTimer[1] = 60.0f; // arbitrary number since no rockets ever fire } if(rocketTimer[2] <= 0.0f)//生存期结束 { Particle* rock = m_ParticleSystem.AddParticle();//火箭粒子 //初始化火箭 //确定火箭类型 rock->xyz[0] = rsRandf(200.0f) + 700.0f; rock->xyz[1] = 5.0f; rock->xyz[2] = rsRandf(200.0f) - 500.0f; rock->initRocket(); if(rsRandi(2)) rock->m_Fire = &m_CFire[2]; else rock->m_Fire = &m_CFire[6]; rock->explosiontype = 22; if(dMaxrockets) rocketTimer[2] = rsRandf(rocketTimeConst[2]);//火箭时间 else rocketTimer[2] = 60.0f; // arbitrary number since no rockets ever fire } if(rocketTimer[3] <= 0.0f)//生存期结束 { Particle* rock = m_ParticleSystem.AddParticle();//火箭粒子 //初始化火箭 //确定火箭类型 rock->xyz[0] = rsRandf(200.0f) - 500.0f; rock->xyz[1] = 5.0f; rock->xyz[2] = rsRandf(200.0f) + 700.0f; rock->initRocket(); if(rsRandi(2)) rock->m_Fire = &m_CFire[3]; else rock->m_Fire = &m_CFire[7]; rock->explosiontype = 22; if(dMaxrockets) rocketTimer[3] = rsRandf(rocketTimeConst[3]);//火箭时间 else rocketTimer[3] = 60.0f; // arbitrary number since no rockets ever fire } if(rocketTimer[4] <= 0.0f)//生存期结束 { Particle* rock = m_ParticleSystem.AddParticle();//火箭粒子 //初始化火箭 //确定火箭类型 rock->xyz[0] = rsRandf(200.0f) - 1000.0f; rock->xyz[1] = 5.0f; rock->xyz[2] = rsRandf(200.0f) + 500.0f; rock->initRocket(); rock->explosiontype = 3; if(dMaxrockets) rocketTimer[4] = rsRandf(rocketTimeConst[4]);//火箭时间 else rocketTimer[4] = 60.0f; // arbitrary number since no rockets ever fire } if(rocketTimer[5] <= 0.0f)//生存期结束 { Particle* rock = m_ParticleSystem.AddParticle();//火箭粒子 //初始化火箭 //确定火箭类型 rock->xyz[0] = rsRandf(200.0f) - 1300.0f; rock->xyz[1] = 5.0f; rock->xyz[2] = rsRandf(200.0f) + 500.0f; rock->initRocket(); rock->explosiontype = 4; if(dMaxrockets) rocketTimer[5] = rsRandf(rocketTimeConst[5]);//火箭时间 else rocketTimer[5] = 60.0f; // arbitrary number since no rockets ever fire } */ //更新粒子 numRockets = 0; for(unsigned int i=0; i<m_ParticleSystem.last_particle; i++) { Particle* curpart(&(m_ParticleSystem.particles[i])); m_ParticleSystem.particles[i].update(frameTime,dSmoke,dClouds,dWind,dAmbient,dIllumination,&theWorld); if(curpart->type == ROCKET) numRockets++; // curpart->findDepth(m_Camera.cameraPos,billboardMat); if(curpart->type==IGNITOR&&curpart->life <0.93) { if(!curpart->m_Fire->m_Exploded)//未爆炸 { if(IsRecord()) { m_PlayTime.push_back(m_Frame*m_f);//记录时间 m_PlayStyle.push_back(BOOM1SOUND );//记录类型 m_PlayPos.push_back(m_Camera.cameraPos); m_PlaySource.push_back(curpart->xyz); soundengine->insertSoundNode(BOOM1SOUND , curpart->xyz, m_Camera.cameraPos); m_PlayTime.push_back(m_Frame*m_f);//记录时间 m_PlayStyle.push_back(SUCKSOUND);//记录类型 m_PlayPos.push_back(m_Camera.cameraPos); m_PlaySource.push_back(curpart->xyz); soundengine->insertSoundNode(SUCKSOUND, curpart->xyz,m_Camera.cameraPos); } else { //播放声音 soundengine->insertSoundNode(BOOM1SOUND, curpart->xyz, m_Camera.cameraPos); soundengine->insertSoundNode(SUCKSOUND , curpart->xyz, m_Camera.cameraPos); } curpart->m_Fire->m_Exploded = true; } } if(curpart->m_Fire!=NULL&&curpart->type==ROCKET&&curpart->life <0.43) { if(!curpart->m_Fire->m_Boom)//未爆炸 { if(IsRecord()) { m_PlayTime.push_back(m_Frame*m_f);//记录时间 m_PlayStyle.push_back(BOOM1SOUND );//记录类型 m_PlayPos.push_back(m_Camera.cameraPos); m_PlaySource.push_back(curpart->xyz); soundengine->insertSoundNode(BOOM1SOUND , curpart->xyz, m_Camera.cameraPos); } else { //播放声音 soundengine->insertSoundNode(BOOM1SOUND, curpart->xyz, m_Camera.cameraPos); } curpart->m_Fire->m_Boom = true; } } //点燃烟花 if(curpart->life <= 0.0f || curpart->xyz[1] < 0.0f) { switch(curpart->type) { case ROCKET: if(curpart->xyz[1] <= 0.0f) { // move above ground for explosion so new particles aren't removed curpart->xyz[1] = 0.1f; curpart->vel[1] *= -0.7f; } if(curpart->explosiontype == 18) curpart->initSpinner(); else { curpart->initExplosion(); } break; case IGNITOR: curpart->m_Fire->m_Ignitor++; if(curpart->m_Fire->m_Ignitor==8) { curpart->m_Fire->m_Ignitor = 0; curpart->explosiontype = 0; curpart->initExplosion(); curpart->explosiontype = 21; curpart->initExplosion(); } else { curpart->explosiontype = 0; curpart->initExplosion(); } break; case POPPER: switch(curpart->explosiontype) { case 21: curpart->initExplosion(); break; case STAR: curpart->explosiontype = 100; curpart->initExplosion(); break; case STREAMER: curpart->explosiontype = 101; curpart->initExplosion(); break; case METEOR: curpart->explosiontype = 102; curpart->initExplosion(); break; case POPPER: curpart->type = STAR; curpart->rgb.set(1.0f, 0.8f, 0.6f); curpart->t = m_ParticleSystem.particles[i].tr = m_ParticleSystem.particles[i].life = 0.2f; } break; case SUCKER: curpart->initShockwave(); break; case STRETCHER: curpart->initBigmama(); } } } m_ParticleSystem.DeallocParticle();//删除粒子 }
void setMaterialAttribs(){ if(dTexture == 0 || dTexture >= 5) glColor3f(rsRandf(1.0f), rsRandf(1.0f), rsRandf(1.0f)); if(dTexture == 1) glBindTexture(GL_TEXTURE_2D, texture_id[rsRandi(2)]); }
void drawWorld () { int i, j; static float moonRotation = rsRandf (360.0f); static float moonHeight = rsRandf (40.0f) + 20.0f; glMatrixMode (GL_MODELVIEW);; glDisable (GL_DEPTH_TEST); // draw stars if (dStardensity) { glDisable (GL_BLEND); glCallList (starlist); } // draw moon if (dMoon) { glPushMatrix (); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glRotatef (moonRotation, 0, 1, 0); glRotatef (moonHeight, 1, 0, 0); glTranslatef (0.0f, 0.0f, -20000.0f); glCallList (moonlist); glPopMatrix (); } // draw clouds if (dClouds) { glPushMatrix (); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBindTexture (GL_TEXTURE_2D, cloudtex); glTranslatef (0.0f, 0.0f, 0.0f); for (j = 0; j < CLOUDMESH; j++) { glBegin (GL_TRIANGLE_STRIP); for (i = 0; i <= CLOUDMESH; i++) { glColor3f (clouds[i][j + 1][6], clouds[i][j + 1][7], clouds[i][j + 1][8]); glTexCoord2f (clouds[i][j + 1][3], clouds[i][j + 1][4]); glVertex3fv (clouds[i][j + 1]); glColor3f (clouds[i][j][6], clouds[i][j][7], clouds[i][j][8]); glTexCoord2f (clouds[i][j][3], clouds[i][j][4]); glVertex3fv (clouds[i][j]); } glEnd (); } glPopMatrix (); } // draw sunset if (doSunset) { glEnable (GL_BLEND); glBlendFunc (GL_ONE, GL_ONE); glCallList (sunsetlist); } // draw moon's halo if (dMoonglow && dMoon) { glPushMatrix (); float glow = float (dMoonglow) * 0.005f; // half of max possible value glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE); glRotatef (moonRotation, 0, 1, 0); glRotatef (moonHeight, 1, 0, 0); glTranslatef (0.0f, 0.0f, -20000.0f); glColor4f (1.0f, 1.0f, 1.0f, glow); glCallList (moonglowlist); // halo glScalef (6000.0f, 6000.0f, 6000.0f); glColor4f (1.0f, 1.0f, 1.0f, glow * 0.7f); glCallList (flarelist[0]); // spot glPopMatrix (); } // draw earth if (dEarth) { glPushMatrix (); glDisable (GL_BLEND); glBindTexture (GL_TEXTURE_2D, earthneartex); glCallList (earthnearlist); glBindTexture (GL_TEXTURE_2D, earthfartex); glCallList (earthfarlist); if (dAmbient <= 30) { glEnable (GL_BLEND); glBlendFunc (GL_ONE, GL_ONE); glBindTexture (GL_TEXTURE_2D, earthlighttex); glCallList (earthlist); } glPopMatrix (); } }
void draw () { int i, j, k; int indexx, indexy, indexz; float xyz[4], dir[4], angvel[4], tempVec[4]; static float oldxyz[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; static float oldDir[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; static float oldAngvel[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; float angle, distance; float rotMat[16]; float newQuat[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; static float quat[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; static int flymode = 1; static float flymodeChange = 20.0f; static int seg = 0; /* Section of path */ static float where = 0.0f; /* Position on path */ static float rollVel = 0.0f, rollAcc = 0.0f; int drawDepth = dDrawdepth + 2; static float rollChange = 0; /* rsRandf (10.0f) + 2.0f; */ where += (float)dSpeed * 0.05f * elapsedTime; if (where >= 1.0f) { where -= 1.0f; seg++; } if (seg >= segments) { seg = 0; reconfigure (); } /* * Calculate position */ xyz[0] = interpolate (path[seg][0], path[seg][3], path[seg + 1][0], path[seg + 1][3], where); xyz[1] = interpolate (path[seg][1], path[seg][4], path[seg + 1][1], path[seg + 1][4], where); xyz[2] = interpolate (path[seg][2], path[seg][5], path[seg + 1][2], path[seg + 1][5], where); /* * Do rotation stuff */ rsVec_subtract (xyz, oldxyz, (float *)&dir); rsVec_normalize ((float *)&dir); rsVec_cross ((float *)&angvel, dir, oldDir); /* Desired axis of rotation */ /* Protect against mild "overflow" */ float dot = MAX(MIN(rsVec_dot (oldDir, dir), -1.0), 1.0); float maxSpin = 0.25f * (float)dSpeed * elapsedTime; angle = MAX(MIN(acos(dot), -maxSpin), maxSpin); rsVec_scale ((float *)&angvel, angle); /* Desired angular velocity */ rsVec_subtract (angvel, oldAngvel, (float *)&tempVec); /* Change in angular velocity */ distance = rsVec_length (tempVec); /* Don't let angular velocity change too much */ float rotationInertia = 0.007f * (float)dSpeed * elapsedTime; if (distance > rotationInertia * elapsedTime) { rsVec_scale ((float *)&tempVec, ((rotationInertia * elapsedTime) / distance)); rsVec_add (oldAngvel, tempVec, (float *)&angvel); } flymodeChange -= elapsedTime; if (flymodeChange <= 1.0f) /* prepare to transition */ rsVec_scale ((float *)&angvel, flymodeChange); if (flymodeChange <= 0.0f) { /* transition from one fly mode to * the other? */ flymode = rsRandi (4); flymodeChange = rsRandf ((float)(150 - dSpeed)) + 5.0f; } rsVec_copy (angvel, (float *)&tempVec); /* Recompute desired rotation */ angle = rsVec_normalize ((float *)&tempVec); rsQuat_make ((float *)&newQuat, angle, tempVec[0], tempVec[1], tempVec[2]); /* Use rotation */ if (flymode) /* fly normal (straight) */ rsQuat_preMult ((float *)&quat, newQuat); else /* don't fly normal (go backwards and stuff) */ rsQuat_postMult ((float *)&quat, newQuat); /* Roll */ rollChange -= elapsedTime; if (rollChange <= 0.0f) { rollAcc = rsRandf (0.02f * (float)dSpeed) - (0.01f * (float)dSpeed); rollChange = rsRandf (10.0f) + 2.0f; } rollVel += rollAcc * elapsedTime; if (rollVel > (0.04f * (float)dSpeed) && rollAcc > 0.0f) rollAcc = 0.0f; if (rollVel < (-0.04f * (float)dSpeed) && rollAcc < 0.0f) rollAcc = 0.0f; rsQuat_make ((float *)&newQuat, rollVel * elapsedTime, oldDir[0], oldDir[1], oldDir[2]); rsQuat_preMult ((float *)&quat, newQuat); /* quat.normalize(); */ rsQuat_toMat ((float *)&quat, (float *)&rotMat); /* * Save old stuff */ rsVec_copy (xyz, (float *)&oldxyz); oldDir[0] = -rotMat[2]; oldDir[1] = -rotMat[6]; oldDir[2] = -rotMat[10]; rsVec_copy (angvel, (float *)&oldAngvel); /* * Apply transformations */ glMatrixMode (GL_MODELVIEW); glLoadMatrixf (rotMat); glTranslatef (-xyz[0], -xyz[1], -xyz[2]); // Just in case display lists contain no colors glColor3f(1.0f, 1.0f, 1.0f); // Environment mapping for crystal, chrome, brass, shiny, and ghostly if(dTexture == 2 || dTexture == 3 || dTexture == 4 || dTexture == 5 || dTexture == 6){ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); } /* * Render everything */ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (i = globalxyz[0] - drawDepth; i <= globalxyz[0] + drawDepth; i++) { for (j = globalxyz[1] - drawDepth; j <= globalxyz[1] + drawDepth; j++) { for (k = globalxyz[2] - drawDepth; k <= globalxyz[2] + drawDepth; k++) { float tpos[4]; /* transformed position */ tempVec[0] = (float)i - xyz[0]; tempVec[1] = (float)j - xyz[1]; tempVec[2] = (float)k - xyz[2]; tpos[0] = tempVec[0] * rotMat[0] + tempVec[1] * rotMat[4] + tempVec[2] * rotMat[8]; /* + rotMat[12]; */ tpos[1] = tempVec[0] * rotMat[1] + tempVec[1] * rotMat[5] + tempVec[2] * rotMat[9]; /* + rotMat[13]; */ tpos[2] = tempVec[0] * rotMat[2] + tempVec[1] * rotMat[6] + tempVec[2] * rotMat[10]; /* + rotMat[14]; */ #define radius 0.9f /* camera_inViewVolume */ /* * check back plane */ if (!(tpos[2] < -(theCamera.farplane + radius))) { /* * check bottom plane */ if (!(rsVec_dot(tpos, theCamera.cullVec[0]) < -radius)) { /* * check top plane */ if (!(rsVec_dot(tpos, theCamera.cullVec[1]) < -radius)) { /* * check left plane */ if (!(rsVec_dot(tpos, theCamera.cullVec[2]) < -radius)) { /* * check right plane */ if (!(rsVec_dot(tpos, theCamera.cullVec[3]) < -radius)) { indexx = myMod (i); indexy = myMod (j); indexz = myMod (k); /* * draw it */ glPushMatrix (); glTranslatef ((float)i, (float)j, (float)k); glCallList (lattice[indexx][indexy][indexz]); glPopMatrix (); } } } } } } } } glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glFlush (); }
bool ConstrainedFire::GenerateParticle(Particle * & particle) { bool control = false; int k =m_K; int objectIndex; //当前欲定位的模型顶点索引 //选取形状受控的粒子(为模型顶点分配粒子) if(m_MatchNum[currentEmitter]<(int)m_Quadrant[currentEmitter].size()) { //设当前粒子为受控粒子 control = true; objectIndex = m_Quadrant[currentEmitter][m_MatchNum[currentEmitter]]; m_MatchNum[currentEmitter]++; } else currentEmitter++; if(currentEmitter==m_K)currentEmitter=0; //设置当前发射器 if(!control) { // if(currentEmitter==SEC_EMITTER) currentEmitter=0; return false;//非约束粒子 } //设置约束粒子属性 if(control) particle = m_ParticleSystem->AddParticle(); particle->controlled = true; //粒子生命值 particle->t = particle->tr = 1.2f +rsRandf(0.6)*0.5; particle->life = 1.0f; particle->type = SHAPE; //爆炸位置 particle->xyz[0] = expEmitter[currentEmitter].explodePos.X(); particle->xyz[1] = expEmitter[currentEmitter].explodePos.Y(); particle->xyz[2] = expEmitter[currentEmitter].explodePos.Z(); //爆炸物理属性 particle->force = expEmitter[currentEmitter].force;//作用力(重力) particle->k = expEmitter[currentEmitter].k;//空气阻力 ///对于x和z方向,为匀速运动,s=vt。 //对于y方向,加速度是重力加速度g, s=v0*t+1/2*gt^2 //基于物理,为新添加的形状受控粒子计算常量C float speed,explodespeed; float d; //XY平面上的角度,0-360 float fi; //与Z的夹角,0-180 float ts; float sx,sy,sz; float rt,t2; rt=1.0/particle->t; //粒子生命值的倒数 t2=particle->t*particle->t; //生命值的平方 float T = particle->t; float T0 = particle->t - particle->t*rsRandf(0.2)*0.5;//成形时间 float ktp1=particle->k*T+1.0; float w = (pow(T,ktp1) - pow(T - T0, ktp1)); sx = m_Vertices[objectIndex].position.X()+m_Center.X()-particle->xyz[0]; sy = m_Vertices[objectIndex].position.Y()+m_Center.Y()-particle->xyz[1]-20; sz = m_Vertices[objectIndex].position.Z()+m_Center.Z()-particle->xyz[2]; particle->C.X()=sx*ktp1/w; particle->C.Y()=(sy- particle->force.Y()*(2*T-T0)*T/(2*(ktp1-2.0))) * (ktp1/w); particle->C.Z()=sz*ktp1/w; //为新添加的形状受控粒子计算速度的初始值 particle->vel[0] = particle->C.X(); particle->vel[1] = particle->force.Y()*T/(particle->k*T-1.0)+particle->C.Y()*pow(T,particle->k*T); particle->vel[2] = particle->C.Z(); return true; }