void DrawFrame() { //_LAT(LED1) = 1; global_drawop = SRCCOPY; SetFontSize(1); SetFont(fonts.Stellaris); // Draw the wallpaper //DrawImage(0,0,wallpaper); ClearImage(); // Draw foreground app if (foreground_app != NULL) foreground_app->draw(); // Draw the battery bar uint8 w = mLerp(0,100, 0,DISPLAY_WIDTH, battery_level); color_t c = WHITE; switch (power_status) { case pwBattery: { switch (battery_status) { case batFull: c = SKYBLUE; break; case batNormal: c = SKYBLUE; break; case batLow: c = RED; break; // No need to put batFlat or batNotConnected default: break; } break; } case pwCharged: c = GREEN; break; case pwCharging: c = ORANGE; break; } // Extra padding at the top of the display to compensate for the bezel //DrawBox(0,0, DISPLAY_WIDTH,4, BLACK,BLACK); DrawBox(0,0, w,3, c,c); // Draw the battery icon if (power_status == pwBattery) { char s[8]; sprintf(s, "%3d%%", battery_level); //utoa(s, battery_level, 10); //int x = DISPLAY_WIDTH - StringWidth(s) - 2; int x = DISPLAY_WIDTH - 30; DrawImString(s, x,5, WHITE); } else { if (usb_connected) { DrawImage(DISPLAY_WIDTH-USB_WIDTH-2,5, &img_usb); } else { DrawImage(DISPLAY_WIDTH-POWER_WIDTH-2,6, &img_power); } } // Framerate debug info // char s[8]; // sprintf(s, "%d", draw_ticks); // DrawString(s, 4,5, DARKGREEN); }
void PSSMLightShadowMap::_calcSplitPos(const Frustum& currFrustum) { const F32 nearDist = 0.01f; // TODO: Should this be adjustable or different? const F32 farDist = currFrustum.getFarDist(); for ( U32 i = 1; i < mNumSplits; i++ ) { F32 step = (F32) i / (F32) mNumSplits; F32 logSplit = nearDist * mPow(farDist / nearDist, step); F32 linearSplit = nearDist + (farDist - nearDist) * step; mSplitDist[i] = mLerp( linearSplit, logSplit, mClampF( mLogWeight, 0.0f, 1.0f ) ); } mSplitDist[0] = nearDist; mSplitDist[mNumSplits] = farDist; }
void PxSingleActor::_updateContainerForces() { if ( !mWorld->getEnabled() ) return; PROFILE_SCOPE( PxSingleActor_updateContainerForces ); // Update container drag and buoyancy properties ContainerQueryInfo info; info.box = getWorldBox(); info.mass = getMass(); // Find and retreive physics info from intersecting WaterObject(s) mContainer->findObjects( getWorldBox(), WaterObjectType|PhysicalZoneObjectType, findRouter, &info ); // Calculate buoyancy and drag F32 angDrag = mBuildAngDrag; F32 linDrag = mBuildLinDrag; F32 buoyancy = 0.0f; if ( true ) //info.waterCoverage >= 0.1f) { F32 waterDragScale = info.waterViscosity * mDataBlock->waterDragScale; F32 powCoverage = mPow( info.waterCoverage, 0.25f ); if ( info.waterCoverage > 0.0f ) { //angDrag = mBuildAngDrag * waterDragScale; //linDrag = mBuildLinDrag * waterDragScale; angDrag = mLerp( mBuildAngDrag, mBuildAngDrag * waterDragScale, powCoverage ); linDrag = mLerp( mBuildLinDrag, mBuildLinDrag * waterDragScale, powCoverage ); } buoyancy = ( info.waterDensity / mDataBlock->buoyancyDensity ) * mPow( info.waterCoverage, 2.0f ); } // Apply drag (dampening) mActor->setLinearDamping( linDrag ); mActor->setAngularDamping( angDrag ); // Apply buoyancy force if ( buoyancy != 0 ) { // A little hackery to prevent oscillation // Based on this blog post (http://reinot.blogspot.com/2005/11/oh-yes-they-float-georgie-they-all.html) // JCF: DISABLED NxVec3 gravity; mWorld->getScene()->getGravity(gravity); //NxVec3 velocity = mActor->getLinearVelocity(); NxVec3 buoyancyForce = buoyancy * -gravity * TickSec; //F32 currHeight = getPosition().z; //const F32 C = 2.0f; //const F32 M = 0.1f; //if ( currHeight + velocity.z * TickSec * C > info.waterHeight ) // buoyancyForce *= M; mActor->addForceAtPos( buoyancyForce, mActor->getCMassGlobalPosition(), NX_IMPULSE ); } // Apply physical zone forces if ( info.appliedForce.len() > 0.001f ) mActor->addForceAtPos( pxCast<NxVec3>(info.appliedForce), mActor->getCMassGlobalPosition(), NX_IMPULSE ); }
void ClippedPolyList::end() { PROFILE_SCOPE( ClippedPolyList_Clip ); Poly& poly = mPolyList.last(); // Reject polygons facing away from our normal. if ( mDot( poly.plane, mNormal ) < mNormalTolCosineRadians ) { mIndexList.setSize(poly.vertexStart); mPolyList.decrement(); return; } // Build initial inside/outside plane masks U32 indexStart = poly.vertexStart; U32 vertexCount = mIndexList.size() - indexStart; U32 frontMask = 0,backMask = 0; U32 i; for (i = indexStart; i < mIndexList.size(); i++) { U32 mask = mVertexList[mIndexList[i]].mask; frontMask |= mask; backMask |= ~mask; } // Trivial accept if all the vertices are on the backsides of // all the planes. if (!frontMask) { poly.vertexCount = vertexCount; return; } // Trivial reject if any plane not crossed has all it's points // on the front. U32 crossMask = frontMask & backMask; if (~crossMask & frontMask) { mIndexList.setSize(poly.vertexStart); mPolyList.decrement(); return; } // Potentially, this will add up to mPlaneList.size() * (indexStart - indexEnd) // elements to mIndexList, so ensure that it has enough space to store that // so we can use push_back_noresize. If you find this code block getting hit // frequently, changing the value of 'IndexListReserveSize' or doing some selective // allocation is suggested // // TODO: Re-visit this, since it obviously does not work correctly, and than // re-enable the push_back_noresize //while(mIndexList.size() + mPlaneList.size() * (mIndexList.size() - indexStart) > mIndexList.capacity() ) // mIndexList.reserve(mIndexList.capacity() * 2); // Need to do some clipping for (U32 p = 0; p < mPlaneList.size(); p++) { U32 pmask = 1 << p; // Only test against this plane if we have something // on both sides if (!(crossMask & pmask)) continue; U32 indexEnd = mIndexList.size(); U32 i1 = indexEnd - 1; U32 mask1 = mVertexList[mIndexList[i1]].mask; for (U32 i2 = indexStart; i2 < indexEnd; i2++) { U32 mask2 = mVertexList[mIndexList[i2]].mask; if ((mask1 ^ mask2) & pmask) { // mVertexList.increment(); VectorF& v1 = mVertexList[mIndexList[i1]].point; VectorF& v2 = mVertexList[mIndexList[i2]].point; VectorF vv = v2 - v1; F32 t = -mPlaneList[p].distToPlane(v1) / mDot(mPlaneList[p],vv); mNormalList.increment(); VectorF& n1 = mNormalList[mIndexList[i1]]; VectorF& n2 = mNormalList[mIndexList[i1]]; VectorF nn = mLerp( n1, n2, t ); nn.normalizeSafe(); mNormalList.last() = nn; mIndexList.push_back/*_noresize*/(mVertexList.size() - 1); Vertex& iv = mVertexList.last(); iv.point.x = v1.x + vv.x * t; iv.point.y = v1.y + vv.y * t; iv.point.z = v1.z + vv.z * t; iv.mask = 0; // Test against the remaining planes for (U32 i = p + 1; i < mPlaneList.size(); i++) if (mPlaneList[i].distToPlane(iv.point) > 0) { iv.mask = 1 << i; break; } } if (!(mask2 & pmask)) { U32 index = mIndexList[i2]; mIndexList.push_back/*_noresize*/(index); } mask1 = mask2; i1 = i2; } // Check for degenerate indexStart = indexEnd; if (mIndexList.size() - indexStart < 3) { mIndexList.setSize(poly.vertexStart); mPolyList.decrement(); return; } } // Emit what's left and compress the index list. poly.vertexCount = mIndexList.size() - indexStart; memcpy(&mIndexList[poly.vertexStart], &mIndexList[indexStart],poly.vertexCount); mIndexList.setSize(poly.vertexStart + poly.vertexCount); }
void SFXEmitter::_renderCone( F32 radialIncrements, F32 sweepIncrements, F32 pointDistance, F32 startAngle, F32 stopAngle, F32 startVolume, F32 stopVolume, const ColorI& color ) { if( startAngle == stopAngle ) return; const F32 startAngleRadians = mDegToRad( startAngle ); const F32 stopAngleRadians = mDegToRad( stopAngle ); const F32 radialIncrementsRadians = mDegToRad( radialIncrements ); // Unit quaternions representing the start and end angle so we // can interpolate between the two without flipping. QuatF rotateZStart( EulerF( 0.f, 0.f, startAngleRadians / 2.f ) ); QuatF rotateZEnd( EulerF( 0.f, 0.f, stopAngleRadians / 2.f ) ); // Do an angular sweep on one side of our XY disc. Since we do a full 360 radial sweep // around Y for each angle, we only need to sweep over one side. const F32 increment = 1.f / ( ( ( startAngle / 2.f ) - ( stopAngle / 2.f ) ) / sweepIncrements ); for( F32 t = 0.f; t < 1.0f; t += increment ) { // Quaternion to rotate point into place on XY disc. QuatF rotateZ; rotateZ.interpolate( rotateZStart, rotateZEnd, t ); // Quaternion to rotate one position around Y axis. Used for radial sweep. QuatF rotateYOne( EulerF( 0.f, radialIncrementsRadians, 0.f ) ); // Do a radial sweep each step along the distance axis. For each step, volume is // the same for any point on the sweep circle. for( F32 y = pointDistance; y <= mDescription.mMaxDistance; y += pointDistance ) { ColorI c = color; // Compute volume at current point. First off, find the interpolated volume // in the cone. Only for the outer cone will this actually result in // interpolation. For the remaining angles, the cone volume is constant. F32 volume = mLerp( startVolume, stopVolume, t ); if( volume == 0.f ) c.alpha = 0; else { // Apply distance attenuation. F32 attenuatedVolume = SFXDistanceAttenuation( SFX->getDistanceModel(), mDescription.mMinDistance, mDescription.mMaxDistance, y, volume, SFX->getRolloffFactor() ); //RDTODO // Fade alpha according to how much volume we // have left at the current point. c.alpha = F32( c.alpha ) * ( attenuatedVolume / 1.f ); } PrimBuild::color( c ); // Create points by doing a full 360 degree radial sweep around Y. Point3F p( 0.f, y, 0.f ); rotateZ.mulP( p, &p ); for( F32 radialAngle = 0.f; radialAngle < 360.f; radialAngle += radialIncrements ) { PrimBuild::vertex3f( p.x, p.y, p.z ); rotateYOne.mulP( p, &p ); } } } }