//----------------------------------------------------------------------------- void ZonePlugin::zoneUtility( void ) { const osScalar drawExtent = _zoneExtent.x * OS_SCALAR( 2.0 ) - 0.005f; if( 1 == _solid ) { // colors for checkerboard const Color gray(0.27f); Color zoneGray( getZoneColor() ); zoneGray.setR( zoneGray.r() * gray.r() ); zoneGray.setG( zoneGray.g() * gray.g() ); zoneGray.setB( zoneGray.b() * gray.b() ); // draw checkerboard grid drawXZCheckerboardGrid( drawExtent, 10, position(), zoneGray, gray); #if 0 AABBox kZoneAABBox; kZoneAABBox.initializeWithCenterAndExtent( position(), _zoneExtent ); kZoneAABBox.draw( getZoneColor() ); #endif } else { // alternate style drawXZLineGrid( drawExtent, 1, position(), _ZoneColor ); } const osScalar borderWidth = getBorderWidth(); if( borderWidth > 0 ) { drawXZLineGrid( drawExtent + borderWidth * OS_SCALAR( 2.0 ), 1, position(), _BorderColor ); } }
/** * @return True if the bounding box collides or is inside this frustum */ template<class T> bool Frustum<T>::collideWithAABBox(const AABBox<T> &bbox) const { for (auto &plane : planes) { const Vector3<T> &normal = plane.getNormal(); Point3<T> nVertex(bbox.getMax()); if(normal.X >= 0.0) { nVertex.X = bbox.getMin().X; } if(normal.Y >= 0.0) { nVertex.Y = bbox.getMin().Y; } if(normal.Z >= 0.0) { nVertex.Z = bbox.getMin().Z; } if (plane.distance(nVertex) > 0.0) { return false; } } return true; }
/** * Split the bounding box in several bounding boxes at limitSize. * If original box doesn't exceed limit size, the original box is returned. */ std::vector<AABBox<float>> SplitBoundingBox::split(const AABBox<float> &aabbox) const { std::vector<float> axisSplits[3]; for(unsigned int axis=0; axis<3; ++axis) { float size = aabbox.getHalfSize(axis) * 2.0f; axisSplits[axis].push_back(aabbox.getMin()[axis]); auto nbSplits = static_cast<int>(std::ceil(size/limitSize)); float maxValue = aabbox.getMax()[axis]; for(int split = 0; split < nbSplits; ++split) { float splitValue = std::min(aabbox.getMin()[axis] + limitSize*(split+1), maxValue); axisSplits[axis].push_back(splitValue); } } std::vector<AABBox<float>> splittedBoundingBox; for(unsigned int x=1; x<axisSplits[0].size(); ++x) { for(unsigned int y=1; y<axisSplits[1].size(); ++y) { for(unsigned int z=1; z<axisSplits[2].size(); ++z) { Point3<float> minPoint(axisSplits[0][x-1], axisSplits[1][y-1], axisSplits[2][z-1]); Point3<float> maxPoint(axisSplits[0][x], axisSplits[1][y], axisSplits[2][z]); splittedBoundingBox.emplace_back(AABBox<float>(minPoint, maxPoint)); } } } return splittedBoundingBox; }
void SunLightSource::UpdateSMCamera(Camera const & scene_camera) { float3 const dir = this->Direction(); float3 up_vec; if (abs(MathLib::dot(-dir, scene_camera.UpVec())) > 0.95f) { up_vec = scene_camera.RightVec(); } else { up_vec = scene_camera.UpVec(); } float4x4 light_view = MathLib::look_at_lh(-dir, float3(0, 0, 0), up_vec); AABBox const aabb = CalcFrustumExtents(scene_camera, scene_camera.NearPlane(), scene_camera.FarPlane(), light_view); float3 const & center = aabb.Center(); float3 view_pos = MathLib::transform_coord(float3(center.x(), center.y(), aabb.Min().z()), MathLib::inverse(light_view)); sm_camera_->ViewParams(view_pos, view_pos + dir, up_vec); float3 dimensions = aabb.Max() - aabb.Min(); sm_camera_->ProjOrthoParams(dimensions.x(), dimensions.y(), 0.0f, dimensions.z()); }
bool FrustumShadowData::areIdenticalAABBox(const AABBox<float> &shadowCasterReceiverBox1, const AABBox<float> &shadowCasterReceiverBox2) const { constexpr float SQUARE_EPSILON = 0.0001f * 0.0001f; return shadowCasterReceiverBox1.getMin().squareDistance(shadowCasterReceiverBox2.getMin())<SQUARE_EPSILON && shadowCasterReceiverBox1.getMax().squareDistance(shadowCasterReceiverBox2.getMax())<SQUARE_EPSILON; }
bool ZonePlugin::isVehicleInsideBorder( const AbstractVehicle& vehicle ) const { osVector3 checkZoneExtent = _zoneExtent; checkZoneExtent.x += _borderWidth; checkZoneExtent.z += _borderWidth; AABBox testBox; testBox.initializeWithCenterAndExtent( position(), checkZoneExtent ); return testBox.insideXZWithRadius(vehicle); }
Vector3<float> CollisionConvexHullShape::computeLocalInertia(float mass) const { AABBox<float> aabbox = toAABBox(PhysicsTransform()); float width = 2.0 * aabbox.getHalfSize(0); float height = 2.0 * aabbox.getHalfSize(1); float depth = 2.0 * aabbox.getHalfSize(2); float localInertia1 = (1.0/12.0) * mass * (height*height + depth*depth); float localInertia2 = (1.0/12.0) * mass * (width*width + depth*depth); float localInertia3 = (1.0/12.0) * mass * (width*width + height*height); return Vector3<float>(localInertia1, localInertia2, localInertia3); }
BoundOverlap OCTree::BoundVisible(size_t index, AABBox const & aabb) const { BOOST_ASSERT(index < octree_.size()); octree_node_t const & node = octree_[index]; if ((node.visible != BO_No) && MathLib::intersect_aabb_aabb(node.bb, aabb)) { if (BO_Yes == node.visible) { return BO_Yes; } else { BOOST_ASSERT(BO_Partial == node.visible); if (node.first_child_index != -1) { float3 const center = node.bb.Center(); int mark[6]; mark[0] = aabb.Min().x() >= center.x() ? 1 : 0; mark[1] = aabb.Min().y() >= center.y() ? 2 : 0; mark[2] = aabb.Min().z() >= center.z() ? 4 : 0; mark[3] = aabb.Max().x() >= center.x() ? 1 : 0; mark[4] = aabb.Max().y() >= center.y() ? 2 : 0; mark[5] = aabb.Max().z() >= center.z() ? 4 : 0; for (int j = 0; j < 8; ++ j) { if (j == ((j & 1) ? mark[3] : mark[0]) + ((j & 2) ? mark[4] : mark[1]) + ((j & 4) ? mark[5] : mark[2])) { BoundOverlap const bo = this->BoundVisible(node.first_child_index + j, aabb); if (bo != BO_No) { return bo; } } } return BO_No; } else { return BO_Partial; } } } else { return BO_No; } }
void AABBNode::updateAABBox(float fatMargin) { if (isLeaf()) { Point3<float> fatMargin3(fatMargin, fatMargin, fatMargin); AABBox<float> bodyBox = bodyNodeData->retrieveBodyAABBox(); aabbox = AABBox<float>(bodyBox.getMin()-fatMargin3, bodyBox.getMax()+fatMargin3); }else { aabbox = children[0]->getAABBox().merge(children[1]->getAABBox()); } }
void ShapeToAABBoxTest::boxConversion() { CollisionBoxShape collisionBox(Vector3<float>(1.0, 2.0, 1.0)); //box 1x2x1 PhysicsTransform transform(urchin::Point3<float>(0.0, 0.0, 0.0), //move 0 unit on X, Y and Z axis urchin::Quaternion<float>(urchin::Vector3<float>(0.0, 0.0, 1.0), 3.14159265358979/4)); //rotate 45° on Z axis AABBox<float> box = collisionBox.toAABBox(transform); AssertHelper::assertFloatEquals(box.getHalfSize(0), 2.12132034356); AssertHelper::assertFloatEquals(box.getHalfSize(1), 2.12132034356); AssertHelper::assertFloatEquals(box.getHalfSize(2), 1.0); AssertHelper::assertPoint3FloatEquals(box.getMin(), Point3<float>(-2.12132034356, -2.12132034356, -1.0)); AssertHelper::assertPoint3FloatEquals(box.getMax(), Point3<float>(2.12132034356, 2.12132034356, 1.0)); }
bool ShadowPolygon::inside (const Vector2& pos, const AABBox& bbox) const { Vector2 corners[4]; bbox.getCorners(pos, corners); for (int i=0; i<4; i++) if (!inside(corners[i])) return false; return true; }
void ShapeToAABBoxTest::convexHullConversion() { Point3<float> boxPointsTab[] = { Point3<float>(-1.0, -2.0, 1.0), Point3<float>(1.0, -2.0, 1.0), Point3<float>(1.0, 2.0, 1.0), Point3<float>(-1.0, 2.0, 1.0), Point3<float>(-1.0, -2.0, -1.0), Point3<float>(1.0, -2.0, -1.0), Point3<float>(1.0, 2.0, -1.0), Point3<float>(-1.0, 2.0, -1.0), }; std::vector<Point3<float>> boxPoints(boxPointsTab, boxPointsTab+sizeof(boxPointsTab)/sizeof(Point3<float>)); CollisionConvexHullShape collisionConvexHull(0.0, boxPoints); PhysicsTransform transform(urchin::Point3<float>(0.0, 0.0, 0.0), //move 0 unit on X, Y and Z axis urchin::Quaternion<float>(urchin::Vector3<float>(0.0, 0.0, 1.0), -3.14159265358979/4)); //rotate 45° on Z axis AABBox<float> box = collisionConvexHull.toAABBox(transform); AssertHelper::assertFloatEquals(box.getHalfSize(0), 2.12132034356); AssertHelper::assertFloatEquals(box.getHalfSize(1), 2.12132034356); AssertHelper::assertFloatEquals(box.getHalfSize(2), 1.0); AssertHelper::assertPoint3FloatEquals(box.getMin(), Point3<float>(-2.12132034356, -2.12132034356, -1.0)); AssertHelper::assertPoint3FloatEquals(box.getMax(), Point3<float>(2.12132034356, 2.12132034356, 1.0)); }
AABBox<float> CollisionCompoundShape::toAABBox(const PhysicsTransform &physicsTransform) const { Point3<float> rotatedTranslation = physicsTransform.getOrientation().rotatePoint(Point3<float>(localizedShapes[0]->translation)); Point3<float> finalPosition = physicsTransform.getPosition().translate(rotatedTranslation.toVector()); PhysicsTransform shapeWorldTransform(finalPosition, physicsTransform.getOrientation()); AABBox<float> globalCompoundBox = localizedShapes[0]->shape->toAABBox(shapeWorldTransform); for(unsigned int i=1; i<localizedShapes.size(); ++i) { rotatedTranslation = physicsTransform.getOrientation().rotatePoint(Point3<float>(localizedShapes[i]->translation)); finalPosition = physicsTransform.getPosition().translate(rotatedTranslation.toVector()); shapeWorldTransform.setPosition(finalPosition); AABBox<float> compoundBox = localizedShapes[i]->shape->toAABBox(shapeWorldTransform); globalCompoundBox = globalCompoundBox.merge(compoundBox); } return globalCompoundBox; }
void ModelPreviewCanvas::AddjustCameraPos() { _Assert(mCamera != NULL); _Assert(mModel != NULL); AABBox bound; mModel->CalcDynamicAABBox(IDENTITY_MATRIX, &bound); float width = bound.GetSize().x; float height = bound.GetSize().y; float length = bound.GetSize().z; float aspect = 0; float fov = 0; mCamera->GetCameraParams(NULL, NULL, &fov, &aspect); float distY = (height / 2.0f) / tan(fov / 2.0f); float distX = (height / 2.0f) / (aspect * tan(fov / 2.0f)); float dist = Max(distX, distY); mCamera->SetWorldPosition(bound.GetCenter()); mCamera->Translate(0, 0, -dist - length); mCamera->LookAt(bound.GetCenter()); HoverCameraController* hoverCameraController = New HoverCameraController(5.0f, 20.0f, -4*PI/9, 4*PI/9, 2.0f, 1000.0f, bound.GetCenter(), dist + length); mCamera->SetCameraController(hoverCameraController); }
void FrustumShadowData::updateShadowCasterReceiverBox(const AABBox<float> &shadowCasterReceiverBox, bool forceUpdateAllShadowMap) { if(areIdenticalAABBox(shadowCasterReceiverBox, this->shadowCasterReceiverBox) && !forceUpdateAllShadowMap) { this->shadowCasterReceiverBoxUpdated = false; }else { this->shadowCasterReceiverBox = shadowCasterReceiverBox; this->lightProjectionMatrix = shadowCasterReceiverBox.toProjectionMatrix(); this->shadowCasterReceiverBoxUpdated = true; } }
int Frustum::boxInFrustum(const AABBox &bbox) { int result = INSIDE; for(unsigned int i=0; i<PLANECOUNT; i++) { if(planes[i]->isBehind(bbox.positiveVertex(planes[i]->normal))) { return OUTSIDE; } } return result; }
/** * Updates frustum shadow data (models, shadow caster/receiver box, projection matrix) */ void ShadowManager::updateFrustumShadowData(const Light *const light, ShadowData *const shadowData) { if(light->hasParallelBeams()) { //sun light for(unsigned int i=0; i<splittedFrustum.size(); ++i) { AABBox<float> aabboxSceneIndependent = createSceneIndependentBox(splittedFrustum[i], light, shadowData->getLightViewMatrix()); OBBox<float> obboxSceneIndependentViewSpace = shadowData->getLightViewMatrix().inverse() * OBBox<float>(aabboxSceneIndependent); const std::set<Model *> models = modelOctreeManager->getOctreeablesIn(obboxSceneIndependentViewSpace); shadowData->getFrustumShadowData(i)->setModels(models); AABBox<float> aabboxSceneDependent = createSceneDependentBox(aabboxSceneIndependent, obboxSceneIndependentViewSpace, models, shadowData->getLightViewMatrix()); shadowData->getFrustumShadowData(i)->setShadowCasterReceiverBox(aabboxSceneDependent); shadowData->getFrustumShadowData(i)->setLightProjectionMatrix(aabboxSceneDependent.toProjectionMatrix()); } }else { throw std::runtime_error("Shadow not supported on omnidirectional light."); } }
void Mesh::addPrimitive(unsigned indexA, unsigned indexB, unsigned indexC, Material* material) { if (indexA == indexB || indexB == indexC) { return; } Triangle* newTri = new Triangle(&mVertices[indexA], &mVertices[indexB], &mVertices[indexC], material); const AABBox bounds = newTri->bounds(); unsigned flatCount = 0; for (unsigned i = 0; i < 3; ++i) { if (bounds.ll()[i] == bounds.ur()[i]) ++flatCount; } if (flatCount > 1) { delete newTri; return; } mPrimitives.emplace_back(newTri); }
void OCTree::DivideNode(size_t index, uint32_t curr_depth) { if (octree_[index].obj_ptrs.size() > 1) { size_t const this_size = octree_.size(); AABBox const parent_bb = octree_[index].bb; float3 const parent_center = parent_bb.Center(); octree_[index].first_child_index = static_cast<int>(this_size); octree_[index].visible = BO_No; octree_.resize(this_size + 8); for (SceneObjsType::const_reference so : octree_[index].obj_ptrs) { AABBox const & aabb = *so->PosBoundWS(); int mark[6]; mark[0] = aabb.Min().x() >= parent_center.x() ? 1 : 0; mark[1] = aabb.Min().y() >= parent_center.y() ? 2 : 0; mark[2] = aabb.Min().z() >= parent_center.z() ? 4 : 0; mark[3] = aabb.Max().x() >= parent_center.x() ? 1 : 0; mark[4] = aabb.Max().y() >= parent_center.y() ? 2 : 0; mark[5] = aabb.Max().z() >= parent_center.z() ? 4 : 0; for (int j = 0; j < 8; ++ j) { if (j == ((j & 1) ? mark[3] : mark[0]) + ((j & 2) ? mark[4] : mark[1]) + ((j & 4) ? mark[5] : mark[2])) { octree_[this_size + j].obj_ptrs.push_back(so); } } } for (size_t j = 0; j < 8; ++ j) { octree_node_t& new_node = octree_[this_size + j]; new_node.first_child_index = -1; new_node.bb = AABBox(float3((j & 1) ? parent_center.x() : parent_bb.Min().x(), (j & 2) ? parent_center.y() : parent_bb.Min().y(), (j & 4) ? parent_center.z() : parent_bb.Min().z()), float3((j & 1) ? parent_bb.Max().x() : parent_center.x(), (j & 2) ? parent_bb.Max().y() : parent_center.y(), (j & 4) ? parent_bb.Max().z() : parent_center.z())); if (curr_depth < max_tree_depth_) { this->DivideNode(this_size + j, curr_depth + 1); } } SceneObjsType empty; octree_[index].obj_ptrs.swap(empty); } }
bool ModelComponent::Cull(const tt::GameContext& context) { tt::Vector3 vertices[8]; tt::Matrix4x4 wvpMat = m_pTransform->GetWorldMatrix() * context.pGame->GetActiveScene()->GetActiveCamera()->GetView() * context.pGame->GetActiveScene()->GetActiveCamera()->GetProjection(); AABBox aabBox = m_pModel->GetAABB(); aabBox.GetVertices(vertices); //If one point is inside the view frustum, the bounding volume is visible for(unsigned int i=0; i<8; ++i){ vertices[i] = vertices[i].TransformPoint(wvpMat); if( vertices[i].x >= -1 && vertices[i].x <= 1 && vertices[i].y >= -1 && vertices[i].y <= 1 && vertices[i].z >= 0 && vertices[i].z <= 1 ) return false; } //Additional checks to make sure we don't cull edge cases tt::Matrix4x4 invWvpMat = wvpMat.Inverse(); tt::Vector3 origin[] = {tt::Vector3(-1, -1, 0), tt::Vector3(-1, 1, 0), tt::Vector3( 1, -1, 0), tt::Vector3( 1, 1, 0), }; tt::Vector3 destination[] = {tt::Vector3(-1, -1, 1), tt::Vector3(-1, 1, 1), tt::Vector3( 1, -1, 1), tt::Vector3( 1, 1, 1), }; tt::Vector3 direction = tt::Vector3(0,0,1).TransformVector(invWvpMat); if(aabBox.Intersect(Ray(origin[0].TransformPoint(invWvpMat), destination[0].TransformPoint(invWvpMat)), 0, 1) ) return false; if(aabBox.Intersect(Ray(origin[1].TransformPoint(invWvpMat), destination[1].TransformPoint(invWvpMat)), 0, 1) ) return false; if(aabBox.Intersect(Ray(origin[2].TransformPoint(invWvpMat), destination[2].TransformPoint(invWvpMat)), 0, 1) ) return false; if(aabBox.Intersect(Ray(origin[3].TransformPoint(invWvpMat), destination[3].TransformPoint(invWvpMat)), 0, 1) ) return false; return true; }
void SDSMCascadedShadowLayer::UpdateCascades(Camera const & camera, float4x4 const & light_view_proj, float3 const & light_space_border) { RenderFactory& rf = Context::Instance().RenderFactoryInstance(); RenderEngine& re = rf.RenderEngineInstance(); uint32_t const num_cascades = static_cast<uint32_t>(intervals_.size()); uint32_t const copy_index = frame_index_ & 1; uint32_t const read_back_index = (0 == frame_index_) ? copy_index : !copy_index; if (cs_support_) { re.BindFrameBuffer(FrameBufferPtr()); float max_blur_light_space = 8.0f / 1024; float3 max_cascade_scale(max_blur_light_space / light_space_border.x(), max_blur_light_space / light_space_border.y(), std::numeric_limits<float>::max()); int const TILE_DIM = 128; int dispatch_x = (depth_tex_->Width(0) + TILE_DIM - 1) / TILE_DIM; int dispatch_y = (depth_tex_->Height(0) + TILE_DIM - 1) / TILE_DIM; *interval_buff_param_ = interval_buff_; *interval_buff_uint_param_ = interval_buff_; *interval_buff_read_param_ = interval_buff_; *cascade_min_buff_uint_param_ = cascade_min_buff_; *cascade_max_buff_uint_param_ = cascade_max_buff_; *cascade_min_buff_read_param_ = cascade_min_buff_; *cascade_max_buff_read_param_ = cascade_max_buff_; *scale_buff_param_ = scale_buff_; *bias_buff_param_ = bias_buff_; *depth_tex_param_ = depth_tex_; *num_cascades_param_ = static_cast<int32_t>(num_cascades); *inv_depth_width_height_param_ = float2(1.0f / depth_tex_->Width(0), 1.0f / depth_tex_->Height(0)); *near_far_param_ = float2(camera.NearPlane(), camera.FarPlane()); float4x4 const & inv_proj = camera.InverseProjMatrix(); float3 upper_left = MathLib::transform_coord(float3(-1, +1, 1), inv_proj); float3 upper_right = MathLib::transform_coord(float3(+1, +1, 1), inv_proj); float3 lower_left = MathLib::transform_coord(float3(-1, -1, 1), inv_proj); *upper_left_param_ = upper_left; *xy_dir_param_ = float2(upper_right.x() - upper_left.x(), lower_left.y() - upper_left.y()); *view_to_light_view_proj_param_ = camera.InverseViewMatrix() * light_view_proj; *light_space_border_param_ = light_space_border; *max_cascade_scale_param_ = max_cascade_scale; re.Dispatch(*clear_z_bounds_tech_, 1, 1, 1); re.Dispatch(*reduce_z_bounds_from_depth_tech_, dispatch_x, dispatch_y, 1); re.Dispatch(*compute_log_cascades_from_z_bounds_tech_, 1, 1, 1); re.Dispatch(*clear_cascade_bounds_tech_, 1, 1, 1); re.Dispatch(*reduce_bounds_from_depth_tech_, dispatch_x, dispatch_y, 1); re.Dispatch(*compute_custom_cascades_tech_, 1, 1, 1); interval_buff_->CopyToBuffer(*interval_cpu_buffs_[copy_index]); scale_buff_->CopyToBuffer(*scale_cpu_buffs_[copy_index]); bias_buff_->CopyToBuffer(*bias_cpu_buffs_[copy_index]); GraphicsBuffer::Mapper interval_mapper(*interval_cpu_buffs_[read_back_index], BA_Read_Only); GraphicsBuffer::Mapper scale_mapper(*scale_cpu_buffs_[read_back_index], BA_Read_Only); GraphicsBuffer::Mapper bias_mapper(*bias_cpu_buffs_[read_back_index], BA_Read_Only); float2* interval_ptr = interval_mapper.Pointer<float2>(); float3* scale_ptr = scale_mapper.Pointer<float3>(); float3* bias_ptr = bias_mapper.Pointer<float3>(); for (size_t i = 0; i < intervals_.size(); ++ i) { float3 const & scale = scale_ptr[i]; float3 const & bias = bias_ptr[i]; intervals_[i] = interval_ptr[i]; scales_[i] = scale; biases_[i] = bias; } } else { float2 const near_far(camera.NearPlane(), camera.FarPlane()); reduce_z_bounds_from_depth_pp_->SetParam(1, near_far); reduce_z_bounds_from_depth_pp_->Apply(); for (uint32_t i = 1; i < depth_deriative_tex_->NumMipMaps(); ++ i) { int width = depth_deriative_tex_->Width(i - 1); int height = depth_deriative_tex_->Height(i - 1); float delta_x = 1.0f / width; float delta_y = 1.0f / height; float4 delta_offset(delta_x, delta_y, -delta_x / 2, -delta_y / 2); reduce_z_bounds_from_depth_mip_map_pp_->SetParam(0, delta_offset); reduce_z_bounds_from_depth_mip_map_pp_->OutputPin(0, depth_deriative_small_tex_, i - 1); reduce_z_bounds_from_depth_mip_map_pp_->Apply(); int sw = depth_deriative_tex_->Width(i); int sh = depth_deriative_tex_->Height(i); depth_deriative_small_tex_->CopyToSubTexture2D(*depth_deriative_tex_, 0, i, 0, 0, sw, sh, 0, i - 1, 0, 0, sw, sh); } compute_log_cascades_from_z_bounds_pp_->SetParam(1, static_cast<int32_t>(num_cascades)); compute_log_cascades_from_z_bounds_pp_->SetParam(2, near_far); compute_log_cascades_from_z_bounds_pp_->Apply(); interval_tex_->CopyToSubTexture2D(*interval_cpu_texs_[copy_index], 0, 0, 0, 0, num_cascades, 1, 0, 0, 0, 0, num_cascades, 1); Texture::Mapper interval_mapper(*interval_cpu_texs_[read_back_index], 0, 0, TMA_Read_Only, 0, 0, num_cascades, 1); Vector_T<half, 2>* interval_ptr = interval_mapper.Pointer<Vector_T<half, 2> >(); for (size_t i = 0; i < intervals_.size(); ++ i) { float2 const interval(static_cast<float>(interval_ptr[i].x()), static_cast<float>(interval_ptr[i].y())); AABBox aabb = CalcFrustumExtents(camera, interval.x(), interval.y(), light_view_proj); aabb &= AABBox(float3(-1, -1, -1), float3(+1, +1, +1)); aabb.Min() -= light_space_border; aabb.Max() += light_space_border; aabb.Min().x() = +aabb.Min().x() * 0.5f + 0.5f; aabb.Min().y() = -aabb.Min().y() * 0.5f + 0.5f; aabb.Max().x() = +aabb.Max().x() * 0.5f + 0.5f; aabb.Max().y() = -aabb.Max().y() * 0.5f + 0.5f; std::swap(aabb.Min().y(), aabb.Max().y()); float3 const scale = float3(1.0f, 1.0f, 1.0f) / (aabb.Max() - aabb.Min()); float3 const bias = -aabb.Min() * scale; intervals_[i] = interval; scales_[i] = scale; biases_[i] = bias; } } this->UpdateCropMats(); ++ frame_index_; }
void PSSMCascadedShadowLayer::UpdateCascades(Camera const & camera, float4x4 const & light_view_proj, float3 const & light_space_border) { float const range = camera.FarPlane() - camera.NearPlane(); float const ratio = camera.FarPlane() / camera.NearPlane(); std::vector<float> distances(intervals_.size() + 1); for (size_t i = 0; i < intervals_.size(); ++ i) { float p = i / static_cast<float>(intervals_.size()); float log = camera.NearPlane() * std::pow(ratio, p); float uniform = camera.NearPlane() + range * p; distances[i] = lambda_ * (log - uniform) + uniform; } distances[intervals_.size()] = camera.FarPlane(); for (size_t i = 0; i < intervals_.size(); ++ i) { AABBox aabb = CalcFrustumExtents(camera, distances[i], distances[i + 1], light_view_proj); aabb &= AABBox(float3(-1, -1, -1), float3(+1, +1, +1)); aabb.Min() -= light_space_border; aabb.Max() += light_space_border; aabb.Min().x() = +aabb.Min().x() * 0.5f + 0.5f; aabb.Min().y() = -aabb.Min().y() * 0.5f + 0.5f; aabb.Max().x() = +aabb.Max().x() * 0.5f + 0.5f; aabb.Max().y() = -aabb.Max().y() * 0.5f + 0.5f; std::swap(aabb.Min().y(), aabb.Max().y()); float3 const scale = float3(1.0f, 1.0f, 1.0f) / (aabb.Max() - aabb.Min()); float3 const bias = -aabb.Min() * scale; intervals_[i] = float2(distances[i], distances[i + 1]); scales_[i] = scale; biases_[i] = bias; } this->UpdateCropMats(); }
void CollisionConvexHullShape::initializeDistances() { AABBox<float> aabbox = toAABBox(PhysicsTransform()); maxDistanceToCenter = aabbox.getMaxHalfSize(); minDistanceToCenter = aabbox.getMinHalfSize(); }
void COpenGLGrassRenderer::update(float fDeltaTimeInSecond, const Vector4D& camPos, const Frustum& viewFrustum, CSGPGrass* pGrass) { m_vCameraPos = camPos; m_GrassClusterInstanceArray.clearQuick(); if( !pGrass ) return; SGPVertex_GRASS_Cluster tempData; CSGPTerrainChunk** pChunkEnd = pGrass->m_TerrainGrassChunks.end(); for( CSGPTerrainChunk** pChunkStart = pGrass->m_TerrainGrassChunks.begin(); pChunkStart < pChunkEnd; pChunkStart++ ) { if( !m_pRenderDevice->GetWorldSystemManager()->isTerrainChunkVisible( *pChunkStart ) ) continue; for(uint32 i=0; i<(*pChunkStart)->GetGrassClusterDataCount(); i++ ) { // None Flag, skip this Cluster uint32 nGrassSetFlag = (*pChunkStart)->GetGrassClusterData()[i].nData; if( nGrassSetFlag == 0 ) continue; tempData.vPosition[0] = (*pChunkStart)->GetGrassClusterData()[i].fPositionX; tempData.vPosition[1] = (*pChunkStart)->GetGrassClusterData()[i].fPositionY; tempData.vPosition[2] = (*pChunkStart)->GetGrassClusterData()[i].fPositionZ; tempData.vPosition[3] = float( (nGrassSetFlag & 0x00FF0000) >> 16 ); // GrassCluster is not inside the camera Frustum, skip this Cluster AABBox GrassClusterAABB; GrassClusterAABB += Vector3D(tempData.vPosition[0] - m_vDefaultGrassSize.x, tempData.vPosition[1], tempData.vPosition[2] - m_vDefaultGrassSize.x); GrassClusterAABB += Vector3D(tempData.vPosition[0] + m_vDefaultGrassSize.x, tempData.vPosition[1] + m_vDefaultGrassSize.y, tempData.vPosition[2] + m_vDefaultGrassSize.x); if( !GrassClusterAABB.Intersects(viewFrustum) ) continue; // GrassCluster is too far from the Grass Far Fading distance, skip this Cluster float fGrassDis = (m_vCameraPos - Vector4D(tempData.vPosition[0], tempData.vPosition[1], tempData.vPosition[2])).GetLength(); if( fGrassDis > CSGPWorldConfig::getInstance()->m_fGrassFarFadingEnd ) continue; // Too many grass Cluster if( m_GrassClusterInstanceArray.size() + 1 > INIT_GRASSCLUSTERINSTANCE_NUM ) continue; tempData.vPackedNormal[0] = (uint8)(((*pChunkStart)->GetGrassClusterData()[i].nPackedNormal & 0xFF000000) >> 24); tempData.vPackedNormal[1] = (uint8)(((*pChunkStart)->GetGrassClusterData()[i].nPackedNormal & 0x00FF0000) >> 16); tempData.vPackedNormal[2] = (uint8)(((*pChunkStart)->GetGrassClusterData()[i].nPackedNormal & 0x0000FF00) >> 8); tempData.vPackedNormal[3] = (uint8)((nGrassSetFlag & 0xFF000000) >> 24); tempData.vColor[0] = tempData.vColor[1] = tempData.vColor[2] = 1.0f; tempData.vColor[3] = 1.0f - jlimit(0.0f, 1.0f, (fGrassDis - CSGPWorldConfig::getInstance()->m_fGrassFarFadingStart) / (CSGPWorldConfig::getInstance()->m_fGrassFarFadingEnd - CSGPWorldConfig::getInstance()->m_fGrassFarFadingStart)); tempData.vWindParams[0] = ((nGrassSetFlag & 0x0000FF00) >> 8) / 255.0f; tempData.vWindParams[1] = 0.0f; tempData.vWindParams[2] = (nGrassSetFlag & 0x000000FF) / 255.0f; tempData.vWindParams[3] = 0.0f; m_GrassClusterInstanceArray.add( tempData ); } } // update grass rendering params m_vTimeParams.x += fDeltaTimeInSecond; m_vTimeParams.y = pGrass->m_fGrassPeriod; m_vLightMapTextureDimision.Set( 1.0f / m_pRenderDevice->GetWorldSystemManager()->getTerrain()->GetTerrainWidth(), 1.0f / m_pRenderDevice->GetWorldSystemManager()->getTerrain()->GetTerrainWidth() ); m_vWindDirForce = pGrass->m_vWindDirectionAndStrength; }
void ShadowMapRenderer::setupVirtualLightCamera(Camera* camera, DirectionalLightNode* lightNode, int cascadeIndex) { const float BOUND_EXPAND_FACTOR = 0.8f; _Assert(camera != NULL); _Assert(cascadeIndex >= 0 && cascadeIndex < CASCADE_COUNTS); DirectionalLight* dirLight = lightNode->GetDirLight(); Vector3 lightDir = dirLight->GetDirection(); lightDir.Normalize(); Vector3 frustumPos[5]; { float farZ = 0; float aspect = 0; float fov = 0; camera->GetCameraParams(NULL, &farZ, &fov, &aspect); farZ *= calcCascadeDist(cascadeIndex); float fy = farZ * tanf(fov / 2.0f); float fx = aspect * fy; frustumPos[0] = Vector3::Zero; frustumPos[1] = Vector3(-fx, fy, farZ); frustumPos[2] = Vector3( fx, fy, farZ); frustumPos[3] = Vector3(-fx, -fy, farZ); frustumPos[4] = Vector3( fx, -fy, farZ); } D3DXMATRIX matCameraViewInv; D3DXMatrixInverse(&matCameraViewInv, 0, &camera->ViewMatrix()); D3DXMATRIX matLightView; { Vector3 lightPos = lightNode->GetWorldPosition(); D3DXMATRIX matRotTranspose, matTransInverse; D3DXMatrixTranspose(&matRotTranspose, &(lightNode->GetWorldOrient().Matrix())); D3DXMatrixTranslation(&matTransInverse, -lightPos.x, -lightPos.y, -lightPos.z); matLightView = matTransInverse * matRotTranspose; } AABBox lightSpaceBound; for(int i = 0; i < 5; ++i) { Vector3 posW = PosVecTransform(frustumPos[i], matCameraViewInv); Vector3 posL = PosVecTransform(posW, matLightView); lightSpaceBound = AABBox::CombinePoint(lightSpaceBound, posL); } float nearZ = 0.1f; float farZ = 0; float width = 0; float height = 0; { Vector3 lookDir = camera->GetWorldForward(); lookDir.Normalize(); float adjustFactor = lookDir.Dot(lightDir); // lookDir与lightDir贴近时, 向后扩展virtualCamera范围 float expandDist = adjustFactor * BOUND_EXPAND_FACTOR * fabsf(lightSpaceBound.mMax.z - lightSpaceBound.mMin.z); Vector3 centerL = lightSpaceBound.GetCenter(); D3DXMATRIX matLightViewInv; D3DXMatrixInverse(&matLightViewInv, 0, &matLightView); Vector3 centerW = PosVecTransform(centerL, matLightViewInv); float lightDist = fabsf(lightSpaceBound.mMax.z - lightSpaceBound.mMin.z) / 2.0f; width = fabsf(lightSpaceBound.mMax.x - lightSpaceBound.mMin.x); height = fabsf(lightSpaceBound.mMax.y - lightSpaceBound.mMin.y); farZ = 2.0f * lightDist + expandDist; mVirtualCamera[cascadeIndex].pos = centerW - (lightDist + expandDist) * lightDir; } D3DXMATRIX matLightProj; D3DXMatrixOrthoLH(&matLightProj, width, height, nearZ, farZ); D3DXMATRIX matVirtualCameraView; { Vector3 virtualCameraPos = mVirtualCamera[cascadeIndex].pos; D3DXMATRIX matRotTranspose, matTransInverse; D3DXMatrixTranspose(&matRotTranspose, &(lightNode->GetWorldOrient().Matrix())); D3DXMatrixTranslation(&matTransInverse, -virtualCameraPos.x, -virtualCameraPos.y, -virtualCameraPos.z); matVirtualCameraView = matTransInverse * matRotTranspose; mVirtualCamera[cascadeIndex].bound = AABBox::MatTransform(AABBox(Vector3(0, 0, farZ/2.0f), width, height, farZ), InversedMatrix(matVirtualCameraView)); } mVirtualCamera[cascadeIndex].matVP = matVirtualCameraView * matLightProj; }
void Renderer::fitViewNearFarToObjects(Float2& near_far, const Float4x4& view, const float near_min, const float far_max, const bool inc_light_vols) const { near_far.set(near_min, far_max); return; // Note, the fitting is NOT tight. Firstly, we're using the geometry's // axis aligned bounding box, which is not tight (after the model // transform) then we're assuming the size of the box is maximum after // rotation into the camera space (which is also not tight). // Recall: OpenGL convention is to look down the negative Z axis, // therefore, more negative values are actually further away. near_far[0] = -std::numeric_limits<float>::infinity(); // znear near_far[1] = std::numeric_limits<float>::infinity(); // zfar float min_z, max_z; gm_->renderStackReset(); while (!gm_->renderStackEmpty()) { GeometryInstance* cur_geometry = gm_->renderStackPop(); AABBox* aabbox = cur_geometry->aabbox(); if (aabbox) { aabbox->calcMinMaxZBoundInViewSpace(min_z, max_z, view); if (max_z < near_far[1]) { near_far[1] = max_z; } if (min_z > near_far[0]) { near_far[0] = min_z; } } } // Also fit to light geometry: if (inc_light_vols) { Float3 pos_source; Float3 dir; float rad; Float3 center_view; LightPoint* light_point; LightSpot* light_spot; for (uint32_t i = 0; i < lighting_->lights().size(); i++) { switch (lighting_->lights()[i]->type()) { case LIGHT_POINT: light_point = (LightPoint*)(lighting_->lights()[i]); // Calculate model view projection matrix Float3::affineTransformPos(center_view, view, light_point->pos_world()); rad = light_point->outside_rad(); if ((center_view[2] - rad) < near_far[1]) { near_far[1] = center_view[2] - rad; } if ((center_view[2] + rad) > near_far[0]) { near_far[0] = center_view[2] + rad; } break; case LIGHT_SPOT_VSM: case LIGHT_SPOT: light_spot = (LightSpot*)(lighting_->lights()[i]); // Check the source point Float3::affineTransformPos(pos_source, view, light_spot->pos_world()); if (pos_source[2] < near_far[1]) { near_far[1] = pos_source[2]; } if (pos_source[2] > near_far[0]) { near_far[0] = pos_source[2]; } // Now check the cone end Float3::affineTransformPos(center_view, view, light_spot->cone_center_world()); rad = light_spot->cone_outside_radius(); if ((center_view[2] - rad) < near_far[1]) { near_far[1] = center_view[2] - rad; } if ((center_view[2] + rad) > near_far[0]) { near_far[0] = center_view[2] + rad; } break; default: break; } } } near_far[0] += LOOSE_EPSILON; near_far[1] -= LOOSE_EPSILON; // now clamp the near and far to the user defined values if (near_far[0] > near_min) { near_far[0] = near_min; } if (near_far[1] < far_max) { near_far[1] = far_max; } if (near_far[1] > near_far[0]) { near_far[1] = near_far[0] - 0.1f; } }
/** * @return Box in light space containing shadow caster and receiver (scene dependent) */ AABBox<float> ShadowManager::createSceneDependentBox(const AABBox<float> &aabboxSceneIndependent, const OBBox<float> &obboxSceneIndependentViewSpace, const std::set<Model *> &models, const Matrix4<float> &lightViewMatrix) const { AABBox<float> aabboxSceneDependent; bool boxInitialized = false; AABBox<float> aabboxSceneIndependentViewSpace = obboxSceneIndependentViewSpace.toAABBox(); for(std::set<Model *>::iterator it = models.begin(); it!=models.end(); ++it) { const Model* model = *it; if(model->isProduceShadow()) { const std::vector<AABBox<float>> &splittedAABBox = model->getSplittedAABBox(); for(unsigned int i=0; i<splittedAABBox.size(); ++i) { if(splittedAABBox.size()==1 || obboxSceneIndependentViewSpace.collideWithAABBox(splittedAABBox[i])) { if(boxInitialized) { aabboxSceneDependent = aabboxSceneDependent.merge(lightViewMatrix * splittedAABBox[i]); }else { aabboxSceneDependent = lightViewMatrix * splittedAABBox[i]; boxInitialized = true; } } } } } Point3<float> cutMin( aabboxSceneDependent.getMin().X<aabboxSceneIndependent.getMin().X ? aabboxSceneIndependent.getMin().X : aabboxSceneDependent.getMin().X, aabboxSceneDependent.getMin().Y<aabboxSceneIndependent.getMin().Y ? aabboxSceneIndependent.getMin().Y : aabboxSceneDependent.getMin().Y, aabboxSceneIndependent.getMin().Z); //shadow can be projected outside the box: value cannot be capped Point3<float> cutMax( aabboxSceneDependent.getMax().X>aabboxSceneIndependent.getMax().X ? aabboxSceneIndependent.getMax().X : aabboxSceneDependent.getMax().X, aabboxSceneDependent.getMax().Y>aabboxSceneIndependent.getMax().Y ? aabboxSceneIndependent.getMax().Y : aabboxSceneDependent.getMax().Y, aabboxSceneDependent.getMax().Z>aabboxSceneIndependent.getMax().Z ? aabboxSceneIndependent.getMax().Z : aabboxSceneDependent.getMax().Z); cutMin.X = (cutMin.X<0.0f) ? cutMin.X-(lightViewOverflowStepSize+fmod(cutMin.X, lightViewOverflowStepSize)) : cutMin.X-fmod(cutMin.X, lightViewOverflowStepSize); cutMin.Y = (cutMin.Y<0.0f) ? cutMin.Y-(lightViewOverflowStepSize+fmod(cutMin.Y, lightViewOverflowStepSize)) : cutMin.Y-fmod(cutMin.Y, lightViewOverflowStepSize); cutMin.Z = (cutMin.Z<0.0f) ? cutMin.Z-(lightViewOverflowStepSize+fmod(cutMin.Z, lightViewOverflowStepSize)) : cutMin.Z-fmod(cutMin.Z, lightViewOverflowStepSize); cutMax.X = (cutMax.X<0.0f) ? cutMax.X-fmod(cutMax.X, lightViewOverflowStepSize) : cutMax.X+(lightViewOverflowStepSize-fmod(cutMax.X, lightViewOverflowStepSize)); cutMax.Y = (cutMax.Y<0.0f) ? cutMax.Y-fmod(cutMax.Y, lightViewOverflowStepSize) : cutMax.Y+(lightViewOverflowStepSize-fmod(cutMax.Y, lightViewOverflowStepSize)); cutMax.Z = (cutMax.Z<0.0f) ? cutMax.Z-fmod(cutMax.Z, lightViewOverflowStepSize) : cutMax.Z+(lightViewOverflowStepSize-fmod(cutMax.Z, lightViewOverflowStepSize)); return AABBox<float>(cutMin, cutMax); }
bool operator()(AABBox a, AABBox b) { return (a.mortonCentroid() < b.mortonCentroid()); }
bool BVH::compareBoxMorton(AABBox a, AABBox b) { return a.mortonCentroid() < b.mortonCentroid(); }