Line2D::Line2D(Ogre::SceneManager &sceneMgr, const Vector2 &startPoint, const Vector2 &endPoint, const ColourValue &colour) : m_sceneMgr(sceneMgr) { m_manObj = m_sceneMgr.createManualObject(); m_manObjNode = m_sceneMgr.getRootSceneNode()->createChildSceneNode(); const String materialName = "line2d_material" + StringConverter::toString(instanceId); m_manObjMaterial = MaterialManager::getSingleton().create(materialName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); m_manObjMaterial->setReceiveShadows(false); m_manObjMaterial->getTechnique(0)->setLightingEnabled(true); SetColour(colour); m_manObj->setRenderQueueGroup(RENDER_QUEUE_OVERLAY); m_manObj->setUseIdentityProjection(true); m_manObj->setUseIdentityView(true); m_manObj->setQueryFlags(0); AxisAlignedBox box; box.setInfinite(); m_manObj->setBoundingBox(box); m_manObj->begin(materialName, Ogre::RenderOperation::OT_LINE_LIST); m_manObj->position(Vector3(startPoint.x, startPoint.y, 0.0f)); m_manObj->position(Vector3(endPoint.x, endPoint.y, 0.0f)); m_manObj->end(); m_manObjNode->attachObject(m_manObj); instanceId++; }
void Camera::calculateFrustumAABB( AxisAlignedBox& outAABB ) const { // calculate a bounding box around the frustum in camera's local space AxisAlignedBox localSpaceAABB; { switch( m_projectionType ) { case PT_PERSPECTIVE: { float y = tan( m_fov * 0.5f ) * m_farZPlane; float x = y * m_aspectRatio; localSpaceAABB.min.set( -x, -y, m_nearZPlane ); localSpaceAABB.max.set( x, y, m_farZPlane ); break; } case PT_ORTHO: { float x = m_nearPlaneWidth * 0.5f; float y = m_nearPlaneHeight * 0.5f; localSpaceAABB.min.set( -x, -y, m_nearZPlane ); localSpaceAABB.max.set( x, y, m_farZPlane ); break; } } } // transform the box to global space const Matrix& globalMtx = getGlobalMtx(); localSpaceAABB.transform( globalMtx, outAABB ); }
//----------------------------------------------------------------------- bool Math::intersects(const Sphere& sphere, const AxisAlignedBox& box) { if (box.isNull()) return false; if (box.isInfinite()) return true; // Use splitting planes const Vector3& center = sphere.getCenter(); Real radius = sphere.getRadius(); const Vector3& min = box.getMinimum(); const Vector3& max = box.getMaximum(); // Arvo's algorithm Real s, d = 0; for (int i = 0; i < 3; ++i) { if (center.ptr()[i] < min.ptr()[i]) { s = center.ptr()[i] - min.ptr()[i]; d += s * s; } else if(center.ptr()[i] > max.ptr()[i]) { s = center.ptr()[i] - max.ptr()[i]; d += s * s; } } return d <= radius * radius; }
//----------------------------------------------------------------------- bool Frustum::IsVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy) { // Null boxes always invisible if (bound.isNull()) return false; // Infinite boxes always visible if (bound.isInfinite()) return true; // Make any pending updates to the calculated frustum planes _UpdateFrustumPlanes(); // Get centre of the box Vector3f centre = bound.getCenter(); // Get the half-size of the box Vector3f halfSize = bound.getHalfSize(); // For each plane, see if all points are on the negative side // If so, object is not visible for (int plane = 0; plane < 6; ++plane) { // Skip far plane if infinite view frustum if (plane == FRUSTUM_PLANE_FAR && m_farDist == 0) continue; Plane::Side side = m_frustumPlanes[plane].getSide(centre, halfSize); if (side == Plane::NEGATIVE_SIDE) { // ALL corners on negative side therefore out of view if (culledBy) *culledBy = (FrustumPlane)plane; return false; } } return true; }
bool SelectionQuery::Intersection(const AxisAlignedBox& box, const QVector3D& ray_start, const QVector3D& ray_dir, double* result) { const QVector3D& bmin = box.Min(); const QVector3D& bmax = box.Max(); const double inv_x = 1 / ray_dir.x(); const double inv_y = 1 / ray_dir.y(); const double inv_z = 1 / ray_dir.z(); const double tx1 = (bmin.x() - ray_start.x()) * inv_x; const double tx2 = (bmax.x() - ray_start.x()) * inv_x; double tmin = std::min(tx1, tx2); double tmax = std::max(tx1, tx2); const double ty1 = (bmin.y() - ray_start.y()) * inv_y; const double ty2 = (bmax.y() - ray_start.y()) * inv_y; tmin = std::max(tmin, std::min(ty1, ty2)); tmax = std::min(tmax, std::max(ty1, ty2)); const double tz1 = (bmin.z() - ray_start.z()) * inv_z; const double tz2 = (bmax.z() - ray_start.z()) * inv_z; tmin = std::max(tmin, std::min(tz1, tz2)); tmax = std::min(tmax, std::max(tz1, tz2)); if (tmax >= tmin && tmax > 0) { *result = std::max(0.0, std::min(tmin, tmax)); return true; } return false; }
btoCylinder::btoCylinder(btoWorld *world, BulletOgreEngine *btoEngine, btScalar radius, btScalar height, const btTransform &transform, const btScalar density) : btCylinder(world, radius, height, transform, density) { this->btoEngine = btoEngine; // New entity btoCylinder::mNumEntitiesInstanced++; // Create Ogre Entity entity = btoEngine->getOgreEngine()->getOgreSceneManager()->createEntity( "CylinderEntity_" + StringConverter::toString(btoCylinder::mNumEntitiesInstanced), "Barrel.mesh"); // Material entity->setMaterialName("GeneCraft/RockWall"); entity->setCastShadows(true); // Attach node = btoEngine->getOgreEngine()->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode(); // Scale AxisAlignedBox boundingB = entity->getBoundingBox(); // we need the bounding box of the box to be able to set the size of the Bullet-box Vector3 sizeBB = boundingB.getSize(); sizeBB /= 2.0f; // only the half needed sizeBB *= 0.95f; // Bullet margin is a bit bigger so we need a smaller size (Bullet 2.76 Physics SDK Manual page 18) Vector3 ogreSize(radius*2,height,radius*2); Vector3 scale = ogreSize / boundingB.getSize(); node->scale(scale); // the cube is too big for us sizeBB *= scale; // don't forget to scale down the Bullet-box too }
//---------------------------------------------------------------------------- // AxisAlignedBox AxisAlignedBox StringConv::axisAlignedBoxFromString(const String& _str, size_t _start, size_t& _readcount) { AxisAlignedBox aab; size_t rdc; _readcount = 0; aab.setMinimum( fromString<Vector3>(_str, _start, rdc) ); if(!rdc) { _readcount = 0; return AxisAlignedBox::BOX_NULL; } _readcount += rdc; _start += rdc; aab.setMaximum( fromString<Vector3>(_str, _start, rdc) ); if(!rdc) { _readcount = 0; return AxisAlignedBox::BOX_NULL; } _readcount += rdc; return aab; }
void App::TerCircleInit() { moTerC = mSceneMgr->createManualObject(); moTerC->setDynamic(true); moTerC->setCastShadows(false); moTerC->estimateVertexCount(divs+2); moTerC->estimateIndexCount(divs+2); moTerC->begin("circle_deform", RenderOperation::OT_TRIANGLE_STRIP); for (int d = 0; d < divs+2; ++d) { Real a = d/2 * aAdd; fTcos[d] = cosf(a); fTsin[d] = sinf(a); Real r = (d % 2 == 0) ? 1.f : 0.9f; Real x = r * fTcos[d], z = r * fTsin[d]; moTerC->position(x,0,z); //moTerC->normal(0,1,0); moTerC->textureCoord(d/2*dTc, d%2); } moTerC->end(); AxisAlignedBox aab; aab.setInfinite(); moTerC->setBoundingBox(aab); // always visible moTerC->setRenderQueueGroup(RQG_Hud2); moTerC->setVisibilityFlags(RV_Hud); ndTerC = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0,0,0)); ndTerC->attachObject(moTerC); ndTerC->setVisible(false); }
OctreeCamera::Visibility OctreeCamera::getVisibility( const AxisAlignedBox &bound ) { // Null boxes always invisible if ( bound.isNull() ) return NONE; // Get centre of the box Vector3 centre = bound.getCenter(); // Get the half-size of the box Vector3 halfSize = bound.getHalfSize(); bool all_inside = true; for ( int plane = 0; plane < 6; ++plane ) { // Skip far plane if infinite view frustum if (plane == FRUSTUM_PLANE_FAR && mFarDist == 0) continue; // This updates frustum planes and deals with cull frustum Plane::Side side = getFrustumPlane(plane).getSide(centre, halfSize); if(side == Plane::NEGATIVE_SIDE) return NONE; // We can't return now as the box could be later on the negative side of a plane. if(side == Plane::BOTH_SIDE) all_inside = false; } if ( all_inside ) return FULL; else return PARTIAL; }
void OctreeSceneManager::resize( const AxisAlignedBox &box ) { list< SceneNode * >::type nodes; list< SceneNode * >::type ::iterator it; _findNodes( mOctree->mBox, nodes, 0, true, mOctree ); OGRE_DELETE mOctree; mOctree = OGRE_NEW Octree( 0 ); mOctree->mBox = box; const Vector3 &min = box.getMinimum(); const Vector3 &max = box.getMaximum(); mOctree->mHalfSize = ( max - min ) * 0.5f; it = nodes.begin(); while ( it != nodes.end() ) { OctreeNode * on = static_cast < OctreeNode * > ( *it ); on -> setOctant( 0 ); _updateOctreeNode( on ); ++it; } }
//! Gets all triangles which lie within a specific bounding box. void COctreeTriangleSelector::getTriangles(triangle3df* triangles, SINT32 arraySize, SINT32& outTriangleCount, const AxisAlignedBox& box, const Matrix4* transform) const { Matrix4 mat(Matrix4::ZERO); AxisAlignedBox invbox = box; if (SceneNode) { //SceneNode->getAbsoluteTransformation().getInverse(mat); mat = SceneNode->getAbsoluteTransformation(); mat.inverse(); //mat.transformBoxEx(invbox); invbox.transform(mat); } if (transform) mat = *transform; else mat = Matrix4::IDENTITY; if (SceneNode) //mat *= SceneNode->getAbsoluteTransformation(); mat = SceneNode->getAbsoluteTransformation() * mat; SINT32 trianglesWritten = 0; if (Root) getTrianglesFromOctree(Root, trianglesWritten, arraySize, invbox, &mat, triangles); outTriangleCount = trianglesWritten; }
AxisAlignedBox NavigationInputGeometry::getBoundingBox() { AxisAlignedBox bbox; bbox.setMinimum( Math::floatArrayToOgreVec3( mBBoxMin ) ); bbox.setMaximum( Math::floatArrayToOgreVec3( mBBoxMax ) ); return bbox; }
bool SystemWindowManager::CheckWindowCollision(bool canChangeSelection, Vector2 *outRelativePosition) { Vector3 origin = m_Controller->mRotationNode->convertLocalToWorldPosition(Vector3::ZERO); Vector3 cursor = m_MosueCursor->GetPosition(); //convert to a vector 3 going into the screen Vector3 other = cursor - origin; Vector3 result; Entity* entity = NULL; float distToColl = -1.0f; m_MosueCursor->SetVisible(false); m_CollisionTools.raycastFromPoint(origin, other, result, entity, distToColl); m_MosueCursor->SetVisible(true); if(entity) { AxisAlignedBox bounds = entity->getBoundingBox(); SceneNode *node = entity->getParentSceneNode(); Vector3 nodePosition = node->getPosition(); Vector3 nodeWorldPosition = node->convertLocalToWorldPosition(Vector3::ZERO); Vector3 position = node->convertWorldToLocalPosition(result); double relx, rely = 0; Vector3 topLeft = bounds.getCorner(AxisAlignedBox::FAR_LEFT_TOP); Vector3 bottomRight = bounds.getCorner(AxisAlignedBox::FAR_RIGHT_BOTTOM); relx = (position.x - topLeft.x) / (bottomRight.x - topLeft.x); rely = (position.y - topLeft.y) / (bottomRight.y - topLeft.y); if(m_SelectedWindow->GetMaterialName() == entity->getName()) { //todo figure out the mouse coordiantes m_SelectedWindow->CheckActiveWindow(relx, rely); *outRelativePosition = Vector2(relx, rely); return true; } else if(canChangeSelection) { for (std::vector<SystemWindow*>::iterator it = m_Windows.begin(); it != m_Windows.end(); ++it) { if((*it)->GetMaterialName() == entity->getName()) { //todo deactivate the old window here m_SelectedWindow = (*it); m_SelectedWindow->CheckActiveWindow(relx, rely); *outRelativePosition = Vector2(relx, rely); return true; } } } return false; } else if(canChangeSelection) { RemoveHighlightedThumbnail(); } return false; }
ParaEngine::AxisAlignedBox AxisAlignedBox::intersection(const AxisAlignedBox& b2) const { if (this->isNull() || b2.isNull()) { return AxisAlignedBox(); } else if (this->isInfinite()) { return b2; } else if (b2.isInfinite()) { return *this; } Vector3 intMin = mMinimum; Vector3 intMax = mMaximum; intMin.makeCeil(b2.getMinimum()); intMax.makeFloor(b2.getMaximum()); // Check intersection isn't null if (intMin.x < intMax.x && intMin.y < intMax.y && intMin.z < intMax.z) { return AxisAlignedBox(intMin, intMax); } return AxisAlignedBox(); }
/** It's assumed the the given box has already been proven to fit into * a child. Since it's a loose octree, only the centers need to be * compared to find the appropriate node. */ void Octree::_getChildIndexes( const AxisAlignedBox &box, int *x, int *y, int *z ) const { Vector3 max = mBox.getMaximum(); Vector3 min = box.getMinimum(); Vector3 center = mBox.getMaximum().midPoint( mBox.getMinimum() ); Vector3 ncenter = box.getMaximum().midPoint( box.getMinimum() ); if ( ncenter.x > center.x ) * x = 1; else *x = 0; if ( ncenter.y > center.y ) * y = 1; else *y = 0; if ( ncenter.z > center.z ) * z = 1; else *z = 0; }
/** Returns true is the box will fit in a child. */ bool Octree::_isTwiceSize( const AxisAlignedBox &box ) const { return ( ( box.getMaximum().x - box.getMinimum().x ) <= ( mBox.getMaximum().x - mBox.getMinimum().x ) / 2 ) && ( ( box.getMaximum().y - box.getMinimum().y ) <= ( mBox.getMaximum().y - mBox.getMinimum().y ) / 2 ) && ( ( box.getMaximum().z - box.getMinimum().z ) <= ( mBox.getMaximum().z - mBox.getMinimum().z ) / 2 ) ; }
/** Since we are loose, only check the center. */ bool OctreeNode::_isIn( AxisAlignedBox &box ) { // Always fail if not in the scene graph or box is null if (!mIsInSceneGraph || box.isNull()) return false; // Always succeed if AABB is infinite if (box.isInfinite()) return true; Vector3 center = mWorldAABB.getMaximum().midPoint( mWorldAABB.getMinimum() ); Vector3 bmin = box.getMinimum(); Vector3 bmax = box.getMaximum(); bool centre = ( bmax > center && bmin < center ); if (!centre) return false; // Even if covering the centre line, need to make sure this BB is not large // enough to require being moved up into parent. When added, bboxes would // end up in parent due to cascade but when updating need to deal with // bbox growing too large for this child Vector3 octreeSize = bmax - bmin; Vector3 nodeSize = mWorldAABB.getMaximum() - mWorldAABB.getMinimum(); return nodeSize < octreeSize; }
//------------------------------------------------------------------------------ void SegmentedDynamicLightManager::LightData::setBounds(const AxisAlignedBox& i_Bounds) { mMinX = i_Bounds.getMinimum().x; mMaxX = i_Bounds.getMaximum().x; mMinZ = i_Bounds.getMinimum().z; mMaxZ = i_Bounds.getMaximum().z; }
//------------------------------------------------------------------------- TerrainTile * OverhangTerrainPage::getTerrainTile( const Vector3 & pt ) { /* Since we don't know if the terrain is square, or has holes, we use a line trace to find the containing tile... */ TerrainTile * tile = tiles[ 0 ][ 0 ]; while ( tile != 0 ) { AxisAlignedBox b = tile -> getBoundingBox(); if ( pt.x < b.getMinimum().x ) tile = tile -> _getNeighbor( TerrainTile::WEST ); else if ( pt.x > b.getMaximum().x ) tile = tile -> _getNeighbor( TerrainTile::EAST ); else if ( pt.z < b.getMinimum().z ) tile = tile -> _getNeighbor( TerrainTile::NORTH ); else if ( pt.z > b.getMaximum().z ) tile = tile -> _getNeighbor( TerrainTile::SOUTH ); else return tile; } return 0; }
void GeometryApp::loadGeomSource( const geom::Source &source, const geom::Source &sourceWire ) { // The purpose of the TriMesh is to capture a bounding box; without that need we could just instantiate the Batch directly using primitive TriMesh::Format fmt = TriMesh::Format().positions().normals().texCoords().tangents(); if( mShowColors && source.getAvailableAttribs().count( geom::COLOR ) > 0 ) fmt.colors(); TriMesh mesh( source, fmt ); AxisAlignedBox bbox = mesh.calcBoundingBox(); mCameraLerpTarget = mesh.calcBoundingBox().getCenter(); mCameraViewDirection = mCamera.getViewDirection(); mRecenterCamera = true; if( mPhongShader ) mPrimitive = gl::Batch::create( mesh, mPhongShader ); if( mWireShader ) mPrimitiveWire = gl::Batch::create( sourceWire, mWireShader ); if( mWireframeShader ) mPrimitiveWireframe = gl::Batch::create( mesh, mWireframeShader ); vec3 size = bbox.getMax() - bbox.getMin(); float scale = std::max( std::max( size.x, size.y ), size.z ) / 25.0f; mPrimitiveNormalLines = gl::Batch::create( mesh >> geom::VertexNormalLines( scale ), gl::getStockShader( gl::ShaderDef().color() ) ); if( mesh.hasTangents() ) mPrimitiveTangentLines = gl::Batch::create( mesh >> geom::VertexNormalLines( scale, geom::TANGENT ), gl::getStockShader( gl::ShaderDef().color() ) ); else
void IntroScene::initScene() { mSceneMgr = mRoot->createSceneManager( ST_GENERIC , "intro" ); mCamera = mSceneMgr->createCamera("Cam1"); mVp = mWindow->addViewport(mCamera); mVp->setBackgroundColour(ColourValue(1.0f, 0.0f,0.0f)); mCamera->setAspectRatio(Real(mVp->getActualWidth())/mVp->getActualHeight()); mSceneMgr->setAmbientLight( ColourValue( 1, 1, 1 ) ); Ogre::MaterialManager *matMgr = Ogre::MaterialManager::getSingletonPtr(); Ogre::MaterialPtr mat = (Ogre::MaterialPtr )matMgr->create("intro2","General"); mat->getTechnique(0)->getPass(0)->createTextureUnitState("cybernetic.jpg"); mat->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); mat->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); mat->getTechnique(0)->getPass(0)->setLightingEnabled(false); Ogre::Rectangle2D *rect = new Ogre::Rectangle2D(true); rect->setCorners( -1.0 , 1.0 , 1.0 , -1.0 ); rect->setMaterial("intro2"); rect->setRenderQueueGroup(Ogre::RENDER_QUEUE_BACKGROUND); SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode("Background"); node->attachObject(rect); AxisAlignedBox aabInf; aabInf.setInfinite(); rect->setBoundingBox(aabInf); }
void Actor::setHighlighted(bool highlight) { if (highlight != mHighlighted) { //getControlledObject()->setHighlighted(highlight); mHighlighted = highlight; } if (mHighlighted && mDescription == NULL) { if (mSceneNode != NULL) { mDescription = new MovableText(mName + "_desc", mName); mDescription->showOnTop(true); mDescription->setAlignment(MovableText::ALIGN_CENTER); if (mActorControlledObject && mActorControlledObject->isMeshObject()) { MeshObject* mo = static_cast<MeshObject*>(mActorControlledObject); AxisAlignedBox aabb = mo->getDefaultSize(); mDescription->setPositionOffset(Vector3(0, aabb.getMaximum().y * 1.1, 0)); } mSceneNode->attachObject(mDescription); } } else if (mDescription) { mDescription->setVisible(highlight); } }
bool AxisAlignedBox::intersects(const AxisAlignedBox& b2) const { // Early-fail for nulls if (this->isNull() || b2.isNull()) return false; // Early-success for infinites if (this->isInfinite() || b2.isInfinite()) return true; // Use up to 6 separating planes if (mMaximum.x < b2.mMinimum.x) return false; if (mMaximum.y < b2.mMinimum.y) return false; if (mMaximum.z < b2.mMinimum.z) return false; if (mMinimum.x > b2.mMaximum.x) return false; if (mMinimum.y > b2.mMaximum.y) return false; if (mMinimum.z > b2.mMaximum.z) return false; // otherwise, must be intersecting return true; }
// util //--------------------------------------------------------------------------------------------------------------- ManualObject* App::Create2D(const String& mat, Real s, bool dyn) { ManualObject* m = mSceneMgr->createManualObject(); m->setDynamic(dyn); m->setUseIdentityProjection(true); m->setUseIdentityView(true); m->setCastShadows(false); m->estimateVertexCount(4); m->begin(mat, RenderOperation::OT_TRIANGLE_STRIP); m->position(-s,-s*asp, 0); m->textureCoord(0, 1); m->position( s,-s*asp, 0); m->textureCoord(1, 1); m->position(-s, s*asp, 0); m->textureCoord(0, 0); m->position( s, s*asp, 0); m->textureCoord(1, 0); m->end(); //TODO:replace OT_TRIANGLE_FAN with a more friendly version for D3D11 as it is not supported /* m->estimateVertexCount(6); m->begin(mat, RenderOperation::OT_TRIANGLE_LIST); m->position(-s,-s*asp, 0); m->textureCoord(0, 1); m->position( s,-s*asp, 0); m->textureCoord(1, 1); m->position( s, s*asp, 0); m->textureCoord(1, 0); m->position(-s, s*asp, 0); m->textureCoord(0, 0); m->position(-s,-s*asp, 0); m->textureCoord(0, 1); m->position( s, s*asp, 0); m->textureCoord(1, 0); m->end(); */ AxisAlignedBox aabInf; aabInf.setInfinite(); m->setBoundingBox(aabInf); // always visible m->setRenderQueueGroup(RQG_Hud2); return m; }
/** Checks how the box intersects with the sphere. */ Intersection intersect( const Sphere &one, const AxisAlignedBox &two ) { OctreeSceneManager::intersect_call++; // Null box? if (two.isNull()) return OUTSIDE; if (two.isInfinite()) return INTERSECT; float sradius = one.getRadius(); sradius *= sradius; Vector3 scenter = one.getCenter(); const Vector3& twoMin = two.getMinimum(); const Vector3& twoMax = two.getMaximum(); float s, d = 0; Vector3 mndistance = ( twoMin - scenter ); Vector3 mxdistance = ( twoMax - scenter ); if ( mndistance.squaredLength() < sradius && mxdistance.squaredLength() < sradius ) { return INSIDE; } //find the square of the distance //from the sphere to the box for ( int i = 0 ; i < 3 ; i++ ) { if ( scenter[ i ] < twoMin[ i ] ) { s = scenter[ i ] - twoMin[ i ]; d += s * s; } else if ( scenter[ i ] > twoMax[ i ] ) { s = scenter[ i ] - twoMax[ i ]; d += s * s; } } bool partial = ( d <= sradius ); if ( !partial ) { return OUTSIDE; } else { return INTERSECT; } }
String StringConv::axisAlignedBoxToString(const AxisAlignedBox& _val, size_t _precision) { String r; r += toString(_val.getMinimum(), _precision); r += " "; r += toString(_val.getMaximum(), _precision); return r; }
PagingLandScapeOctreeCamera::Visibility PagingLandScapeOctreeCamera::getVisibility( const AxisAlignedBox &bound ) const { // Null boxes always invisible if ( bound.isNull() ) return NONE; // Make any pending updates to the calculated frustum Camera::updateView(); // Get corners of the box const Vector3 * const pCorners = bound.getAllCorners(); // For each plane, see if all points are on the negative side // If so, object is not visible. // If one or more are, it's partial. // If all aren't, full static unsigned int corners[ 8 ] = {0, 4, 3, 5, 2, 6, 1, 7}; static unsigned int planes[ 6 ] = {FRUSTUM_PLANE_TOP, FRUSTUM_PLANE_BOTTOM, FRUSTUM_PLANE_LEFT, FRUSTUM_PLANE_RIGHT, FRUSTUM_PLANE_FAR, FRUSTUM_PLANE_NEAR }; bool all_inside = true; const bool infinite_far_clip = (mFarDist == 0); for ( int plane = 0; plane < 6; ++plane ) { const unsigned int currPlane = planes[ plane ]; // Skip far plane if infinite view frustum if (infinite_far_clip && currPlane == FRUSTUM_PLANE_FAR) continue; bool all_outside = true; const Plane &frustumPlane = mFrustumPlanes[ currPlane ]; for ( unsigned int corner = 0; corner < 8; ++corner ) { const Real distance = frustumPlane.getDistance( pCorners[ corners[ corner ] ] ); all_outside = all_outside && ( distance < 0 ); all_inside = all_inside && ( distance >= 0 ); if ( !all_outside && !all_inside ) break; } if ( all_outside ) return NONE; } if ( all_inside ) return FULL; else return PARTIAL; }
//----------------------------------------------------------------------- Plane::Side Plane::getSide (const AxisAlignedBox& box) const { if (box.isNull()) return NO_SIDE; if (box.isInfinite()) return BOTH_SIDE; return getSide(box.getCenter(), box.getHalfSize()); }
AxisAlignedBox* AreaLight::createBoundingBox() { AxisAlignedBox* result = new AxisAlignedBox(); result->includePoint(origin); result->includePoint(origin + uDirection); result->includePoint(origin + vDirection); result->includePoint(origin + uDirection + vDirection); return result; }
static double squaredDistanceToAABB(const QVector3D& point, const AxisAlignedBox& box) { const QVector3D center = (box.Max() + box.Min()) / 2; const QVector3D half_sz = (box.Max() - box.Min()) / 2; const QVector3D vec(max(0.0, fabs(center.x() - point.x()) - half_sz.x()), max(0.0, fabs(center.y() - point.y()) - half_sz.y()), max(0.0, fabs(center.z() - point.z()) - half_sz.z())); return vec.lengthSquared(); }