void CLargeBeamLaserProjectile::Draw() { inArray = true; const float3 cameraDir = (pos - camera->pos).SafeANormalize(); // beam's coor-system; degenerate if targetPos == startPos const float3 zdir = (targetPos - startpos).SafeANormalize(); const float3 xdir = (cameraDir.cross(zdir)).SafeANormalize(); const float3 ydir = (cameraDir.cross(xdir)); float3 pos1 = startpos; float3 pos2 = targetPos; const float startTex = 1.0f - ((gu->modGameTime * scrollspeed) - int(gu->modGameTime * scrollspeed)); const float texSizeX = beamtex.xend - beamtex.xstart; const float beamEdgeSize = thickness; const float beamCoreSize = beamEdgeSize * corethickness; const float beamLength = (targetPos - startpos).dot(zdir); const float flareEdgeSize = thickness * flaresize; const float flareCoreSize = flareEdgeSize * corethickness; const float beamTileMinDst = tilelength * (1.0f - startTex); const float beamTileMaxDst = beamLength - tilelength; // note: beamTileMaxDst can be negative, in which case we want numBeamTiles to equal zero const float numBeamTiles = std::floor(((std::max(beamTileMinDst, beamTileMaxDst) - beamTileMinDst) / tilelength) + 0.5f); AtlasedTexture tex = beamtex; va->EnlargeArrays(64 + (8 * (int((beamTileMaxDst - beamTileMinDst) / tilelength) + 2)), 0, VA_SIZE_TC); #define WT2 weaponDef->visuals.texture2 #define WT4 weaponDef->visuals.texture4 if (beamTileMinDst > beamLength) { // beam short enough to be drawn by one polygon // draw laser start tex.xstart = beamtex.xstart + startTex * texSizeX; va->AddVertexQTC(pos1 - (xdir * beamEdgeSize), tex.xstart, tex.ystart, edgeColStart); va->AddVertexQTC(pos1 + (xdir * beamEdgeSize), tex.xstart, tex.yend, edgeColStart); va->AddVertexQTC(pos2 + (xdir * beamEdgeSize), tex.xend, tex.yend, edgeColStart); va->AddVertexQTC(pos2 - (xdir * beamEdgeSize), tex.xend, tex.ystart, edgeColStart); va->AddVertexQTC(pos1 - (xdir * beamCoreSize), tex.xstart, tex.ystart, coreColStart); va->AddVertexQTC(pos1 + (xdir * beamCoreSize), tex.xstart, tex.yend, coreColStart); va->AddVertexQTC(pos2 + (xdir * beamCoreSize), tex.xend, tex.yend, coreColStart); va->AddVertexQTC(pos2 - (xdir * beamCoreSize), tex.xend, tex.ystart, coreColStart); } else { // beam longer than one polygon pos2 = pos1 + zdir * beamTileMinDst; // draw laser start tex.xstart = beamtex.xstart + startTex * texSizeX; va->AddVertexQTC(pos1 - (xdir * beamEdgeSize), tex.xstart, tex.ystart, edgeColStart); va->AddVertexQTC(pos1 + (xdir * beamEdgeSize), tex.xstart, tex.yend, edgeColStart); va->AddVertexQTC(pos2 + (xdir * beamEdgeSize), tex.xend, tex.yend, edgeColStart); va->AddVertexQTC(pos2 - (xdir * beamEdgeSize), tex.xend, tex.ystart, edgeColStart); va->AddVertexQTC(pos1 - (xdir * beamCoreSize), tex.xstart, tex.ystart, coreColStart); va->AddVertexQTC(pos1 + (xdir * beamCoreSize), tex.xstart, tex.yend, coreColStart); va->AddVertexQTC(pos2 + (xdir * beamCoreSize), tex.xend, tex.yend, coreColStart); va->AddVertexQTC(pos2 - (xdir * beamCoreSize), tex.xend, tex.ystart, coreColStart); // draw continous beam tex.xstart = beamtex.xstart; for (float i = beamTileMinDst; i < beamTileMaxDst; i += tilelength) { //! CAUTION: loop count must match EnlargeArrays above pos1 = startpos + zdir * i; pos2 = startpos + zdir * (i + tilelength); va->AddVertexQTC(pos1 - (xdir * beamEdgeSize), tex.xstart, tex.ystart, edgeColStart); va->AddVertexQTC(pos1 + (xdir * beamEdgeSize), tex.xstart, tex.yend, edgeColStart); va->AddVertexQTC(pos2 + (xdir * beamEdgeSize), tex.xend, tex.yend, edgeColStart); va->AddVertexQTC(pos2 - (xdir * beamEdgeSize), tex.xend, tex.ystart, edgeColStart); va->AddVertexQTC(pos1 - (xdir * beamCoreSize), tex.xstart, tex.ystart, coreColStart); va->AddVertexQTC(pos1 + (xdir * beamCoreSize), tex.xstart, tex.yend, coreColStart); va->AddVertexQTC(pos2 + (xdir * beamCoreSize), tex.xend, tex.yend, coreColStart); va->AddVertexQTC(pos2 - (xdir * beamCoreSize), tex.xend, tex.ystart, coreColStart); } // draw laser end pos1 = startpos + zdir * (beamTileMinDst + numBeamTiles * tilelength); pos2 = targetPos; tex.xend = tex.xstart + (pos1.distance(pos2) / tilelength) * texSizeX; va->AddVertexQTC(pos1 - (xdir * beamEdgeSize), tex.xstart, tex.ystart, edgeColStart); va->AddVertexQTC(pos1 + (xdir * beamEdgeSize), tex.xstart, tex.yend, edgeColStart); va->AddVertexQTC(pos2 + (xdir * beamEdgeSize), tex.xend, tex.yend, edgeColStart); va->AddVertexQTC(pos2 - (xdir * beamEdgeSize), tex.xend, tex.ystart, edgeColStart); va->AddVertexQTC(pos1 - (xdir * beamCoreSize), tex.xstart, tex.ystart, coreColStart); va->AddVertexQTC(pos1 + (xdir * beamCoreSize), tex.xstart, tex.yend, coreColStart); va->AddVertexQTC(pos2 + (xdir * beamCoreSize), tex.xend, tex.yend, coreColStart); va->AddVertexQTC(pos2 - (xdir * beamCoreSize), tex.xend, tex.ystart, coreColStart); } va->AddVertexQTC(pos2 - (xdir * beamEdgeSize), WT2->xstart, WT2->ystart, edgeColStart); va->AddVertexQTC(pos2 + (xdir * beamEdgeSize), WT2->xstart, WT2->yend, edgeColStart); va->AddVertexQTC(pos2 + (xdir * beamEdgeSize) + (ydir * beamEdgeSize), WT2->xend, WT2->yend, edgeColStart); va->AddVertexQTC(pos2 - (xdir * beamEdgeSize) + (ydir * beamEdgeSize), WT2->xend, WT2->ystart, edgeColStart); va->AddVertexQTC(pos2 - (xdir * beamCoreSize), WT2->xstart, WT2->ystart, coreColStart); va->AddVertexQTC(pos2 + (xdir * beamCoreSize), WT2->xstart, WT2->yend, coreColStart); va->AddVertexQTC(pos2 + (xdir * beamCoreSize) + (ydir * beamCoreSize), WT2->xend, WT2->yend, coreColStart); va->AddVertexQTC(pos2 - (xdir * beamCoreSize) + (ydir * beamCoreSize), WT2->xend, WT2->ystart, coreColStart); float pulseStartTime = (gu->modGameTime * pulseSpeed) - int(gu->modGameTime * pulseSpeed); float muzzleEdgeSize = thickness * flaresize * pulseStartTime; float muzzleCoreSize = muzzleEdgeSize * 0.6f; unsigned char coreColor[4] = {0, 0, 0, 1}; unsigned char edgeColor[4] = {0, 0, 0, 1}; for (int i = 0; i < 3; i++) { coreColor[i] = int(coreColStart[i] * (1.0f - pulseStartTime)); edgeColor[i] = int(edgeColStart[i] * (1.0f - pulseStartTime)); } { // draw muzzleflare pos1 = startpos - zdir * (thickness * flaresize) * 0.02f; va->AddVertexQTC(pos1 + (ydir * muzzleEdgeSize), sidetex.xstart, sidetex.ystart, edgeColor); va->AddVertexQTC(pos1 + (ydir * muzzleEdgeSize) + (zdir * muzzleEdgeSize), sidetex.xend, sidetex.ystart, edgeColor); va->AddVertexQTC(pos1 - (ydir * muzzleEdgeSize) + (zdir * muzzleEdgeSize), sidetex.xend, sidetex.yend, edgeColor); va->AddVertexQTC(pos1 - (ydir * muzzleEdgeSize), sidetex.xstart, sidetex.yend, edgeColor); va->AddVertexQTC(pos1 + (ydir * muzzleCoreSize), sidetex.xstart, sidetex.ystart, coreColor); va->AddVertexQTC(pos1 + (ydir * muzzleCoreSize) + (zdir * muzzleCoreSize), sidetex.xend, sidetex.ystart, coreColor); va->AddVertexQTC(pos1 - (ydir * muzzleCoreSize) + (zdir * muzzleCoreSize), sidetex.xend, sidetex.yend, coreColor); va->AddVertexQTC(pos1 - (ydir * muzzleCoreSize), sidetex.xstart, sidetex.yend, coreColor); pulseStartTime += 0.5f; pulseStartTime -= (1.0f * (pulseStartTime > 1.0f)); for (int i = 0; i < 3; i++) { coreColor[i] = int(coreColStart[i] * (1.0f - pulseStartTime)); edgeColor[i] = int(edgeColStart[i] * (1.0f - pulseStartTime)); } muzzleEdgeSize = thickness * flaresize * pulseStartTime; va->AddVertexQTC(pos1 + (ydir * muzzleEdgeSize), sidetex.xstart, sidetex.ystart, edgeColor); va->AddVertexQTC(pos1 + (ydir * muzzleEdgeSize) + (zdir * muzzleEdgeSize), sidetex.xend, sidetex.ystart, edgeColor); va->AddVertexQTC(pos1 - (ydir * muzzleEdgeSize) + (zdir * muzzleEdgeSize), sidetex.xend, sidetex.yend, edgeColor); va->AddVertexQTC(pos1 - (ydir * muzzleEdgeSize), sidetex.xstart, sidetex.yend, edgeColor); muzzleCoreSize = muzzleEdgeSize * 0.6f; va->AddVertexQTC(pos1 + (ydir * muzzleCoreSize), sidetex.xstart, sidetex.ystart, coreColor); va->AddVertexQTC(pos1 + (ydir * muzzleCoreSize) + (zdir * muzzleCoreSize), sidetex.xend, sidetex.ystart, coreColor); va->AddVertexQTC(pos1 - (ydir * muzzleCoreSize) + (zdir * muzzleCoreSize), sidetex.xend, sidetex.yend, coreColor); va->AddVertexQTC(pos1 - (ydir * muzzleCoreSize), sidetex.xstart, sidetex.yend, coreColor); } { // draw flare (moved slightly along the camera direction) pos1 = startpos - (camera->forward * 3.0f); va->AddVertexQTC(pos1 - (camera->right * flareEdgeSize) - (camera->up * flareEdgeSize), WT4->xstart, WT4->ystart, edgeColStart); va->AddVertexQTC(pos1 + (camera->right * flareEdgeSize) - (camera->up * flareEdgeSize), WT4->xend, WT4->ystart, edgeColStart); va->AddVertexQTC(pos1 + (camera->right * flareEdgeSize) + (camera->up * flareEdgeSize), WT4->xend, WT4->yend, edgeColStart); va->AddVertexQTC(pos1 - (camera->right * flareEdgeSize) + (camera->up * flareEdgeSize), WT4->xstart, WT4->yend, edgeColStart); va->AddVertexQTC(pos1 - (camera->right * flareCoreSize) - (camera->up * flareCoreSize), WT4->xstart, WT4->ystart, coreColStart); va->AddVertexQTC(pos1 + (camera->right * flareCoreSize) - (camera->up * flareCoreSize), WT4->xend, WT4->ystart, coreColStart); va->AddVertexQTC(pos1 + (camera->right * flareCoreSize) + (camera->up * flareCoreSize), WT4->xend, WT4->yend, coreColStart); va->AddVertexQTC(pos1 - (camera->right * flareCoreSize) + (camera->up * flareCoreSize), WT4->xstart, WT4->yend, coreColStart); } #undef WT4 #undef WT2 }
void CAdvTreeDrawer::Draw(float treeDistance, bool drawReflection) { const int activeFarTex = (camera->forward.z < 0.0f)? treeGen->farTex[0]: treeGen->farTex[1]; const bool drawDetailed = ((treeDistance >= 4.0f) || drawReflection); CBaseGroundDrawer* gd = readmap->GetGroundDrawer(); Shader::IProgramObject* treeShader = NULL; const CMapInfo::light_t& light = mapInfo->light; glEnable(GL_ALPHA_TEST); glEnable(GL_TEXTURE_2D); ISky::SetupFog(); if (shadowHandler->shadowsLoaded && !gd->DrawExtraTex()) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, activeFarTex); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, shadowHandler->shadowTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA); treeShader = treeShaders[TREE_PROGRAM_DIST_SHADOW]; treeShader->Enable(); if (globalRendering->haveGLSL) { treeShader->SetUniformMatrix4fv(7, false, &shadowHandler->shadowMatrix.m[0]); treeShader->SetUniform4fv(8, &(shadowHandler->GetShadowParams().x)); } else { treeShader->SetUniformTarget(GL_FRAGMENT_PROGRAM_ARB); treeShader->SetUniform4f(10, light.groundAmbientColor.x, light.groundAmbientColor.y, light.groundAmbientColor.z, 1.0f); treeShader->SetUniform4f(11, 0.0f, 0.0f, 0.0f, 1.0f - (sky->GetLight()->GetGroundShadowDensity() * 0.5f)); treeShader->SetUniformTarget(GL_VERTEX_PROGRAM_ARB); glMatrixMode(GL_MATRIX0_ARB); glLoadMatrixf(shadowHandler->shadowMatrix.m); glMatrixMode(GL_MODELVIEW); } } else { glBindTexture(GL_TEXTURE_2D, activeFarTex); } const int cx = int(camera->pos.x / (SQUARE_SIZE * TREE_SQUARE_SIZE)); const int cy = int(camera->pos.z / (SQUARE_SIZE * TREE_SQUARE_SIZE)); CAdvTreeSquareDrawer drawer(this, cx, cy, treeDistance * SQUARE_SIZE * TREE_SQUARE_SIZE, drawDetailed); GML_STDMUTEX_LOCK(tree); // Draw oldTreeDistance = treeDistance; // draw far-trees using map-dependent grid-visibility readmap->GridVisibility(camera, TREE_SQUARE_SIZE, drawer.treeDistance * 2.0f, &drawer); if (drawDetailed) { // draw near-trees const int xstart = std::max( 0, cx - 2); const int xend = std::min(gs->mapx / TREE_SQUARE_SIZE - 1, cx + 2); const int ystart = std::max( 0, cy - 2); const int yend = std::min(gs->mapy / TREE_SQUARE_SIZE - 1, cy + 2); if (shadowHandler->shadowsLoaded && !gd->DrawExtraTex()) { treeShader->Disable(); treeShader = treeShaders[TREE_PROGRAM_NEAR_SHADOW]; treeShader->Enable(); if (globalRendering->haveGLSL) { treeShader->SetUniformMatrix4fv(7, false, &shadowHandler->shadowMatrix.m[0]); treeShader->SetUniform4fv(8, &(shadowHandler->GetShadowParams().x)); } glActiveTexture(GL_TEXTURE1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, treeGen->barkTex); glActiveTexture(GL_TEXTURE0); } else { glBindTexture(GL_TEXTURE_2D, treeGen->barkTex); treeShader = treeShaders[TREE_PROGRAM_NEAR_BASIC]; treeShader->Enable(); if (!globalRendering->haveGLSL) { const int mx = gs->pwr2mapx * SQUARE_SIZE; const int my = gs->pwr2mapy * SQUARE_SIZE; treeShader->SetUniformTarget(GL_VERTEX_PROGRAM_ARB); treeShader->SetUniform4f(15, 1.0f / mx, 1.0f / my, 1.0f / mx, 1.0f); } } if (globalRendering->haveGLSL) { treeShader->SetUniform3fv(0, &camera->right[0]); treeShader->SetUniform3fv(1, &camera->up[0]); treeShader->SetUniform2f(5, 0.20f * (1.0f / MAX_TREE_HEIGHT), 0.85f); } else { treeShader->SetUniformTarget(GL_VERTEX_PROGRAM_ARB); treeShader->SetUniform3f(13, camera->right.x, camera->right.y, camera->right.z); treeShader->SetUniform3f( 9, camera->up.x, camera->up.y, camera->up.z ); treeShader->SetUniform4f(11, light.groundSunColor.x, light.groundSunColor.y, light.groundSunColor.z, 0.85f); treeShader->SetUniform4f(14, light.groundAmbientColor.x, light.groundAmbientColor.y, light.groundAmbientColor.z, 0.85f); treeShader->SetUniform4f(12, 0.0f, 0.0f, 0.0f, 0.20f * (1.0f / MAX_TREE_HEIGHT)); // w = alpha/height modifier } glAlphaFunc(GL_GREATER, 0.5f); glDisable(GL_BLEND); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); CVertexArray* va = GetVertexArray(); va->Initialize(); static FadeTree fadeTrees[3000]; FadeTree* pFT = fadeTrees; for (TreeSquareStruct* pTSS = trees + (ystart * treesX); pTSS <= trees + (yend * treesX); pTSS += treesX) { for (TreeSquareStruct* tss = pTSS + xstart; tss <= (pTSS + xend); ++tss) { tss->lastSeen = gs->frameNum; va->EnlargeArrays(12 * tss->trees.size(), 0, VA_SIZE_T); //!alloc room for all tree vertexes for (std::map<int, TreeStruct>::iterator ti = tss->trees.begin(); ti != tss->trees.end(); ++ti) { const TreeStruct* ts = &ti->second; const float3 pos(ts->pos); if (!camera->InView(pos + float3(0.0f, MAX_TREE_HEIGHT / 2.0f, 0.0f), MAX_TREE_HEIGHT / 2.0f)) { continue; } const float camDist = (pos - camera->pos).SqLength(); int type = ts->type; float dy = 0.0f; unsigned int dispList; if (type < 8) { dy = 0.5f; dispList = treeGen->pineDL + type; } else { type -= 8; dy = 0.0f; dispList = treeGen->leafDL + type; } if (camDist < (SQUARE_SIZE * SQUARE_SIZE * 110 * 110)) { // draw detailed near-distance tree (same as mid-distance trees without alpha) treeShader->SetUniform3f(((globalRendering->haveGLSL)? 2: 10), pos.x, pos.y, pos.z); glCallList(dispList); } else if (camDist < (SQUARE_SIZE * SQUARE_SIZE * 125 * 125)) { // draw mid-distance tree const float relDist = (pos.distance(camera->pos) - SQUARE_SIZE * 110) / (SQUARE_SIZE * 15); treeShader->SetUniform3f(((globalRendering->haveGLSL)? 2: 10), pos.x, pos.y, pos.z); glAlphaFunc(GL_GREATER, 0.8f + relDist * 0.2f); glCallList(dispList); glAlphaFunc(GL_GREATER, 0.5f); // save for second pass pFT->pos = pos; pFT->deltaY = dy; pFT->type = type; pFT->relDist = relDist; ++pFT; } else { // draw far-distance tree CAdvTreeDrawer::DrawTreeVertex(va, pos, type * 0.125f, dy, false); } } } } // reset the world-offset treeShader->SetUniform3f(((globalRendering->haveGLSL)? 2: 10), 0.0f, 0.0f, 0.0f); // draw trees that have been marked as falling for (std::list<FallingTree>::iterator fti = fallingTrees.begin(); fti != fallingTrees.end(); ++fti) { const float3 pos = fti->pos - UpVector * (fti->fallPos * 20); if (camera->InView(pos + float3(0.0f, MAX_TREE_HEIGHT / 2, 0.0f), MAX_TREE_HEIGHT / 2.0f)) { const float ang = fti->fallPos * PI; const float3 yvec(fti->dir.x * sin(ang), cos(ang), fti->dir.z * sin(ang)); const float3 zvec((yvec.cross(float3(-1.0f, 0.0f, 0.0f))).ANormalize()); const float3 xvec(yvec.cross(zvec)); CMatrix44f transMatrix(pos, xvec, yvec, zvec); glPushMatrix(); glMultMatrixf(&transMatrix[0]); int type = fti->type; int dispList = 0; if (type < 8) { dispList = treeGen->pineDL + type; } else { type -= 8; dispList = treeGen->leafDL + type; } glCallList(dispList); glPopMatrix(); } } if (shadowHandler->shadowsLoaded && !gd->DrawExtraTex()) { treeShader->Disable(); treeShader = treeShaders[TREE_PROGRAM_DIST_SHADOW]; treeShader->Enable(); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, activeFarTex); glActiveTexture(GL_TEXTURE0); } else { treeShader->Disable(); glBindTexture(GL_TEXTURE_2D, activeFarTex); } // draw far-distance trees va->DrawArrayT(GL_QUADS); // draw faded mid-distance trees for (FadeTree* pFTree = fadeTrees; pFTree < pFT; ++pFTree) { va = GetVertexArray(); va->Initialize(); va->CheckInitSize(12 * VA_SIZE_T); CAdvTreeDrawer::DrawTreeVertex(va, pFTree->pos, pFTree->type * 0.125f, pFTree->deltaY, false); glAlphaFunc(GL_GREATER, 1.0f - (pFTree->relDist * 0.5f)); va->DrawArrayT(GL_QUADS); } } if (shadowHandler->shadowsLoaded && !gd->DrawExtraTex()) { treeShader->Disable(); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE); } else { glBindTexture(GL_TEXTURE_2D, 0); } glDisable(GL_TEXTURE_2D); glDisable(GL_FOG); glDisable(GL_ALPHA_TEST); // clean out squares from memory that are no longer visible const int startClean = lastListClean * 20 % (nTrees); const int endClean = gs->frameNum * 20 % (nTrees); lastListClean = gs->frameNum; if (startClean > endClean) { for (TreeSquareStruct* pTSS = trees + startClean; pTSS < (trees + nTrees); ++pTSS) { if ((pTSS->lastSeen < gs->frameNum - 50) && pTSS->dispList) { glDeleteLists(pTSS->dispList, 1); pTSS->dispList = 0; } if ((pTSS->lastSeenFar < (gs->frameNum - 50)) && pTSS->farDispList) { glDeleteLists(pTSS->farDispList, 1); pTSS->farDispList = 0; } } for (TreeSquareStruct* pTSS = trees; pTSS < (trees + endClean); ++pTSS) { if ((pTSS->lastSeen < (gs->frameNum - 50)) && pTSS->dispList) { glDeleteLists(pTSS->dispList, 1); pTSS->dispList = 0; } if ((pTSS->lastSeenFar < (gs->frameNum - 50)) && pTSS->farDispList) { glDeleteLists(pTSS->farDispList, 1); pTSS->farDispList = 0; } } } else { for (TreeSquareStruct* pTSS = trees + startClean; pTSS < (trees + endClean); ++pTSS) { if ((pTSS->lastSeen < (gs->frameNum - 50)) && pTSS->dispList) { glDeleteLists(pTSS->dispList, 1); pTSS->dispList = 0; } if ((pTSS->lastSeenFar < (gs->frameNum - 50)) && pTSS->farDispList) { glDeleteLists(pTSS->farDispList, 1); pTSS->farDispList = 0; } } } }
void CAdvTreeDrawer::DrawShadowPass() { const float treeDistance = oldTreeDistance; const int activeFarTex = (camera->forward.z < 0.0f)? treeGen->farTex[0] : treeGen->farTex[1]; const bool drawDetailed = (treeDistance >= 4.0f); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, activeFarTex); glEnable(GL_TEXTURE_2D); glEnable(GL_ALPHA_TEST); glDisable(GL_CULL_FACE); glPolygonOffset(1, 1); glEnable(GL_POLYGON_OFFSET_FILL); CAdvTreeSquareDrawer_SP drawer; const int cx = drawer.cx = (int)(camera->pos.x / (SQUARE_SIZE * TREE_SQUARE_SIZE)); const int cy = drawer.cy = (int)(camera->pos.z / (SQUARE_SIZE * TREE_SQUARE_SIZE)); drawer.drawDetailed = drawDetailed; drawer.td = this; drawer.treeDistance = treeDistance * SQUARE_SIZE * TREE_SQUARE_SIZE; Shader::IProgramObject* po = NULL; GML_STDMUTEX_LOCK(tree); // DrawShadowPass // draw with extraSize=1 readmap->GridVisibility(camera, TREE_SQUARE_SIZE, drawer.treeDistance * 2.0f, &drawer, 1); if (drawDetailed) { const int xstart = std::max( 0, cx - 2); const int xend = std::min(gs->mapx / TREE_SQUARE_SIZE - 1, cx + 2); const int ystart = std::max( 0, cy - 2); const int yend = std::min(gs->mapy / TREE_SQUARE_SIZE - 1, cy + 2); glBindTexture(GL_TEXTURE_2D, treeGen->barkTex); glEnable(GL_TEXTURE_2D); po = shadowHandler->GetShadowGenProg(CShadowHandler::SHADOWGEN_PROGRAM_TREE_NEAR); po->Enable(); if (globalRendering->haveGLSL) { po->SetUniform3fv(1, &camera->right[0]); po->SetUniform3fv(2, &camera->up[0]); } else { po->SetUniformTarget(GL_VERTEX_PROGRAM_ARB); po->SetUniform4f(13, camera->right.x, camera->right.y, camera->right.z, 0.0f); po->SetUniform4f(9, camera->up.x, camera->up.y, camera->up.z, 0.0f); po->SetUniform4f(11, 1.0f, 1.0f, 1.0f, 0.85f ); po->SetUniform4f(12, 0.0f, 0.0f, 0.0f, 0.20f * (1.0f / MAX_TREE_HEIGHT)); // w = alpha/height modifier } glAlphaFunc(GL_GREATER, 0.5f); glEnable(GL_ALPHA_TEST); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); CVertexArray* va = GetVertexArray(); va->Initialize(); static FadeTree fadeTrees[3000]; FadeTree* pFT = fadeTrees; for (TreeSquareStruct* pTSS = trees + (ystart * treesX); pTSS <= trees + (yend * treesX); pTSS += treesX) { for (TreeSquareStruct* tss = pTSS + xstart; tss <= pTSS + xend; ++tss) { tss->lastSeen = gs->frameNum; va->EnlargeArrays(12 * tss->trees.size(), 0, VA_SIZE_T); //!alloc room for all tree vertexes for (std::map<int, TreeStruct>::iterator ti = tss->trees.begin(); ti != tss->trees.end(); ++ti) { const TreeStruct* ts = &ti->second; const float3 pos(ts->pos); if (!camera->InView(pos + float3(0, MAX_TREE_HEIGHT / 2, 0), MAX_TREE_HEIGHT / 2 + 150)) { continue; } const float camDist = (pos - camera->pos).SqLength(); int type = ts->type; float dy = 0.0f; unsigned int dispList; if (type < 8) { dy = 0.5f; dispList = treeGen->pineDL + type; } else { type -= 8; dy = 0; dispList = treeGen->leafDL + type; } if (camDist < SQUARE_SIZE * SQUARE_SIZE * 110 * 110) { po->SetUniform3f((globalRendering->haveGLSL? 3: 10), pos.x, pos.y, pos.z); glCallList(dispList); } else if (camDist < SQUARE_SIZE * SQUARE_SIZE * 125 * 125) { const float relDist = (pos.distance(camera->pos) - SQUARE_SIZE * 110) / (SQUARE_SIZE * 15); glAlphaFunc(GL_GREATER, 0.8f + relDist * 0.2f); po->SetUniform3f((globalRendering->haveGLSL? 3: 10), pos.x, pos.y, pos.z); glCallList(dispList); glAlphaFunc(GL_GREATER, 0.5f); pFT->pos = pos; pFT->deltaY = dy; pFT->type = type; pFT->relDist = relDist; ++pFT; } else { CAdvTreeDrawer::DrawTreeVertex(va, pos, type * 0.125f, dy, false); } } } } po->SetUniform3f((globalRendering->haveGLSL? 3: 10), 0.0f, 0.0f, 0.0f); for (std::list<FallingTree>::iterator fti = fallingTrees.begin(); fti != fallingTrees.end(); ++fti) { const float3 pos = fti->pos - UpVector * (fti->fallPos * 20); if (camera->InView(pos + float3(0, MAX_TREE_HEIGHT / 2, 0), MAX_TREE_HEIGHT / 2)) { const float ang = fti->fallPos * PI; const float3 yvec(fti->dir.x * sin(ang), cos(ang), fti->dir.z * sin(ang)); const float3 zvec((yvec.cross(float3(1.0f, 0.0f, 0.0f))).ANormalize()); const float3 xvec(zvec.cross(yvec)); CMatrix44f transMatrix(pos, xvec, yvec, zvec); glPushMatrix(); glMultMatrixf(&transMatrix[0]); int type = fti->type; int dispList; if (type < 8) { dispList = treeGen->pineDL + type; } else { type -= 8; dispList = treeGen->leafDL + type; } glCallList(dispList); glPopMatrix(); } } po->Disable(); po = shadowHandler->GetShadowGenProg(CShadowHandler::SHADOWGEN_PROGRAM_TREE_FAR); po->Enable(); glBindTexture(GL_TEXTURE_2D, activeFarTex); va->DrawArrayT(GL_QUADS); for (FadeTree* pFTree = fadeTrees; pFTree < pFT; ++pFTree) { // faded close trees va = GetVertexArray(); va->Initialize(); va->CheckInitSize(12 * VA_SIZE_T); CAdvTreeDrawer::DrawTreeVertex(va, pFTree->pos, pFTree->type * 0.125f, pFTree->deltaY, false); glAlphaFunc(GL_GREATER, 1.0f - (pFTree->relDist * 0.5f)); va->DrawArrayT(GL_QUADS); } po->Disable(); } glEnable(GL_CULL_FACE); glDisable(GL_POLYGON_OFFSET_FILL); glDisable(GL_TEXTURE_2D); glDisable(GL_ALPHA_TEST); }
bool CHoverAirMoveType::Update() { const float3 lastPos = owner->pos; const float4 lastSpd = owner->speed; AAirMoveType::Update(); if ((owner->IsStunned() && !owner->IsCrashing()) || owner->beingBuilt) { wantedSpeed = ZeroVector; UpdateAirPhysics(); return (HandleCollisions(collide && !owner->beingBuilt && (padStatus == PAD_STATUS_FLYING) && (aircraftState != AIRCRAFT_TAKEOFF))); } // allow us to stop if wanted (changes aircraft state) if (wantToStop) ExecuteStop(); if (aircraftState != AIRCRAFT_CRASHING) { if (owner->fpsControlPlayer != NULL) { SetState(AIRCRAFT_FLYING); const FPSUnitController& con = owner->fpsControlPlayer->fpsController; const float3 forward = con.viewDir; const float3 right = forward.cross(UpVector); const float3 nextPos = lastPos + owner->speed; float3 flatForward = forward; flatForward.Normalize2D(); wantedSpeed = ZeroVector; if (con.forward) wantedSpeed += flatForward; if (con.back ) wantedSpeed -= flatForward; if (con.right ) wantedSpeed += right; if (con.left ) wantedSpeed -= right; wantedSpeed.Normalize(); wantedSpeed *= maxSpeed; if (!nextPos.IsInBounds()) { owner->SetVelocityAndSpeed(ZeroVector); } UpdateAirPhysics(); wantedHeading = GetHeadingFromVector(flatForward.x, flatForward.z); } if (reservedPad != NULL) { MoveToRepairPad(); if (padStatus >= PAD_STATUS_LANDING) { flyState = FLY_LANDING; } } } switch (aircraftState) { case AIRCRAFT_LANDED: UpdateLanded(); break; case AIRCRAFT_TAKEOFF: UpdateTakeoff(); break; case AIRCRAFT_FLYING: UpdateFlying(); break; case AIRCRAFT_LANDING: UpdateLanding(); break; case AIRCRAFT_HOVERING: UpdateHovering(); break; case AIRCRAFT_CRASHING: { UpdateAirPhysics(); if ((ground->GetHeightAboveWater(owner->pos.x, owner->pos.z) + 5.0f + owner->radius) > owner->pos.y) { owner->ClearPhysicalStateBit(CSolidObject::PSTATE_BIT_CRASHING); owner->KillUnit(NULL, true, false); } else { #define SPIN_DIR(o) ((o->id & 1) * 2 - 1) wantedHeading = GetHeadingFromVector(owner->rightdir.x * SPIN_DIR(owner), owner->rightdir.z * SPIN_DIR(owner)); wantedHeight = 0.0f; #undef SPIN_DIR } new CSmokeProjectile(owner->midPos, gs->randVector() * 0.08f, 100 + gs->randFloat() * 50, 5, 0.2f, owner, 0.4f); } break; } if (lastSpd == ZeroVector && owner->speed != ZeroVector) { owner->script->StartMoving(false); } if (lastSpd != ZeroVector && owner->speed == ZeroVector) { owner->script->StopMoving(); } // Banking requires deltaSpeed.y = 0 deltaSpeed = owner->speed - lastSpd; deltaSpeed.y = 0.0f; // Turn and bank and move; update dirs UpdateHeading(); UpdateBanking(aircraftState == AIRCRAFT_HOVERING); return (HandleCollisions(collide && !owner->beingBuilt && (padStatus == PAD_STATUS_FLYING) && (aircraftState != AIRCRAFT_TAKEOFF))); }
bool CHoverAirMoveType::Update() { float3& pos = owner->pos; float3& speed = owner->speed; AAirMoveType::Update(); if (owner->stunned || owner->beingBuilt) { wantedSpeed = ZeroVector; wantToStop = true; } // Allow us to stop if wanted if (wantToStop) { ExecuteStop(); } const float3 lastSpeed = speed; if (owner->fpsControlPlayer != NULL) { SetState(AIRCRAFT_FLYING); const FPSUnitController& con = owner->fpsControlPlayer->fpsController; const float3 forward = con.viewDir; const float3 right = forward.cross(UpVector); const float3 nextPos = pos + speed; float3 flatForward = forward; flatForward.y = 0.0f; flatForward.Normalize(); wantedSpeed = ZeroVector; if (con.forward) wantedSpeed += flatForward; if (con.back ) wantedSpeed -= flatForward; if (con.right ) wantedSpeed += right; if (con.left ) wantedSpeed -= right; wantedSpeed.Normalize(); wantedSpeed *= maxSpeed; if (!nextPos.IsInBounds()) { speed = ZeroVector; } UpdateAirPhysics(); wantedHeading = GetHeadingFromVector(flatForward.x, flatForward.z); } else { if (reservedPad != NULL) { MoveToRepairPad(); if (padStatus >= 1) { flyState = FLY_LANDING; } } // Main state handling switch (aircraftState) { case AIRCRAFT_LANDED: UpdateLanded(); break; case AIRCRAFT_TAKEOFF: UpdateTakeoff(); break; case AIRCRAFT_FLYING: UpdateFlying(); break; case AIRCRAFT_LANDING: UpdateLanding(); break; case AIRCRAFT_HOVERING: UpdateHovering(); break; case AIRCRAFT_CRASHING: break; } } // Banking requires deltaSpeed.y = 0 deltaSpeed = speed - lastSpeed; deltaSpeed.y = 0.0f; // Turn and bank and move; update dirs UpdateHeading(); UpdateBanking(aircraftState == AIRCRAFT_HOVERING); return (HandleCollisions()); }
void CSMFReadMap::UpdateVertexNormalsUnsynced(const SRectangle& update) { #ifdef USE_UNSYNCED_HEIGHTMAP const float* shm = &cornerHeightMapSynced[0]; float* uhm = &cornerHeightMapUnsynced[0]; float3* vvn = &visVertexNormals[0]; const int W = mapDims.mapxp1; const int H = mapDims.mapyp1; static const int SS = SQUARE_SIZE; // a heightmap update over (x1, y1) - (x2, y2) implies the // normals change over (x1 - 1, y1 - 1) - (x2 + 1, y2 + 1) const int minx = std::max(update.x1 - 1, 0); const int minz = std::max(update.y1 - 1, 0); const int maxx = std::min(update.x2 + 1, W - 1); const int maxz = std::min(update.y2 + 1, H - 1); for_mt(minz, maxz+1, [&](const int z) { for (int x = minx; x <= maxx; x++) { const int vIdxTL = (z ) * W + x; const int xOffL = (x > 0)? 1: 0; const int xOffR = (x < W - 1)? 1: 0; const int zOffT = (z > 0)? 1: 0; const int zOffB = (z < H - 1)? 1: 0; const float sxm1 = (x - 1) * SS; const float sx = x * SS; const float sxp1 = (x + 1) * SS; const float szm1 = (z - 1) * SS; const float sz = z * SS; const float szp1 = (z + 1) * SS; const int shxm1 = x - xOffL; const int shx = x; const int shxp1 = x + xOffR; const int shzm1 = (z - zOffT) * W; const int shz = z * W; const int shzp1 = (z + zOffB) * W; // pretend there are 8 incident triangle faces per vertex // for each these triangles, calculate the surface normal, // then average the 8 normals (this stays closest to the // heightmap data) // if edge vertex, don't add virtual neighbor normals to vn const float3 vmm = float3(sx , shm[shz + shx ], sz ); const float3 vtl = float3(sxm1, shm[shzm1 + shxm1], szm1) - vmm; const float3 vtm = float3(sx , shm[shzm1 + shx ], szm1) - vmm; const float3 vtr = float3(sxp1, shm[shzm1 + shxp1], szm1) - vmm; const float3 vml = float3(sxm1, shm[shz + shxm1], sz ) - vmm; const float3 vmr = float3(sxp1, shm[shz + shxp1], sz ) - vmm; const float3 vbl = float3(sxm1, shm[shzp1 + shxm1], szp1) - vmm; const float3 vbm = float3(sx , shm[shzp1 + shx ], szp1) - vmm; const float3 vbr = float3(sxp1, shm[shzp1 + shxp1], szp1) - vmm; float3 vn(0.0f, 0.0f, 0.0f); vn += vtm.cross(vtl) * (zOffT & xOffL); assert(vtm.cross(vtl).y >= 0.0f); vn += vtr.cross(vtm) * (zOffT ); assert(vtr.cross(vtm).y >= 0.0f); vn += vmr.cross(vtr) * (zOffT & xOffR); assert(vmr.cross(vtr).y >= 0.0f); vn += vbr.cross(vmr) * ( xOffR); assert(vbr.cross(vmr).y >= 0.0f); vn += vtl.cross(vml) * ( xOffL); assert(vtl.cross(vml).y >= 0.0f); vn += vbm.cross(vbr) * (zOffB & xOffR); assert(vbm.cross(vbr).y >= 0.0f); vn += vbl.cross(vbm) * (zOffB ); assert(vbl.cross(vbm).y >= 0.0f); vn += vml.cross(vbl) * (zOffB & xOffL); assert(vml.cross(vbl).y >= 0.0f); // update the visible vertex/face height/normal uhm[vIdxTL] = shm[vIdxTL]; vvn[vIdxTL] = vn.ANormalize(); } }); #endif }
void C3DOParser::GetPrimitives(S3DOPiece* obj, int pos, int num, int excludePrim) { map<int,int> prevHashes; for(int a=0;a<num;a++){ if(excludePrim==a){ continue; } curOffset=pos+a*sizeof(_Primitive); _Primitive p; READ_PRIMITIVE(p); S3DOPrimitive sp; sp.numVertex=p.NumberOfVertexIndexes; if(sp.numVertex<3) continue; sp.vertices.reserve(sp.numVertex); sp.vnormals.reserve(sp.numVertex); curOffset=p.OffsetToVertexIndexArray; boost::uint16_t w; list<int> orderVert; for(int b=0;b<sp.numVertex;b++){ SimStreamRead(&w,2); swabWordInPlace(w); sp.vertices.push_back(w); orderVert.push_back(w); } orderVert.sort(); int vertHash=0; for(list<int>::iterator vi=orderVert.begin();vi!=orderVert.end();++vi) vertHash=(vertHash+(*vi))*(*vi); std::string texName; if (p.OffsetToTextureName != 0) { texName = StringToLower(GetText(p.OffsetToTextureName)); if (teamtex.find(texName) == teamtex.end()) { texName += "00"; } } else { texName = "ta_color" + IntToString(p.PaletteEntry, "%i"); } if ((sp.texture = texturehandler3DO->Get3DOTexture(texName)) == NULL) { LOG_L(L_WARNING, "[%s] unknown 3DO texture \"%s\" for piece \"%s\"", __FUNCTION__, texName.c_str(), obj->name.c_str()); // assign a dummy texture (the entire atlas) sp.texture = texturehandler3DO->Get3DOTexture("___dummy___"); } const float3 v0v1 = (obj->vertices[sp.vertices[1]].pos - obj->vertices[sp.vertices[0]].pos); const float3 v0v2 = (obj->vertices[sp.vertices[2]].pos - obj->vertices[sp.vertices[0]].pos); float3 n = (-v0v1.cross(v0v2)).SafeNormalize(); // set the primitive-normal and copy it <numVertex> // times (vnormals get overwritten by CalcNormals()) sp.primNormal = n; sp.vnormals.insert(sp.vnormals.begin(), sp.numVertex, n); // sometimes there are more than one selection primitive (??) if (n.dot(DownVector) > 0.99f) { bool ignore=true; if(sp.numVertex!=4) { ignore=false; } else { const float3 s1 = obj->vertices[sp.vertices[0]].pos - obj->vertices[sp.vertices[1]].pos; const float3 s2 = obj->vertices[sp.vertices[1]].pos - obj->vertices[sp.vertices[2]].pos; if(s1.SqLength()<900 || s2.SqLength()<900) ignore=false; if (ignore) { for(int a=0;a<sp.numVertex;++a) { if(obj->vertices[sp.vertices[a]].pos.y>0) { ignore=false; break; } } } } if(ignore) continue; } map<int,int>::iterator phi; if((phi=prevHashes.find(vertHash))!=prevHashes.end()){ if(n.y>0) obj->prims[phi->second]=sp; continue; } else { prevHashes[vertHash]=obj->prims.size(); obj->prims.push_back(sp); obj->isEmpty = false; } curOffset = p.OffsetToVertexIndexArray; for (int b = 0; b < sp.numVertex; b++) { SimStreamRead(&w, 2); swabWordInPlace(w); obj->vertices[w].prims.push_back(obj->prims.size() - 1); } } }
void CBeamLaserProjectile::Draw() { inArray = true; const float3 cameraDir = (pos - camera->pos).SafeANormalize(); // beam's coor-system; degenerate if targetPos == startPos const float3 zdir = (targetPos - startpos).SafeANormalize(); const float3 xdir = (cameraDir.cross(zdir)).SafeANormalize(); const float3 ydir = (cameraDir.cross(xdir)); const float beamEdgeSize = thickness; const float beamCoreSize = beamEdgeSize * corethickness; const float flareEdgeSize = thickness * flaresize; const float flareCoreSize = flareEdgeSize * corethickness; const float3& pos1 = startpos; const float3& pos2 = targetPos; va->EnlargeArrays(32, 0, VA_SIZE_TC); #define WT1 weaponDef->visuals.texture1 #define WT2 weaponDef->visuals.texture2 #define WT3 weaponDef->visuals.texture3 if ((pos - camera->pos).SqLength() < (1000.0f * 1000.0f)) { va->AddVertexQTC(pos1 - xdir * beamEdgeSize, midtexx, WT2->ystart, edgeColStart); va->AddVertexQTC(pos1 + xdir * beamEdgeSize, midtexx, WT2->yend, edgeColStart); va->AddVertexQTC(pos1 + xdir * beamEdgeSize - ydir * beamEdgeSize, WT2->xend, WT2->yend, edgeColStart); va->AddVertexQTC(pos1 - xdir * beamEdgeSize - ydir * beamEdgeSize, WT2->xend, WT2->ystart, edgeColStart); va->AddVertexQTC(pos1 - xdir * beamCoreSize, midtexx, WT2->ystart, coreColStart); va->AddVertexQTC(pos1 + xdir * beamCoreSize, midtexx, WT2->yend, coreColStart); va->AddVertexQTC(pos1 + xdir * beamCoreSize - ydir * beamCoreSize, WT2->xend, WT2->yend, coreColStart); va->AddVertexQTC(pos1 - xdir * beamCoreSize - ydir * beamCoreSize, WT2->xend, WT2->ystart, coreColStart); va->AddVertexQTC(pos1 - xdir * beamEdgeSize, WT1->xstart, WT1->ystart, edgeColStart); va->AddVertexQTC(pos1 + xdir * beamEdgeSize, WT1->xstart, WT1->yend, edgeColStart); va->AddVertexQTC(pos2 + xdir * beamEdgeSize, WT1->xend, WT1->yend, edgeColEnd); va->AddVertexQTC(pos2 - xdir * beamEdgeSize, WT1->xend, WT1->ystart, edgeColEnd); va->AddVertexQTC(pos1 - xdir * beamCoreSize, WT1->xstart, WT1->ystart, coreColStart); va->AddVertexQTC(pos1 + xdir * beamCoreSize, WT1->xstart, WT1->yend, coreColStart); va->AddVertexQTC(pos2 + xdir * beamCoreSize, WT1->xend, WT1->yend, coreColEnd); va->AddVertexQTC(pos2 - xdir * beamCoreSize, WT1->xend, WT1->ystart, coreColEnd); va->AddVertexQTC(pos2 - xdir * beamEdgeSize, midtexx, WT2->ystart, edgeColStart); va->AddVertexQTC(pos2 + xdir * beamEdgeSize, midtexx, WT2->yend, edgeColStart); va->AddVertexQTC(pos2 + xdir * beamEdgeSize + ydir * beamEdgeSize, WT2->xend, WT2->yend, edgeColStart); va->AddVertexQTC(pos2 - xdir * beamEdgeSize + ydir * beamEdgeSize, WT2->xend, WT2->ystart, edgeColStart); va->AddVertexQTC(pos2 - xdir * beamCoreSize, midtexx, WT2->ystart, coreColStart); va->AddVertexQTC(pos2 + xdir * beamCoreSize, midtexx, WT2->yend, coreColStart); va->AddVertexQTC(pos2 + xdir * beamCoreSize + ydir * beamCoreSize, WT2->xend, WT2->yend, coreColStart); va->AddVertexQTC(pos2 - xdir * beamCoreSize + ydir * beamCoreSize, WT2->xend, WT2->ystart, coreColStart); } else { va->AddVertexQTC(pos1 - xdir * beamEdgeSize, WT1->xstart, WT1->ystart, edgeColStart); va->AddVertexQTC(pos1 + xdir * beamEdgeSize, WT1->xstart, WT1->yend, edgeColStart); va->AddVertexQTC(pos2 + xdir * beamEdgeSize, WT1->xend, WT1->yend, edgeColEnd); va->AddVertexQTC(pos2 - xdir * beamEdgeSize, WT1->xend, WT1->ystart, edgeColEnd); va->AddVertexQTC(pos1 - xdir * beamCoreSize, WT1->xstart, WT1->ystart, coreColStart); va->AddVertexQTC(pos1 + xdir * beamCoreSize, WT1->xstart, WT1->yend, coreColStart); va->AddVertexQTC(pos2 + xdir * beamCoreSize, WT1->xend, WT1->yend, coreColEnd); va->AddVertexQTC(pos2 - xdir * beamCoreSize, WT1->xend, WT1->ystart, coreColEnd); } // draw flare va->AddVertexQTC(pos1 - camera->right * flareEdgeSize - camera->up * flareEdgeSize, WT3->xstart, WT3->ystart, edgeColStart); va->AddVertexQTC(pos1 + camera->right * flareEdgeSize - camera->up * flareEdgeSize, WT3->xend, WT3->ystart, edgeColStart); va->AddVertexQTC(pos1 + camera->right * flareEdgeSize + camera->up * flareEdgeSize, WT3->xend, WT3->yend, edgeColStart); va->AddVertexQTC(pos1 - camera->right * flareEdgeSize + camera->up * flareEdgeSize, WT3->xstart, WT3->yend, edgeColStart); va->AddVertexQTC(pos1 - camera->right * flareCoreSize - camera->up * flareCoreSize, WT3->xstart, WT3->ystart, coreColStart); va->AddVertexQTC(pos1 + camera->right * flareCoreSize - camera->up * flareCoreSize, WT3->xend, WT3->ystart, coreColStart); va->AddVertexQTC(pos1 + camera->right * flareCoreSize + camera->up * flareCoreSize, WT3->xend, WT3->yend, coreColStart); va->AddVertexQTC(pos1 - camera->right * flareCoreSize + camera->up * flareCoreSize, WT3->xstart, WT3->yend, coreColStart); #undef WT3 #undef WT2 #undef WT1 }
void CRepulseGfx::Draw() { const CUnit* owner = CProjectile::owner(); if (!owner || !repulsed) { return; } const float3 zdir = (repulsed->pos - owner->pos).SafeANormalize(); const float3 xdir = (zdir.cross(UpVector)).SafeANormalize(); const float3 ydir = xdir.cross(zdir); float3 xdirDS; float3 ydirDS; pos = (repulsed->pos - zdir * 10.0f) + (repulsed->speed * globalRendering->timeOffset); inArray = true; float drawsize = 10.0f; float alpha = std::min(255.0f, age * 10.0f); unsigned char col[4] = { (unsigned char) (color.x * alpha), (unsigned char) (color.y * alpha), (unsigned char) (color.z * alpha), (unsigned char) (0.2f * alpha), }; xdirDS = xdir * drawsize; ydirDS = ydir * drawsize; const AtlasedTexture* et = projectileDrawer->repulsetex; const float txo = et->xstart; const float tyo = et->ystart; const float txs = et->xend - et->xstart; const float tys = et->yend - et->ystart; static const int loopCountY = 4; static const int loopCountX = 4; va->EnlargeArrays(loopCountY * loopCountX * 4 + 16, 0, VA_SIZE_TC); for (int y = 0; y < loopCountY; ++y) { //! CAUTION: loop count must match EnlargeArrays above const float dy = y - 2.0f; const float ry = y * 0.25f; for (int x = 0; x < loopCountX; ++x) { const float dx = x - 2.00f; const float rx = x * 0.25f; va->AddVertexQTC(pos + xdirDS * (dx + 0) + ydirDS * (dy + 0) + zdir * difs[(y ) * 5 + x ], txo + (ry ) * txs, tyo + (rx ) * tys, col); va->AddVertexQTC(pos + xdirDS * (dx + 0) + ydirDS * (dy + 1) + zdir * difs[(y + 1) * 5 + x ], txo + (ry + 0.25f) * txs, tyo + (rx ) * tys, col); va->AddVertexQTC(pos + xdirDS * (dx + 1) + ydirDS * (dy + 1) + zdir * difs[(y + 1) * 5 + x + 1], txo + (ry + 0.25f) * txs, tyo + (rx + 0.25f) * tys, col); va->AddVertexQTC(pos + xdirDS * (dx + 1) + ydirDS * (dy + 0) + zdir * difs[(y ) * 5 + x + 1], txo + (ry ) * txs, tyo + (rx + 0.25f) * tys, col); } } drawsize = 7.0f; alpha = std::min(10.0f, age / 2.0f); col[0] = (unsigned char) (color.x * alpha); col[1] = (unsigned char) (color.y * alpha); col[2] = (unsigned char) (color.z * alpha); col[3] = (unsigned char) (alpha * 0.4f); const AtlasedTexture* ct = projectileDrawer->repulsegfxtex; const float tx = (ct->xend + ct->xstart) * 0.5f; const float ty = (ct->yend + ct->ystart) * 0.5f; static const unsigned char col2[4] = {0, 0, 0, 0}; xdirDS = xdir * drawsize; ydirDS = ydir * drawsize; va->AddVertexQTC(owner->pos + (-xdir + ydir) * drawsize * 0.2f, tx, ty, col2); va->AddVertexQTC(owner->pos + ( xdir + ydir) * drawsize * 0.2f, tx, ty, col2); va->AddVertexQTC( pos + xdirDS + ydirDS + zdir * difs[6], tx, ty, col); va->AddVertexQTC( pos - xdirDS + ydirDS + zdir * difs[6], tx, ty, col); va->AddVertexQTC(owner->pos + (-xdir - ydir) * drawsize * 0.2f, tx, ty, col2); va->AddVertexQTC(owner->pos + ( xdir - ydir) * drawsize * 0.2f, tx, ty, col2); va->AddVertexQTC( pos + xdirDS - ydirDS + zdir * difs[6], tx, ty, col); va->AddVertexQTC( pos - xdirDS - ydirDS + zdir * difs[6], tx, ty, col); va->AddVertexQTC(owner->pos + (xdir - ydir) * drawsize * 0.2f, tx, ty, col2); va->AddVertexQTC(owner->pos + (xdir + ydir) * drawsize * 0.2f, tx, ty, col2); va->AddVertexQTC( pos + xdirDS + ydirDS + zdir * difs[6], tx, ty, col); va->AddVertexQTC( pos + xdirDS - ydirDS + zdir * difs[6], tx, ty, col); va->AddVertexQTC(owner->pos + (-xdir - ydir) * drawsize * 0.2f, tx, ty, col2); va->AddVertexQTC(owner->pos + (-xdir + ydir) * drawsize * 0.2f, tx, ty, col2); va->AddVertexQTC( pos - xdirDS + ydirDS + zdir * difs[6], tx, ty, col); va->AddVertexQTC( pos - xdirDS - ydirDS + zdir * difs[6], tx, ty, col); }
void CSmokeTrailProjectile::Draw() { inArray = true; float age = gs->frameNum + globalRendering->timeOffset - creationTime; va->EnlargeArrays(8 * 4, 0, VA_SIZE_TC); if (drawTrail) { const float3 dif1 = (pos1 - camera->GetPos()).ANormalize(); const float3 dif2 = (pos2 - camera->GetPos()).ANormalize(); const float3 odir1 = (dif1.cross(dir1)).ANormalize(); const float3 odir2 = (dif2.cross(dir2)).ANormalize(); unsigned char col[4]; float a1 = (1 - (float) age / lifeTime) * 255; if (lastSegment) { a1 = 0; } a1 *= 0.7f + math::fabs(dif1.dot(dir1)); float alpha = std::min(255.f, std::max(0.f, a1)); col[0] = (unsigned char) (color * alpha); col[1] = (unsigned char) (color * alpha); col[2] = (unsigned char) (color * alpha); col[3] = (unsigned char) alpha; unsigned char col2[4]; float a2 = (1 - (float)(age + 8) / lifeTime) * 255; if (firstSegment) { a2 = 0; } a2 *= 0.7f + math::fabs(dif2.dot(dir2)); alpha = std::min(255.f, std::max(0.0f, a2)); col2[0] = (unsigned char) (color * alpha); col2[1] = (unsigned char) (color * alpha); col2[2] = (unsigned char) (color * alpha); col2[3] = (unsigned char) alpha; float size = 1 + ( age * (1.0f / lifeTime)) * orgSize; float size2 = 1 + ((age + 8) * (1.0f / lifeTime)) * orgSize; if (drawSegmented) { const float3 dif3 = (midpos - camera->GetPos()).ANormalize(); const float3 odir3 = (dif3.cross(middir)).ANormalize(); float size3 = 0.2f + ((age + 4) * (1.0f / lifeTime)) * orgSize; unsigned char col3[4]; float a2 = (1 - (float)(age + 4) / lifeTime) * 255; a2 *= 0.7f + math::fabs(dif3.dot(middir)); alpha = std::min(255.0f, std::max(0.0f, a2)); col3[0] = (unsigned char) (color * alpha); col3[1] = (unsigned char) (color * alpha); col3[2] = (unsigned char) (color * alpha); col3[3] = (unsigned char) alpha; const float midtexx = texture->xstart + ((texture->xend - texture->xstart) * 0.5f); va->AddVertexQTC(pos1 - (odir1 * size), texture->xstart, texture->ystart, col); va->AddVertexQTC(pos1 + (odir1 * size), texture->xstart, texture->yend, col); va->AddVertexQTC(midpos + (odir3 * size3), midtexx, texture->yend, col3); va->AddVertexQTC(midpos - (odir3 * size3), midtexx, texture->ystart, col3); va->AddVertexQTC(midpos - (odir3 * size3), midtexx, texture->ystart, col3); va->AddVertexQTC(midpos + (odir3 * size3), midtexx, texture->yend, col3); va->AddVertexQTC(pos2 + (odir2 * size2), texture->xend, texture->yend, col2); va->AddVertexQTC(pos2 - (odir2 * size2), texture->xend, texture->ystart, col2); } else { va->AddVertexQTC(pos1 - (odir1 * size), texture->xstart, texture->ystart, col); va->AddVertexQTC(pos1 + (odir1 * size), texture->xstart, texture->yend, col); va->AddVertexQTC(pos2 + (odir2 * size2), texture->xend, texture->yend, col2); va->AddVertexQTC(pos2 - (odir2 * size2), texture->xend, texture->ystart, col2); } } else { // draw as particles unsigned char col[4]; for (int a = 0; a < 8; ++a) { const float a1 = 1 - (float)(age + a) / lifeTime; const float alpha = std::min(255.0f, std::max(0.0f, a1 * 255)); const float size = ((0.2f + (age + a) * (1.0f / lifeTime)) * orgSize) * 1.2f; col[0] = (unsigned char) (color * alpha); col[1] = (unsigned char) (color * alpha); col[2] = (unsigned char) (color * alpha); col[3] = (unsigned char) alpha; #define st projectileDrawer->smoketex[0] va->AddVertexQTC(pos1 + ( camera->up + camera->right) * size, st->xstart, st->ystart, col); va->AddVertexQTC(pos1 + ( camera->up - camera->right) * size, st->xend, st->ystart, col); va->AddVertexQTC(pos1 + (-camera->up - camera->right) * size, st->xend, st->ystart, col); va->AddVertexQTC(pos1 + (-camera->up + camera->right) * size, st->xstart, st->ystart, col); #undef st } } CProjectile* callbacker = drawCallbacker; if (callbacker != NULL) { callbacker->DrawCallback(); } }
particles[i].size = particles[i].size*sizeMod + sizeGrowth; deleteMe = false; } } } void CSimpleParticleSystem::Init(const float3& explosionPos, CUnit *owner GML_PARG_C) { CProjectile::Init(explosionPos, owner GML_PARG_P); particles = new Particle[numParticles]; float3 up = emitVector; float3 right = up.cross(float3(up.y,up.z,-up.x)); float3 forward = up.cross(right); for(int i=0; i<numParticles; i++) { float az = gu->usRandFloat()*2*PI; float ay = (emitRot + emitRotSpread*gu->usRandFloat())*(PI/180.0); particles[i].decayrate = 1.0f/(particleLife + gu->usRandFloat()*particleLifeSpread); particles[i].life = 0; particles[i].size = particleSize + gu->usRandFloat()*particleSizeSpread; particles[i].pos = pos; particles[i].speed = ((up*emitMul.y)*cos(ay)-((right*emitMul.x)*cos(az)-(forward*emitMul.z)*sin(az))*sin(ay)) * (particleSpeed + gu->usRandFloat()*particleSpeedSpread); }
void CPieceProjectile::Draw() { if (flags & PF_NoCEGTrail) { if (flags & PF_Smoke) { // this piece leaves a default (non-CEG) smoketrail inArray = true; float age2 = (age & 7) + globalRendering->timeOffset; float color = 0.5f; unsigned char col[4]; float3 dir = speed; dir.Normalize(); int numParts = age & 7; va->EnlargeArrays(4+4*numParts,0,VA_SIZE_TC); if (drawTrail) { // draw the trail as a single quad if camera close enough const float3 dif = (drawPos - camera->pos).Normalize(); const float3 dir1 = (dif.cross(dir)).Normalize(); const float3 dif2 = (oldSmokePos - camera->pos).Normalize(); const float3 dir2 = (dif2.cross(oldSmokeDir)).Normalize(); float a1 = ((1 - 0.0f / (Smoke_Time)) * 255) * (0.7f + fabs(dif.dot(dir))); float alpha = std::min(255.0f, std::max(0.f, a1)); col[0] = (unsigned char) (color * alpha); col[1] = (unsigned char) (color * alpha); col[2] = (unsigned char) (color * alpha); col[3] = (unsigned char) (alpha); unsigned char col2[4]; float a2 = ((1 - float(age2) / (Smoke_Time)) * 255) * (0.7f + fabs(dif2.dot(oldSmokeDir))); if (age < 8) a2 = 0; alpha = std::min(255.0f, std::max(0.f, a2)); col2[0] = (unsigned char) (color * alpha); col2[1] = (unsigned char) (color * alpha); col2[2] = (unsigned char) (color * alpha); col2[3] = (unsigned char) (alpha); const float size = 1.0f; const float size2 = 1 + (age2 * (1 / Smoke_Time)) * 14; const float txs = projectileDrawer->smoketrailtex->xstart - (projectileDrawer->smoketrailtex->xend - projectileDrawer->smoketrailtex->xstart) * (age2 / 8.0f); va->AddVertexQTC(drawPos - dir1 * size, txs, projectileDrawer->smoketrailtex->ystart, col); va->AddVertexQTC(drawPos + dir1 * size, txs, projectileDrawer->smoketrailtex->yend, col); va->AddVertexQTC(oldSmokePos + dir2 * size2, projectileDrawer->smoketrailtex->xend, projectileDrawer->smoketrailtex->yend, col2); va->AddVertexQTC(oldSmokePos - dir2 * size2, projectileDrawer->smoketrailtex->xend, projectileDrawer->smoketrailtex->ystart, col2); } else { // draw the trail as particles const float dist = pos.distance(oldSmokePos); const float3 dirpos1 = pos - dir * dist * 0.33f; const float3 dirpos2 = oldSmokePos + oldSmokeDir * dist * 0.33f; for (int a = 0; a < numParts; ++a) { //! CAUTION: loop count must match EnlargeArrays above float alpha = 255.0f; col[0] = (unsigned char) (color * alpha); col[1] = (unsigned char) (color * alpha); col[2] = (unsigned char) (color * alpha); col[3] = (unsigned char) (alpha); const float size = 1.0f + ((a) * (1.0f / Smoke_Time)) * 14.0f; const float3 pos1 = CalcBeizer(float(a) / (numParts), pos, dirpos1, dirpos2, oldSmokePos); #define st projectileDrawer->smoketex[0] va->AddVertexQTC(pos1 + ( camera->up+camera->right) * size, st->xstart, st->ystart, col); va->AddVertexQTC(pos1 + ( camera->up-camera->right) * size, st->xend, st->ystart, col); va->AddVertexQTC(pos1 + (-camera->up-camera->right) * size, st->xend, st->ystart, col); va->AddVertexQTC(pos1 + (-camera->up+camera->right) * size, st->xstart, st->ystart, col); #undef st } } } } DrawCallback(); }