void GameObjectGroup::Update(const FrameTime& fr, UpdateTypeEnum updateType) { bool boundDirty = m_boundsDirty; super::Update(fr,updateType); m_boundsDirty = boundDirty; for( auto it = m_children.begin(); it != m_children.end(); ++it) { (*it)->Update(fr,updateType); } // Update bounds if(m_boundsDirty) { bool usechildbounds = false; AABB childbounds; // default ctor will set initial value of min and max. // merge bounds for the the visibile children. for (auto it = m_children.begin(); it != m_children.end(); ++it) { if( (*it)->IsVisible()) { AABB local = (*it)->GetLocalBounds(); local.Transform((*it)->GetTransform()); childbounds.Extend( local ); usechildbounds = true; } } // set local bounds m_localBounds = usechildbounds ? childbounds : AABB(float3(-0.5f,-0.5f,-0.5f), float3(0.5f,0.5f,0.5f)); UpdateWorldAABB(); } }
// ------------------------------------------------------------------------------------------------ void Model::UpdateBounds() { assert(m_constructed==true); const GeometryDict& geos = Geometries(); if(geos.size()==0) { return; } float3 min = float3(FLT_MAX, FLT_MAX, FLT_MAX); float3 max = float3(-FLT_MAX, -FLT_MAX, -FLT_MAX); const NodeDict& nodes = Nodes(); for(auto nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt) { Node* node = nodeIt->second; for(auto geoIt = node->geometries.begin(); geoIt != node->geometries.end(); ++geoIt) { Geometry * geo = (*geoIt); AABB bbox = geo->mesh->bounds; bbox.Transform(m_nodeTransforms[node->index]); min = minimize(min, bbox.Min()); max = maximize(max, bbox.Max()); } } // note: min & max already transformed by entire object world matrix m_bounds = AABB(min, max); }
OBB operator *(const Quat &transform, const AABB &aabb) { return aabb.Transform(transform); }
OBB operator *(const float4x4 &transform, const AABB &aabb) { return aabb.Transform(transform); }
void CurveGob::Update(const FrameTime& fr, UpdateTypeEnum updateType) { bool boundDirty = m_boundsDirty; super::Update(fr,updateType); m_boundsDirty = boundDirty; if(!m_boundsDirty) return; m_mesh.pos.clear(); if(m_needsRebuild) { SAFE_DELETE(m_mesh.vertexBuffer); } if(m_points.size()<2) { m_localBounds = AABB(float3(-0.5f,-0.5f,-0.5f), float3(0.5f,0.5f,0.5f)); UpdateWorldAABB(); return; } // compute local bounds. m_localBounds = m_points[0]->GetLocalBounds(); m_localBounds.Transform(m_points[0]->GetTransform()); for( auto it = m_points.begin(); it != m_points.end(); ++it) { (*it)->Update(fr,updateType); AABB local = (*it)->GetLocalBounds(); local.Transform((*it)->GetTransform()); m_localBounds.Extend(local); } // compute world bound. float3 min,max; min = m_points[0]->GetBounds().Min(); max = m_points[0]->GetBounds().Max(); for( auto it = m_points.begin(); it != m_points.end(); ++it) { min = minimize(min, (*it)->GetBounds().Min()); max = maximize(max, (*it)->GetBounds().Max()); } m_bounds = AABB(min,max); m_boundsDirty = false; std::vector<float3> verts; switch(m_type) { default: Logger::Log(OutputMessageType::Error, "Invalid curve type, '%d'\n", m_type); // fall through and just pretend it is Linear case Linear: {// add all the normal control point positions for(auto it = m_points.begin(); it != m_points.end(); ++it) { float3 vert = float3(&(*it)->GetTransform().M41); verts.push_back(vert); } if(m_closed) { verts.push_back(verts[0]); } break; } case CatmullRom: { std::vector<float3> points; //// since catmull-rom interpolation requires additional points, we want to calculate //// to 'fake' points to be the endpoints. That way our line will exists for all the //// actual control points. size_t size = m_points.size(); if(m_closed) { // add the last point before others for consistent interpolation points.push_back(float3(&m_points[size-1]->GetTransform().M41)); } else { // add an extra point in front of the 1st control point for interpolation float3 p1(&m_points[0]->GetTransform().M41); float3 p2(&m_points[1]->GetTransform().M41); float3 delta = p1 - p2; // from p2 to p1 points.push_back(p1 + delta); } // add all normal control point positions for(auto it = m_points.begin(); it != m_points.end(); ++it) { points.push_back(float3(&(*it)->GetTransform().M41)); } if(m_closed) { // add first and second points for consistent interpolation points.push_back(&m_points[0]->GetTransform().M41); points.push_back(&m_points[1]->GetTransform().M41); } else { // add an extra point in after of the last control point for interpolation float3 p1 = points[size-1]; float3 p2 = points[size-2]; float3 delta = p1 - p2; // from p2 to p1 points.push_back(p1 + delta); } // Interpolate size_t sz = points.size() - 2; for(unsigned int index = 1; index < sz; index++) { float3 p0 = points[index-1]; float3 p1 = points[index]; float3 p2 = points[index+1]; float3 p3 = points[index+2]; for(int i = 0; i < m_steps; ++i) { float s = (float)i / (float)m_steps; verts.push_back(Vec3CatmullRom(p0,p1,p2,p3,s)); } } verts.push_back(points[sz]); break; } case Bezier: { std::vector<float3> points; // add all normal control point positions for(auto it = m_points.begin(); it != m_points.end(); ++it) { points.push_back(float3(&(*it)->GetTransform().M41)); } BezierSpline spline(&points[0],(int)points.size(),m_closed); for(int i = 0; i < spline.CurveCount(); i++) { const BezierCurve& curve = spline.GetCurveAt(i); for(int k = 0; k < m_steps; k++) { float s = (float)k / (float)m_steps; verts.push_back(curve.Eval(s)); } } // Handle last point if (m_closed && m_points.size() > 2) verts.push_back(points[0]); else verts.push_back(points[points.size()-1]); break; } } for(auto it = verts.begin(); it != verts.end(); it++) { m_mesh.pos.push_back(*it); } m_mesh.ComputeBound(); if(m_needsRebuild) { m_mesh.vertexBuffer = GpuResourceFactory::CreateVertexBuffer(&verts[0], VertexFormat::VF_P, (uint32_t)verts.size(), BufferUsage::DYNAMIC); } else { ID3D11DeviceContext* context = gD3D11->GetImmediateContext(); assert(m_mesh.vertexBuffer != NULL); m_mesh.vertexBuffer->Update(context,&verts[0],(uint32_t)verts.size()); } m_needsRebuild = false; }
//--------------------------------------------------------------------------- void ShadowMaps::UpdateLightCamera( ID3D11DeviceContext* dc, const DirLight* light, const AABB& renderedArea ) { float3 worldUp(0,1,0); float3 lightDir = normalize(light->dir); // compute ligtcam params. float dt = dot(-lightDir, worldUp); float3 center = renderedArea.GetCenter(); float dim = length(renderedArea.Max() - renderedArea.Min()); float radi = dim * 0.5f; float3 camPos = center - (radi * lightDir); float3 up; float3 right; if ((dt + Epsilon) >= 1) { up = float3(0, 0, -1); right = float3(1, 0, 0); } else { right = normalize(cross(lightDir, worldUp)); up = normalize(cross(right, lightDir)); right = cross(lightDir, worldUp); up = cross(right, lightDir); } // create view matrix from right, up and look, and position. float rp = -dot(right, camPos); float upp = -dot(up, camPos); float zp = dot(lightDir, camPos); Matrix view( right.x, up.x, -lightDir.x, 0.0f, right.y, up.y, -lightDir.y, 0.0f, right.z, up.z, -lightDir.z, 0.0f, rp, upp, zp, 1.0f); // compute the width, height, near, far by transforming the AABB into view space. AABB lbounds = renderedArea; lbounds.Transform(view); float3 vmin = lbounds.Min(); float3 vmax = lbounds.Max(); float width = vmax.x - vmin.x; float height = vmax.y - vmin.y; float nearz = 0.0f; float farz = dim; Matrix proj = Matrix::CreateOrthographic(width,height, nearz, farz); //Matrix proj = Matrix::CreateOrthographicOffCenter(vmin.x, vmax.x, vmin.y, vmax.y, nearz, farz); m_lightCamera.SetViewProj(view, proj); // update cb m_cbShadow.Data.texelSize = ( 1.0f / MapSize() ); // udpate constant buffer using lightcamera. // transform coords from NDC space to texture space. float4x4 ndcToTexSpace( 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, 0.0f, 1.0f); float4x4 shadowViewProjection = (m_lightCamera.View() * m_lightCamera.Proj()) * ndcToTexSpace; Matrix::Transpose(shadowViewProjection, m_cbShadow.Data.xform); m_cbShadow.Update(dc); }