// a and b are not overlapping if they are seperated on any major axis bool TestAABBAABB(const AABB& a, const AABB& b) { if(a.Max().x < b.Min().x || a.Min().x > b.Max().x) return false; if(a.Max().z < b.Min().z || a.Min().z > b.Max().z) return false; if(a.Max().y < b.Min().y || a.Min().y > b.Max().y) return false; return true; }
bool IntersectRayAABB(const Ray& r, const AABB& a, float* out_tmin, float3* out_pos, float3* out_nor) { const float3& p = r.pos; const float3& d = r.direction; float tmin = -FLT_MAX; float tmax = FLT_MAX; float3 minNorm, maxNorm; // check vs. all three 'slabs' of the aabb for(int i = 0; i < 3; ++i) { if(abs(d[i]) < Epsilon) { // ray is parallel to slab, no hit if origin not within slab if(p[i] < a.Min()[i] || p[i] > a.Max()[i] ) { return false; } } else { // compute intersection t values of ray with near and far plane of slab float ood = 1.0f / d[i]; float t1 = (a.Min()[i] - p[i]) * ood; float t2 = (a.Max()[i] - p[i]) * ood; tmin = maximize(tmin, minimize(t1, t2)); tmax = minimize(tmax, maximize(t1, t2)); // exit with no collision as soon as slab intersection becomes empty if(tmin > tmax) { return false; } } } if(tmax < 0.f) { // entire bounding box is behind us return false; } else if(tmin < 0.f) { // we are inside the bounding box *out_tmin = 0.f; *out_pos = p; *out_nor = normalize(a.GetCenter() - (*out_pos)); // use 'sphere' type normal calculation to approximate. return true; } else { // ray intersects all 3 slabs. return point and normal of intersection *out_tmin = tmin; *out_pos = p + d * tmin; *out_nor = normalize(a.GetCenter() - (*out_pos)); // use 'sphere' type normal calculation to approximate. return true; } }
AABB operator*(const Mat4& transform, const AABB& aabb) { const Vec4 newMin = transform * Vec4( aabb.Min(), 1.0f ); const Vec4 newMax = transform * Vec4( aabb.Max(), 1.0f ); return AABB( Vec3( newMin ), Vec3( newMax ) ); }
// ------------------------------------------------------------------------------------------------ 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); }
void LineRenderer::DrawAABB(const AABB& aabb, const float4& color) { float3 min = aabb.Min(); float3 max = aabb.Max(); // render top quad m_vertsPC.push_back(VertexPC(max,color)); m_vertsPC.push_back(VertexPC(float3(min.x,max.y,max.z),color)); m_vertsPC.push_back(VertexPC(float3(min.x,max.y,max.z),color)); m_vertsPC.push_back(VertexPC(float3(min.x,max.y,min.z),color)); m_vertsPC.push_back(VertexPC(float3(min.x,max.y,min.z),color)); m_vertsPC.push_back(VertexPC(float3(max.x,max.y,min.z),color)); m_vertsPC.push_back(VertexPC(float3(max.x,max.y,min.z),color)); m_vertsPC.push_back(VertexPC(max,color)); // render bottom quad m_vertsPC.push_back(VertexPC(float3(max.x,min.y,max.z),color)); m_vertsPC.push_back(VertexPC(float3(min.x,min.y,max.z),color)); m_vertsPC.push_back(VertexPC(float3(min.x,min.y,max.z),color)); m_vertsPC.push_back(VertexPC(float3(min.x,min.y,min.z),color)); m_vertsPC.push_back(VertexPC(float3(min.x,min.y,min.z),color)); m_vertsPC.push_back(VertexPC(float3(max.x,min.y,min.z),color)); m_vertsPC.push_back(VertexPC(float3(max.x,min.y,min.z),color)); m_vertsPC.push_back(VertexPC(float3(max.x,min.y,max.z),color)); // four legs m_vertsPC.push_back(VertexPC(max,color)); m_vertsPC.push_back(VertexPC(float3(max.x,min.y,max.z),color)); m_vertsPC.push_back(VertexPC(float3(min.x,max.y,max.z),color)); m_vertsPC.push_back(VertexPC(float3(min.x,min.y,max.z),color)); m_vertsPC.push_back(VertexPC(float3(min.x,max.y,min.z),color)); m_vertsPC.push_back(VertexPC(float3(min.x,min.y,min.z),color)); m_vertsPC.push_back(VertexPC(float3(max.x,max.y,min.z),color)); m_vertsPC.push_back(VertexPC(float3(max.x,min.y,min.z),color)); }
//--------------------------------------------------------------------------- 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); }