void Turboprop::updateVisuals(RoR::GfxActor* gfx_actor) { RoR::GfxActor::NodeData* node_buf = gfx_actor->GetSimNodeBuffer(); //smoke if (smokeNode) { smokeNode->setPosition(node_buf[nodeback].AbsPosition); ParticleEmitter* emit = smokePS->getEmitter(0); Vector3 dir = node_buf[nodeback].AbsPosition - node_buf[noderef].AbsPosition; emit->setDirection(dir); emit->setParticleVelocity(propwash - propwash / 10, propwash + propwash / 10); if (!failed) { if (ignition) { emit->setEnabled(true); emit->setColour(ColourValue(0.0, 0.0, 0.0, 0.03 + throtle * 0.05)); emit->setTimeToLive((0.03 + throtle * 0.05) / 0.1); } else { emit->setEnabled(false); } } else { emit->setDirection(Vector3(0, 1, 0)); emit->setParticleVelocity(5, 9); emit->setEnabled(true); emit->setColour(ColourValue(0.0, 0.0, 0.0, 0.1)); emit->setTimeToLive(0.1 / 0.1); } } #ifdef USE_ANGELSCRIPT if (failed != failedold) { TRIGGER_EVENT(SE_TRUCK_ENGINE_FIRE, trucknum); failedold = failed; } #endif }
//------------------------------------------------------------------------------------------------------- // Update //------------------------------------------------------------------------------------------------------- void CarModel::Update(PosInfo& posInfo, PosInfo& posInfoCam, float time) { pReflect->camPosition = pMainNode->getPosition(); int w,i; // upd chk mtr if (bChkUpd && entNextChk) { MaterialPtr mtr = MaterialManager::getSingleton().getByName(sChkMtr); if (!mtr.isNull()) entNextChk->setMaterial(mtr); } // stop/resume par sys float fa = pGame->pause ? 0.f : 1.f; for (w=0; w < numWheels; ++w) { for (i=0; i < PAR_ALL; ++i) if (par[i][w]) par[i][w]->setSpeedFactor(fa); if (w < PAR_BOOST && parBoost[w]) parBoost[w]->setSpeedFactor(fa); if (parHit) parHit->setSpeedFactor(fa); } for (w=0; w < PAR_THRUST*2; ++w) if (parThrust[w]) parThrust[w]->setSpeedFactor(fa); if (!posInfo.bNew) return; // new only ? posInfo.bNew = false; /// dont get anything from pCar or car.dynamics here /// all must be read from posInfo (it is filled from vdrift car or from replay) if (!pMainNode) return; // set car pos and rot pMainNode->setPosition(posInfo.pos); if (vtype == V_Sphere) pMainNode->setOrientation(Quaternion(Quaternion(Degree(-posInfo.hov_roll),Vector3::UNIT_Y))); else if (vtype == V_Spaceship) // roll vis only pMainNode->setOrientation(posInfo.rot * Quaternion(Degree(posInfo.hov_roll),Vector3::UNIT_X)); else pMainNode->setOrientation(posInfo.rot); ///() grass sphere pos Vector3 vx(1,0,0); // car x dir vx = posInfo.rot * vx * 1.1; //par posSph[0] = posInfo.pos + vx; posSph[0].y += 0.5f; posSph[1] = posInfo.pos - vx; posSph[1].y += 0.5f; if (ndSph) // sph test { ndSph->setPosition(posSph[0]); ndSph->setScale(Vector3::UNIT_SCALE * 1.7 *2/0.6f); //par } // set camera view if (fCam) { fCam->Apply(posInfoCam); ///~~ camera in fluid fog, detect and compute iCamFluid = -1; fCamFl = 0.f; // none const size_t sf = sc->fluids.size(); if (sf > 0 && pSet->game.local_players == 1) { const Vector3& p = posInfo.camPos; const float r = 0.2f; //par, near cam? // check if any fluid box overlaps camera pos sphere bool srch = true; size_t f = 0; while (srch && f < sf) { const FluidBox& fb = sc->fluids[f]; const Vector3& fp = fb.pos; Vector3 fs = fb.size; fs.x *= 0.5f; fs.z *= 0.5f; bool inFl = // p +r -fs fp +fs -r p p.y +r > fp.y - fs.y && p.y -r < fp.y && p.x +r > fp.x - fs.x && p.x -r < fp.x + fs.x && p.z +r > fp.z - fs.z && p.z -r < fp.z + fs.z; if (inFl) // 1st only { iCamFluid = f; fCamFl = std::min(1.f, std::max(0.f, fp.y - p.y)) * 3.f; srch = false; } ++f; } } } // upd rotY for minimap if (vtype == V_Sphere) angCarY = posInfo.hov_roll * 180.f / PI_d + 180.f; else { Quaternion q = posInfo.rot * Quaternion(Degree(90),Vector3(0,1,0)); angCarY = q.getYaw().valueDegrees() + 90.f; } // brake state #ifndef CAR_PRV bool braking = posInfo.braking > 0; if (bBraking != braking) { bBraking = braking; UpdateBraking(); } #endif // terrain lightmap enable/disable (depending on distance to terrain) #define MAX_TERRAIN_DIST 2.0 // meters bool changed = false; if (terrain) { Vector3 carPos = pMainNode->getPosition(); float terrainHeight = terrain->getHeightAtWorldPosition(carPos); float diff = std::abs(carPos.y - terrainHeight); if (diff > MAX_TERRAIN_DIST) { if (bLightMapEnabled) { changed = true; bLightMapEnabled = false; } } else if (!bLightMapEnabled) { changed = true; bLightMapEnabled = true; } } // if no terrain, disable else if (bLightMapEnabled) { changed = true; bLightMapEnabled = false; } if (changed) UpdateLightMap(); // update particle emitters if (pSet->particles && pCar) { // boost for (i=0; i < PAR_BOOST; ++i) if (parBoost[i]) { /// <><> damage reduce float dmg = pCar->dynamics.fDamage >= 80.f ? 0.f : std::max(0.f, 1.4f - pCar->dynamics.fDamage*0.01f); float emitB = posInfo.fboost * 40.f * dmg; // par ParticleEmitter* pe = parBoost[i]->getEmitter(0); pe->setEmissionRate(emitB); } // spaceship thrusters for (i=0; i < PAR_THRUST*2; ++i) if (parThrust[i]) { float dmg = 1.f - 0.5f * pCar->dynamics.fDamage*0.01f; float emitT = posInfo.hov_throttle * 60.f * dmg; // par ParticleEmitter* pe = parThrust[i]->getEmitter(0); pe->setEmissionRate(emitT); } } // world hit if (parHit) { ParticleEmitter* pe = parHit->getEmitter(0); if (posInfo.fHitTime > 0.f && pSet->particles) { pe->setPosition(posInfo.vHitPos); pe->setDirection(posInfo.vHitNorm); pe->setEmissionRate(pSet->particles_len * std::min(160.f, posInfo.fParIntens) * posInfo.fHitTime); pe->setParticleVelocity(posInfo.fParVel); }else pe->setEmissionRate(0.f); } // wheels ------------------------------------------------------------------------ const float trlH = sc->ter ? 0.90f : 0.76f; // vdr needs up (ter bumps), no ter ..get from wheel contact ?rpl for (w=0; w < numWheels; ++w) { float wR = whRadius[w]; #ifdef CAM_TILT_DBG // cam debug test only if (fCam) ndWh[w]->setPosition(fCam->posHit[w]); ndWh[w]->setScale(0.5f*Vector3::UNIT_SCALE); #else ndWh[w]->setPosition(posInfo.whPos[w]); #endif ndWh[w]->setOrientation(posInfo.whRot[w]); /// Update particles and trails if (isGhostTrk()) continue; // doesnt have any int whMtr = posInfo.whTerMtr[w]; int whRd = posInfo.whRoadMtr[w]; bool pipe = whRd >= 30 && whRd < 60; //old: whRd == 2; //todo: road,pipe 4mtr [whRd] layer params.. float whVel = posInfo.whVel[w] * 3.6f; //kmh float slide = posInfo.whSlide[w], squeal = posInfo.whSqueal[w]; //LogO(" slide:"+fToStr(slide,3,5)+" squeal:"+fToStr(squeal,3,5)); float onGr = slide < 0.f ? 0.f : 1.f; // wheel temp whTemp[w] += std::min(12.f, std::max(0.f, squeal*8 - slide*2 + squeal*slide*2)*time); whTemp[w] = std::min(1.5f, whTemp[w]); ///* whTemp[w] -= time*7.f; if (whTemp[w] < 0.f) whTemp[w] = 0.f; //LogO(toStr(w)+" wht "+fToStr(wht[w],3,5)); /// emit rates + Real sq = squeal* std::min(1.f, whTemp[w]), l = pSet->particles_len * onGr; Real emitS = sq * (whVel * 30) * l * 0.45f; ///* Real emitM = slide < 1.4f ? 0.f : (8.f * sq * std::min(5.f, slide) * l); Real emitD = (std::min(140.f, whVel) / 3.5f + slide * 1.f ) * l; Real sizeD = (0.8f + 0.6f * std::min(140.f, whVel) / 140.f) * (w < 2 ? 0.7f : 1.1f); // ter mtr factors int mtr = std::max(0, std::min(whMtr-1, (int)(sc->td.layers.size()-1))); int rd = sc->td.road1mtr ? 0 : std::max(0, std::min(3, whRd)); TerLayer& lay = whMtr==0 ? sc->td.layerRoad[rd] : sc->td.layersAll[sc->td.layers[mtr]]; emitD *= lay.dust; emitM *= lay.mud; sizeD *= lay.dustS; emitS *= lay.smoke; if (pipe) emitD = 0; // no dust in pipes if (posInfo.whH[w] > 0.1f) emitD = 0; // no dust in fluids bool ghost = isGhost(); // opt dis for ghost bool ghPar = !(ghost && !pSet->rpl_ghostpar); if (!ghPar) { emitD = 0.f; emitM = 0.f; emitS = 0.f; } /// emit particles Vector3 vpos = posInfo.whPos[w]; if (pSet->particles) { ParticleSystem* ps = par[PAR_Smoke][w]; if (ps) // smoke { ParticleEmitter* pe = ps->getEmitter(0); pe->setPosition(vpos + posInfo.carY * wR*0.7f); ///* ps->getAffector(0)->setParameter("alpha", toStr(-0.2f - 0.023f * whVel)); // fade out speed pe->setTimeToLive( std::max(0.12f, 2.f - whVel * 0.06f) ); // live time pe->setDirection(-posInfo.carY); pe->setEmissionRate(emitS); } ps = par[PAR_Mud][w]; if (ps) // mud { ParticleEmitter* pe = ps->getEmitter(0); //pe->setDimensions(sizeM,sizeM); pe->setPosition(vpos + posInfo.carY * wR*0.7f); pe->setDirection(-posInfo.carY); pe->setEmissionRate(emitM); } ps = par[PAR_Dust][w]; if (ps) // dust { ps->setDefaultDimensions(sizeD,sizeD); ParticleEmitter* pe = ps->getEmitter(0); pe->setPosition(vpos + posInfo.carY * wR*0.31f); pe->setDirection(-posInfo.carY); pe->setEmissionRate(emitD); } // fluids .::. ps = par[PAR_Water][w]; int idPar = posInfo.whP[w]; if (ps) // Water ~ { float vel = posInfo.speed; // depth.. only on surface? bool e = idPar == 0 && ghPar && vel > 10.f && posInfo.whH[w] < 1.f; float emitW = e ? std::min(80.f, 5.0f * vel) : 0.f; ParticleEmitter* pe = ps->getEmitter(0); pe->setPosition(vpos + posInfo.carY * wR*0.51f); pe->setMinParticleVelocity(0.07* vel); pe->setMaxParticleVelocity(0.20* vel); pe->setDirection(-posInfo.carY); pe->setEmissionRate(emitW * pSet->particles_len); } ps = par[PAR_MudHard][w]; if (ps) // Mud ^ { float vel = Math::Abs(posInfo.whAngVel[w]); bool e = idPar == 2 && ghPar && vel > 30.f; float emitM = e ? posInfo.whH[w] * std::min(80.f, 1.5f * vel) : 0.f; ParticleEmitter* pe = ps->getEmitter(0); pe->setPosition(vpos + posInfo.carY * wR*0.51f); pe->setDirection(-posInfo.carY); pe->setEmissionRate(emitM * pSet->particles_len); } ps = par[PAR_MudSoft][w]; if (ps) // Mud soft ^ { float vel = Math::Abs(posInfo.whAngVel[w]); bool e = idPar == 1 && ghPar && vel > 30.f; float emitM = e ? posInfo.whH[w] * std::min(160.f, 3.f * vel) : 0.f; ParticleEmitter* pe = ps->getEmitter(0); pe->setPosition(vpos + posInfo.carY * wR*0.51f); pe->setDirection(-posInfo.carY); pe->setEmissionRate(emitM * pSet->particles_len); } } // update trails h+ if (pSet->trails) { if (ndWhE[w]) { Vector3 vp = vpos + posInfo.carY * wR*trlH; if (terrain && whMtr > 0) vp.y = terrain->getHeightAtWorldPosition(vp) + 0.02f; // 0.05f //if (/*whOnRoad[w]*/whMtr > 0 && road) // on road, add ofs // vp.y += road->fHeight; }/**/ ndWhE[w]->setPosition(vp); ndWhE[w]->setOrientation(posInfo.rot); } // const trail alpha float ac = pipe ? 0.f : /*own par..*/lay.smoke < 0.5f ? 0.14f : 0.f; float al = (ac + 0.6f * std::min(1.f, 0.7f * whTemp[w]) ) * onGr; // par+ if (whTrail[w]) { whTrail[w]->setInitialColour(0, lay.tcl.x, lay.tcl.y, lay.tcl.z, lay.tcl.w * al/**/); if (iFirst > 10) //par whTrail[w]->setInitialWidth(0, whWidth[w]); } } } // blendmap UpdWhTerMtr(); // update brake meshes orientation for (w=0; w < numWheels; ++w) { if (ndBrake[w]) { ndBrake[w]->_setDerivedOrientation( pMainNode->getOrientation() ); // this transformation code is just so the brake mesh can have the same alignment as the wheel mesh ndBrake[w]->yaw(Degree(-90), Node::TS_LOCAL); if (w%2 == 1) ndBrake[w]->setScale(-1, 1, 1); ndBrake[w]->pitch(Degree(180), Node::TS_LOCAL); if (w < 2) // turn only front wheels ndBrake[w]->yaw(-Degree(posInfo.whSteerAng[w])); } } if (iFirst <= 10) ++iFirst; //par UpdateKeys(); }
void Turbojet::updateVisuals() { //nozzle nzsnode->setPosition(nodes[nodeback].AbsPosition); //build a local system Vector3 laxis = nodes[nodefront].RelPosition - nodes[nodeback].RelPosition; laxis.normalise(); Vector3 paxis = Plane(laxis, 0).projectVector(nodes[noderef].RelPosition - nodes[nodeback].RelPosition); paxis.normalise(); Vector3 taxis = laxis.crossProduct(paxis); Quaternion dir = Quaternion(laxis, paxis, taxis); nzsnode->setOrientation(dir); //afterburner if (afterburner) { absnode->setVisible(true); float flamelength = (afterburnthrust / 15.0) * (rpm / 100.0); flamelength = flamelength * (1.0 + (((Real)rand() / (Real)RAND_MAX) - 0.5) / 10.0); absnode->setScale(flamelength, radius * 2.0, radius * 2.0); absnode->setPosition(nodes[nodeback].AbsPosition + dir * Vector3(-0.2, 0.0, 0.0)); absnode->setOrientation(dir); } else absnode->setVisible(false); //smoke if (smokeNode) { smokeNode->setPosition(nodes[nodeback].AbsPosition); ParticleEmitter* emit = smokePS->getEmitter(0); ParticleEmitter* hemit = 0; if (heathazePS) hemit = heathazePS->getEmitter(0); emit->setDirection(-axis); emit->setParticleVelocity(exhaust_velocity); if (hemit) { hemit->setDirection(-axis); hemit->setParticleVelocity(exhaust_velocity); } if (!failed) { if (ignition) { emit->setEnabled(true); emit->setColour(ColourValue(0.0, 0.0, 0.0, 0.02 + throtle * 0.03)); emit->setTimeToLive((0.02 + throtle * 0.03) / 0.1); if (hemit) { hemit->setEnabled(true); hemit->setTimeToLive((0.02 + throtle * 0.03) / 0.1); } } else { emit->setEnabled(false); if (hemit) hemit->setEnabled(false); } } else { emit->setDirection(Vector3(0, 1, 0)); emit->setParticleVelocity(7.0); emit->setEnabled(true); emit->setColour(ColourValue(0.0, 0.0, 0.0, 0.1)); emit->setTimeToLive(0.1 / 0.1); if (hemit) { hemit->setDirection(Vector3(0, 1, 0)); hemit->setParticleVelocity(7.0); hemit->setEnabled(true); hemit->setTimeToLive(0.1 / 0.1); } } } }
void DustPool::update(float gspeed) { gspeed=fabs(gspeed); for (int i=0; i<allocated; i++) { ParticleEmitter *emit = pss[i]->getEmitter(0); Vector3 ndir = velocities[i]; Real vel = ndir.length(); ColourValue col = colours[i]; if (vel == 0) vel += 0.0001; ndir = ndir / vel; emit->setEnabled(true); if (types[i] != DUST_RIPPLE) { emit->setDirection(ndir); emit->setParticleVelocity(vel); sns[i]->setPosition(positions[i]); } if (types[i]==DUST_NORMAL) { ndir.y=0; ndir=ndir/2.0; col.a=(vel+(gspeed/10.0))*0.05; emit->setTimeToLive((vel+(gspeed/10.0))*0.05/0.1); } else if (types[i]==DUST_CLUMP) { ndir=ndir/2.0; if (ndir.y<0) ndir.y=-ndir.y; col.a=1.0; } else if (types[i]==DUST_RUBBER) { ndir.y=0; ndir=ndir/4.0; col.a = vel*0.05; col.b = 0.9; col.g = 0.9; col.r = 0.9; emit->setTimeToLive(vel*0.05/0.1); } else if (types[i]==DUST_SPARKS) { //ugh } else if (types[i]==DUST_VAPOUR) { emit->setParticleVelocity(vel/2.0); col.a = rates[i] * 0.03; col.b = 0.9; col.g = 0.9; col.r = 0.9; emit->setTimeToLive(rates[i]*0.03/0.1); } else if (types[i]==DUST_DRIP) { emit->setEmissionRate(rates[i]); } else if (types[i]==DUST_SPLASH) { if (ndir.y<0) ndir.y=-ndir.y/2.0; emit->setDirection(ndir); col.a = vel*0.05; col.b = 0.9; col.g = 0.9; col.r = 0.9; emit->setTimeToLive(vel*0.05/0.1); } else if (types[i]==DUST_RIPPLE) { positions[i].y = gEnv->terrainManager->getWater()->getHeight() - 0.02; sns[i]->setPosition(positions[i]); col.a = vel*0.04; col.b = 0.9; col.g = 0.9; col.r = 0.9; emit->setTimeToLive(vel*0.04/0.1); } emit->setColour(col); } for (int i=allocated; i<size; i++) { pss[i]->getEmitter(0)->setEnabled(false); } allocated=0; }