void CubeReflector::updateFace( const ReflectParams ¶ms, U32 faceidx ) { GFXDEBUGEVENT_SCOPE( CubeReflector_UpdateFace, ColorI::WHITE ); // store current matrices GFXTransformSaver saver; // set projection to 90 degrees vertical and horizontal F32 left, right, top, bottom; MathUtils::makeFrustum( &left, &right, &top, &bottom, M_HALFPI_F, 1.0f, mDesc->nearDist ); GFX->setFrustum( left, right, bottom, top, mDesc->nearDist, mDesc->farDist ); // We don't use a special clipping projection, but still need to initialize // this for objects like SkyBox which will use it during a reflect pass. gClientSceneGraph->setNonClipProjection( GFX->getProjectionMatrix() ); // Standard view that will be overridden below. VectorF vLookatPt(0.0f, 0.0f, 0.0f), vUpVec(0.0f, 0.0f, 0.0f), vRight(0.0f, 0.0f, 0.0f); switch( faceidx ) { case 0 : // D3DCUBEMAP_FACE_POSITIVE_X: vLookatPt = VectorF( 1.0f, 0.0f, 0.0f ); vUpVec = VectorF( 0.0f, 1.0f, 0.0f ); break; case 1 : // D3DCUBEMAP_FACE_NEGATIVE_X: vLookatPt = VectorF( -1.0f, 0.0f, 0.0f ); vUpVec = VectorF( 0.0f, 1.0f, 0.0f ); break; case 2 : // D3DCUBEMAP_FACE_POSITIVE_Y: vLookatPt = VectorF( 0.0f, 1.0f, 0.0f ); vUpVec = VectorF( 0.0f, 0.0f,-1.0f ); break; case 3 : // D3DCUBEMAP_FACE_NEGATIVE_Y: vLookatPt = VectorF( 0.0f, -1.0f, 0.0f ); vUpVec = VectorF( 0.0f, 0.0f, 1.0f ); break; case 4 : // D3DCUBEMAP_FACE_POSITIVE_Z: vLookatPt = VectorF( 0.0f, 0.0f, 1.0f ); vUpVec = VectorF( 0.0f, 1.0f, 0.0f ); break; case 5: // D3DCUBEMAP_FACE_NEGATIVE_Z: vLookatPt = VectorF( 0.0f, 0.0f, -1.0f ); vUpVec = VectorF( 0.0f, 1.0f, 0.0f ); break; } // create camera matrix VectorF cross = mCross( vUpVec, vLookatPt ); cross.normalizeSafe(); MatrixF matView(true); matView.setColumn( 0, cross ); matView.setColumn( 1, vLookatPt ); matView.setColumn( 2, vUpVec ); matView.setPosition( mObject->getPosition() ); matView.inverse(); GFX->setWorldMatrix(matView); renderTarget->attachTexture( GFXTextureTarget::Color0, cubemap, faceidx ); GFX->setActiveRenderTarget( renderTarget ); GFX->clear( GFXClearStencil | GFXClearTarget | GFXClearZBuffer, gCanvasClearColor, 1.0f, 0 ); SceneRenderState reflectRenderState ( gClientSceneGraph, SPT_Reflect, SceneCameraState::fromGFX() ); reflectRenderState.getMaterialDelegate().bind( REFLECTMGR, &ReflectionManager::getReflectionMaterial ); reflectRenderState.setDiffuseCameraTransform( params.query->cameraMatrix ); reflectRenderState.disableAdvancedLightingBins(true); // render scene LIGHTMGR->registerGlobalLights( &reflectRenderState.getCullingFrustum(), false ); gClientSceneGraph->renderSceneNoLights( &reflectRenderState, mDesc->objectTypeMask ); LIGHTMGR->unregisterAllLights(); // Clean up. renderTarget->resolve(); }
bool AITurretShape::_testTargetLineOfSight(Point3F& aimPoint, ShapeBase* target, Point3F& sightPoint) { Point3F targetCenter = target->getBoxCenter(); RayInfo ri; bool hit = false; target->disableCollision(); // First check for a clear line of sight to the target's center Point3F testPoint = targetCenter; hit = gServerContainer.castRay(aimPoint, testPoint, sAimTypeMask, &ri); if (hit) { // No clear line of sight to center, so try to the target's right. Players holding // a gun in their right hand will tend to stick their right shoulder out first if // they're peering around some cover to shoot, like a wall. Box3F targetBounds = target->getObjBox(); F32 radius = targetBounds.len_x() > targetBounds.len_y() ? targetBounds.len_x() : targetBounds.len_y(); radius *= 0.5; VectorF toTurret = aimPoint - targetCenter; toTurret.normalizeSafe(); VectorF toTurretRight = mCross(toTurret, Point3F::UnitZ); testPoint = targetCenter + toTurretRight * radius; hit = gServerContainer.castRay(aimPoint, testPoint, sAimTypeMask, &ri); if (hit) { // No clear line of sight to right, so try the target's left VectorF toTurretLeft = toTurretRight * -1.0f; testPoint = targetCenter + toTurretLeft * radius; hit = gServerContainer.castRay(aimPoint, testPoint, sAimTypeMask, &ri); } if (hit) { // No clear line of sight to left, so try the target's top testPoint = targetCenter; testPoint.z += targetBounds.len_z() * 0.5f; hit = gServerContainer.castRay(aimPoint, testPoint, sAimTypeMask, &ri); } if (hit) { // No clear line of sight to top, so try the target's bottom testPoint = targetCenter; testPoint.z -= targetBounds.len_z() * 0.5f; hit = gServerContainer.castRay(aimPoint, testPoint, sAimTypeMask, &ri); } } target->enableCollision(); if (!hit) { // Line of sight point is that last one we tested sightPoint = testPoint; } return !hit; }
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); }