BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start, int num) { if(num == 0) { BoundBox bounds = BoundBox::empty; return new LeafNode(bounds, 0, 0, 0); } else if(num == 1) { if(start == prim_index.size()) { assert(params.use_spatial_split); prim_segment.push_back(ref->prim_segment()); prim_index.push_back(ref->prim_index()); prim_object.push_back(ref->prim_object()); } else { prim_segment[start] = ref->prim_segment(); prim_index[start] = ref->prim_index(); prim_object[start] = ref->prim_object(); } uint visibility = objects[ref->prim_object()]->visibility; return new LeafNode(ref->bounds(), visibility, start, start+1); } else { int mid = num/2; BVHNode *leaf0 = create_object_leaf_nodes(ref, start, mid); BVHNode *leaf1 = create_object_leaf_nodes(ref+mid, start+mid, num-mid); BoundBox bounds = BoundBox::empty; bounds.grow(leaf0->m_bounds); bounds.grow(leaf1->m_bounds); return new InnerNode(bounds, leaf0, leaf1); } }
//----------------------------------------------------------------------------- // Purpose: // Input : *pRender - //----------------------------------------------------------------------------- void CGizmo::Render(CRender3D *pRender) { Vector XAxis( m_Position[0] + m_fAxisLength, m_Position[1], m_Position[2] ); Vector YAxis( m_Position[0], m_Position[1] + m_fAxisLength, m_Position[2] ); Vector ZAxis( m_Position[0], m_Position[1], m_Position[2] + m_fAxisLength ); static BoundBox UniformScaleBox; Vector Mins; Vector Maxs; Mins[0] = m_Position[0] - m_fAxisLength * 0.1; Mins[1] = m_Position[1] - m_fAxisLength * 0.1; Mins[2] = m_Position[2] - m_fAxisLength * 0.1; Maxs[0] = m_Position[0] + m_fAxisLength * 0.1; Maxs[1] = m_Position[1] + m_fAxisLength * 0.1; Maxs[2] = m_Position[2] + m_fAxisLength * 0.1; UniformScaleBox.ResetBounds(); UniformScaleBox.UpdateBounds(Mins, Maxs); pRender->BeginRenderHitTarget(this, GIZMO_HANDLE_UNIFORM_SCALE); //pRender->RenderBox(Mins, Maxs, BoxType_Solid, 200, 200, 200); pRender->EndRenderHitTarget(); pRender->SetRenderMode( RENDER_MODE_TEXTURED ); DrawGizmoAxis(pRender, m_Position, XAxis, 255, 0, 0, GIZMO_AXIS_X); DrawGizmoAxis(pRender, m_Position, YAxis, 0, 255, 0, GIZMO_AXIS_Y); DrawGizmoAxis(pRender, m_Position, ZAxis, 0, 0, 255, GIZMO_AXIS_Z); pRender->SetRenderMode( RENDER_MODE_DEFAULT ); }
void BVHSpatialSplit::split_triangle_primitive(const Mesh *mesh, const Transform *tfm, int prim_index, int dim, float pos, BoundBox& left_bounds, BoundBox& right_bounds) { const int *inds = mesh->triangles[prim_index].v; const float3 *verts = &mesh->verts[0]; float3 v1 = tfm ? transform_point(tfm, verts[inds[2]]) : verts[inds[2]]; for(int i = 0; i < 3; i++) { float3 v0 = v1; int vindex = inds[i]; v1 = tfm ? transform_point(tfm, verts[vindex]) : verts[vindex]; float v0p = v0[dim]; float v1p = v1[dim]; /* insert vertex to the boxes it belongs to. */ if(v0p <= pos) left_bounds.grow(v0); if(v0p >= pos) right_bounds.grow(v0); /* edge intersects the plane => insert intersection to both boxes. */ if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) { float3 t = lerp(v0, v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f)); left_bounds.grow(t); right_bounds.grow(t); } } }
BoundBox BicubicPatch::bound() { BoundBox bbox = BoundBox::empty; for (int i = 0; i < 16; i++) bbox.grow(hull[i]); return bbox; }
BoundBox LinearTrianglePatch::bound() { BoundBox bbox; for(int i = 0; i < 3; i++) bbox.grow(hull[i]); return bbox; }
BoundBox BicubicTangentPatch::bound() { BoundBox bbox; for(int i = 0; i < 16; i++) bbox.grow(hull[i]); return bbox; }
BoundBox GregoryTrianglePatch::bound() { BoundBox bbox; for(int i = 0; i < 20; i++) bbox.grow(hull[i]); return bbox; }
BoundBox LinearQuadPatch::bound() { BoundBox bbox; for(int i = 0; i < 4; i++) bbox.grow(hull[i]); return bbox; }
BVHNode* BVHBuild::create_leaf_node(const BVHRange& range) { vector<int>& p_segment = prim_segment; vector<int>& p_index = prim_index; vector<int>& p_object = prim_object; BoundBox bounds = BoundBox::empty; int num = 0, ob_num = 0; uint visibility = 0; for(int i = 0; i < range.size(); i++) { BVHReference& ref = references[range.start() + i]; if(ref.prim_index() != -1) { if(range.start() + num == prim_index.size()) { assert(params.use_spatial_split); p_segment.push_back(ref.prim_segment()); p_index.push_back(ref.prim_index()); p_object.push_back(ref.prim_object()); } else { p_segment[range.start() + num] = ref.prim_segment(); p_index[range.start() + num] = ref.prim_index(); p_object[range.start() + num] = ref.prim_object(); } bounds.grow(ref.bounds()); visibility |= objects[ref.prim_object()]->visibility; num++; } else { if(ob_num < i) references[range.start() + ob_num] = ref; ob_num++; } } BVHNode *leaf = NULL; if(num > 0) { leaf = new LeafNode(bounds, visibility, range.start(), range.start() + num); if(num == range.size()) return leaf; } /* while there may be multiple triangles in a leaf, for object primitives * we want there to be the only one, so we keep splitting */ const BVHReference *ref = (ob_num)? &references[range.start()]: NULL; BVHNode *oleaf = create_object_leaf_nodes(ref, range.start() + num, ob_num); if(leaf) return new InnerNode(range.bounds(), leaf, oleaf); else return oleaf; }
void BVHBuild::add_references(BVHRange& root) { /* reserve space for references */ size_t num_alloc_references = 0; foreach(Object *ob, objects) { if(params.top_level) { if(!ob->mesh->is_instanced()) { num_alloc_references += ob->mesh->triangles.size(); num_alloc_references += count_curve_segments(ob->mesh); } else num_alloc_references++; } else { num_alloc_references += ob->mesh->triangles.size(); num_alloc_references += count_curve_segments(ob->mesh); } } references.reserve(num_alloc_references); /* add references from objects */ BoundBox bounds = BoundBox::empty, center = BoundBox::empty; int i = 0; foreach(Object *ob, objects) { if(params.top_level) { if(!ob->mesh->is_instanced()) add_reference_mesh(bounds, center, ob->mesh, i); else add_reference_object(bounds, center, ob, i); } else add_reference_mesh(bounds, center, ob->mesh, i); i++; if(progress.get_cancel()) return; } /* happens mostly on empty meshes */ if(!bounds.valid()) bounds.grow(make_float3(0.0f, 0.0f, 0.0f)); root = BVHRange(bounds, center, 0, references.size()); }
BoundBox Camera::viewplane_bounds_get() { /* TODO(sergey): This is all rather stupid, but is there a way to perform * checks we need in a more clear and smart fasion? */ BoundBox bounds = BoundBox::empty; if(type == CAMERA_PANORAMA) { bounds.grow(make_float3(cameratoworld.w.x, cameratoworld.w.y, cameratoworld.w.z)); } else { bounds.grow(transform_raster_to_world(0.0f, 0.0f)); bounds.grow(transform_raster_to_world(0.0f, (float)height)); bounds.grow(transform_raster_to_world((float)width, (float)height)); bounds.grow(transform_raster_to_world((float)width, 0.0f)); if(type == CAMERA_PERSPECTIVE) { /* Center point has the most distance in local Z axis, * use it to construct bounding box/ */ bounds.grow(transform_raster_to_world(0.5f*width, 0.5f*height)); } } return bounds; }
void FlightPointList::boundBox(BoundBox &bbox) { uint index; for(index=0; index<size(); index++) { bbox.setMinMax(m_flightPointList[index]->pos()); } }
SPtr<ModelRecord> BoundBox_Loader::loadModel(WorldEntity *we, const std::string &model_id, varconf::Config &model_config) { assert (we); SPtr<ModelRecord> model_record = ModelLoader::loadModel(we, model_id, model_config); BoundBox *model = new BoundBox(); WFMath::AxisBox<3> bbox = we->hasBBox() ? (we->getBBox()) : (WFMath::AxisBox<3>(WFMath::Point<3>(0.0f,0.0f,0.0f), WFMath::Point<3>(1.0f,1.0f,1.0f))); std::string texture = we->type(); bool wrap = false; //default to false // Check whether we specify texture wrapping if (model_config.findItem(model_id, KEY_texture)) { texture = (std::string)model_config.getItem(model_id, KEY_texture); } // Get texture name if (model_config.findItem(model_id, KEY_wrap_texture)) { wrap = (bool)model_config.getItem(model_id, KEY_wrap_texture); } // Initialise model if (model->init(bbox, texture, wrap)) { std::cerr<< "BoundBoxLoader: Error initialising model" << std::endl; delete model; return SPtr<ModelRecord>(); } bool use_stencil = RenderSystem::getInstance().getState(RenderSystem::RENDER_STENCIL) && model_record->outline; StaticObjectList &sol = model->getStaticObjects(); StaticObjectList::iterator I = sol.begin(); while (I != sol.end()) { (*I)->setState(model_record->state); (*I)->setSelectState(model_record->select_state); (*I)->setUseStencil(use_stencil); ++I; } model_record->model = SPtr<Model>(model); return model_record; }
//Determine the global assembly box ErrorCode ParallelMergeMesh::GetGlobalBox(double *gbox) { ErrorCode rval; /*Get Bounding Box*/ BoundBox box; if(mySkinEnts[0].size() != 0){ rval = box.update(*myMB, mySkinEnts[0]);MB_CHK_ERR(rval); } //Invert the max box.bMax *= -1; /*Communicate to all processors*/ MPI_Allreduce(&box, gbox, 6, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); /*Assemble Global Bounding Box*/ //Flip the max back for(int i=3; i<6; i++){ gbox[i] *= -1; } return MB_SUCCESS; }
void BVHSpatialSplit::split_curve_primitive(const Mesh *mesh, const Transform *tfm, int prim_index, int segment_index, int dim, float pos, BoundBox& left_bounds, BoundBox& right_bounds) { /* curve split: NOTE - Currently ignores curve width and needs to be fixed.*/ const int k0 = mesh->curves[prim_index].first_key + segment_index; const int k1 = k0 + 1; const float4& key0 = mesh->curve_keys[k0]; const float4& key1 = mesh->curve_keys[k1]; float3 v0 = float4_to_float3(key0); float3 v1 = float4_to_float3(key1); if(tfm != NULL) { v0 = transform_point(tfm, v0); v1 = transform_point(tfm, v1); } float v0p = v0[dim]; float v1p = v1[dim]; /* insert vertex to the boxes it belongs to. */ if(v0p <= pos) left_bounds.grow(v0); if(v0p >= pos) right_bounds.grow(v0); if(v1p <= pos) left_bounds.grow(v1); if(v1p >= pos) right_bounds.grow(v1); /* edge intersects the plane => insert intersection to both boxes. */ if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) { float3 t = lerp(v0, v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f)); left_bounds.grow(t); right_bounds.grow(t); } }
void BVH4::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility) { if(leaf) { int4 *data = &pack.leaf_nodes[idx]; int4 c = data[0]; /* Refit leaf node. */ for(int prim = c.x; prim < c.y; prim++) { int pidx = pack.prim_index[prim]; int tob = pack.prim_object[prim]; Object *ob = objects[tob]; if(pidx == -1) { /* Object instance. */ bbox.grow(ob->bounds); } else { /* Primitives. */ const Mesh *mesh = ob->mesh; if(pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) { /* Curves. */ int str_offset = (params.top_level)? mesh->curve_offset: 0; Mesh::Curve curve = mesh->get_curve(pidx - str_offset); int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]); curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox); visibility |= PATH_RAY_CURVE; /* Motion curves. */ if(mesh->use_motion_blur) { Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if(attr) { size_t mesh_size = mesh->curve_keys.size(); size_t steps = mesh->motion_steps - 1; float3 *key_steps = attr->data_float3(); for(size_t i = 0; i < steps; i++) curve.bounds_grow(k, key_steps + i*mesh_size, &mesh->curve_radius[0], bbox); } } } else { /* Triangles. */ int tri_offset = (params.top_level)? mesh->tri_offset: 0; Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset); const float3 *vpos = &mesh->verts[0]; triangle.bounds_grow(vpos, bbox); /* Motion triangles. */ if(mesh->use_motion_blur) { Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if(attr) { size_t mesh_size = mesh->verts.size(); size_t steps = mesh->motion_steps - 1; float3 *vert_steps = attr->data_float3(); for(size_t i = 0; i < steps; i++) triangle.bounds_grow(vert_steps + i*mesh_size, bbox); } } } } visibility |= ob->visibility_for_tracing(); } /* TODO(sergey): This is actually a copy of pack_leaf(), * but this chunk of code only knows actual data and has * no idea about BVHNode. * * Would be nice to de-duplicate code, but trying to make * making code more general ends up in much nastier code * in my opinion so far. * * Same applies to the inner nodes case below. */ float4 leaf_data[BVH_QNODE_LEAF_SIZE]; leaf_data[0].x = __int_as_float(c.x); leaf_data[0].y = __int_as_float(c.y); leaf_data[0].z = __uint_as_float(visibility); leaf_data[0].w = __uint_as_float(c.w); memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4)*BVH_QNODE_LEAF_SIZE); } else { int4 *data = &pack.nodes[idx]; bool is_unaligned = (data[0].x & PATH_RAY_NODE_UNALIGNED) != 0; int4 c; if(is_unaligned) { c = data[13]; } else { c = data[7]; } /* Refit inner node, set bbox from children. */ BoundBox child_bbox[4] = {BoundBox::empty, BoundBox::empty, BoundBox::empty, BoundBox::empty}; uint child_visibility[4] = {0}; int num_nodes = 0; for(int i = 0; i < 4; ++i) { if(c[i] != 0) { refit_node((c[i] < 0)? -c[i]-1: c[i], (c[i] < 0), child_bbox[i], child_visibility[i]); ++num_nodes; bbox.grow(child_bbox[i]); visibility |= child_visibility[i]; } } if(is_unaligned) { Transform aligned_space[4] = {transform_identity(), transform_identity(), transform_identity(), transform_identity()}; pack_unaligned_node(idx, aligned_space, child_bbox, &c[0], visibility, 0.0f, 1.0f, 4); } else { pack_aligned_node(idx, child_bbox, &c[0], visibility, 0.0f, 1.0f, 4); } } }
inline bool isBounded( iXY &test ) { return( capture_area.bounds( location, test ) ); }
BoundBox(const BoundBox<THEIR_PRECISION>& src) : minpoint(src.min_point()) , maxpoint(src.max_point()) { }
/** * These add the given point to this bbox - they * offset each corner by this point. Usful for calculating * the location of a box in a higher scope, or for moving * it around as part of a calculation * * Naturally, the {+,-} don't modify and the {+,-}= do. */ BoundBox operator+ (const point_type& rhs) const { BoundBox result = *this; result.offset(rhs); return result; }
BoundBox operator- (const point_type& rhs) const { BoundBox result = *this; result.offset(point_type(-rhs.x, -rhs.y)); return result; }
void BVH::refit_primitives(int start, int end, BoundBox& bbox, uint& visibility) { /* Refit range of primitives. */ for(int prim = start; prim < end; prim++) { int pidx = pack.prim_index[prim]; int tob = pack.prim_object[prim]; Object *ob = objects[tob]; if(pidx == -1) { /* Object instance. */ bbox.grow(ob->bounds); } else { /* Primitives. */ const Mesh *mesh = ob->mesh; if(pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) { /* Curves. */ int str_offset = (params.top_level)? mesh->curve_offset: 0; Mesh::Curve curve = mesh->get_curve(pidx - str_offset); int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]); curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox); visibility |= PATH_RAY_CURVE; /* Motion curves. */ if(mesh->use_motion_blur) { Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if(attr) { size_t mesh_size = mesh->curve_keys.size(); size_t steps = mesh->motion_steps - 1; float3 *key_steps = attr->data_float3(); for(size_t i = 0; i < steps; i++) curve.bounds_grow(k, key_steps + i*mesh_size, &mesh->curve_radius[0], bbox); } } } else { /* Triangles. */ int tri_offset = (params.top_level)? mesh->tri_offset: 0; Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset); const float3 *vpos = &mesh->verts[0]; triangle.bounds_grow(vpos, bbox); /* Motion triangles. */ if(mesh->use_motion_blur) { Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if(attr) { size_t mesh_size = mesh->verts.size(); size_t steps = mesh->motion_steps - 1; float3 *vert_steps = attr->data_float3(); for(size_t i = 0; i < steps; i++) triangle.bounds_grow(vert_steps + i*mesh_size, bbox); } } } } visibility |= ob->visibility_for_tracing(); } }
void BVHSpatialSplit::split(BVHBuild *builder, BVHRange& left, BVHRange& right, const BVHRange& range) { /* Categorize references and compute bounds. * * Left-hand side: [left_start, left_end[ * Uncategorized/split: [left_end, right_start[ * Right-hand side: [right_start, refs.size()[ */ vector<BVHReference>& refs = *references_; int left_start = range.start(); int left_end = left_start; int right_start = range.end(); int right_end = range.end(); BoundBox left_bounds = BoundBox::empty; BoundBox right_bounds = BoundBox::empty; for(int i = left_end; i < right_start; i++) { if(refs[i].bounds().max[this->dim] <= this->pos) { /* entirely on the left-hand side */ left_bounds.grow(refs[i].bounds()); swap(refs[i], refs[left_end++]); } else if(refs[i].bounds().min[this->dim] >= this->pos) { /* entirely on the right-hand side */ right_bounds.grow(refs[i].bounds()); swap(refs[i--], refs[--right_start]); } } /* Duplicate or unsplit references intersecting both sides. * * Duplication happens into a temporary pre-allocated vector in order to * reduce number of memmove() calls happening in vector.insert(). */ vector<BVHReference>& new_refs = storage_->new_references; new_refs.clear(); new_refs.reserve(right_start - left_end); while(left_end < right_start) { /* split reference. */ BVHReference lref, rref; split_reference(*builder, lref, rref, refs[left_end], this->dim, this->pos); /* compute SAH for duplicate/unsplit candidates. */ BoundBox lub = left_bounds; // Unsplit to left: new left-hand bounds. BoundBox rub = right_bounds; // Unsplit to right: new right-hand bounds. BoundBox ldb = left_bounds; // Duplicate: new left-hand bounds. BoundBox rdb = right_bounds; // Duplicate: new right-hand bounds. lub.grow(refs[left_end].bounds()); rub.grow(refs[left_end].bounds()); ldb.grow(lref.bounds()); rdb.grow(rref.bounds()); float lac = builder->params.primitive_cost(left_end - left_start); float rac = builder->params.primitive_cost(right_end - right_start); float lbc = builder->params.primitive_cost(left_end - left_start + 1); float rbc = builder->params.primitive_cost(right_end - right_start + 1); float unsplitLeftSAH = lub.safe_area() * lbc + right_bounds.safe_area() * rac; float unsplitRightSAH = left_bounds.safe_area() * lac + rub.safe_area() * rbc; float duplicateSAH = ldb.safe_area() * lbc + rdb.safe_area() * rbc; float minSAH = min(min(unsplitLeftSAH, unsplitRightSAH), duplicateSAH); if(minSAH == unsplitLeftSAH) { /* unsplit to left */ left_bounds = lub; left_end++; } else if(minSAH == unsplitRightSAH) { /* unsplit to right */ right_bounds = rub; swap(refs[left_end], refs[--right_start]); } else { /* duplicate */ left_bounds = ldb; right_bounds = rdb; refs[left_end++] = lref; new_refs.push_back(rref); right_end++; } } /* Insert duplicated references into actual array in one go. */ if(new_refs.size() != 0) { refs.insert(refs.begin() + (right_end - new_refs.size()), new_refs.begin(), new_refs.end()); } left = BVHRange(left_bounds, left_start, left_end - left_start); right = BVHRange(right_bounds, right_start, right_end - right_start); }
void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, int i) { for(uint j = 0; j < mesh->triangles.size(); j++) { Mesh::Triangle t = mesh->triangles[j]; BoundBox bounds = BoundBox::empty; for(int k = 0; k < 3; k++) { float3 co = mesh->verts[t.v[k]]; bounds.grow(co); } if(bounds.valid()) { references.push_back(BVHReference(bounds, j, i, ~0)); root.grow(bounds); center.grow(bounds.center2()); } } for(uint j = 0; j < mesh->curves.size(); j++) { Mesh::Curve curve = mesh->curves[j]; for(int k = 0; k < curve.num_keys - 1; k++) { BoundBox bounds = BoundBox::empty; float3 co[4]; co[0] = mesh->curve_keys[max(curve.first_key + k - 1,curve.first_key)].co; co[1] = mesh->curve_keys[curve.first_key + k].co; co[2] = mesh->curve_keys[curve.first_key + k + 1].co; co[3] = mesh->curve_keys[min(curve.first_key + k + 2, curve.first_key + curve.num_keys - 1)].co; float3 lower; float3 upper; curvebounds(&lower.x, &upper.x, co, 0); curvebounds(&lower.y, &upper.y, co, 1); curvebounds(&lower.z, &upper.z, co, 2); float mr = max(mesh->curve_keys[curve.first_key + k].radius, mesh->curve_keys[curve.first_key + k + 1].radius); bounds.grow(lower, mr); bounds.grow(upper, mr); if(bounds.valid()) { references.push_back(BVHReference(bounds, j, i, k)); root.grow(bounds); center.grow(bounds.center2()); } } } }
void Shadows::update(Settings *settings, FRMMATRIX4X4& projIn, FRMMATRIX4X4& ModelviewIn, float* fv3SunDirIn) { direction = FRMVECTOR3(fv3SunDirIn[0], fv3SunDirIn[1], fv3SunDirIn[2]); // update pssm matrices float znear = 1.0f; float zfar = 250.0f; float shadowRange = 200.0f; float shadow_distribute = 0.1f;//25f; FRMMATRIX4X4 invProj; inverse( (float *)&invProj, (float *)&projIn ); //hack in a fast inverse FRMMATRIX4X4 imodelview; inverse((float *)& imodelview, (float *)& ModelviewIn);//inverse(mat4(fMat4ModelviewIn));//inverse(camera->getModelview()); // ortho basis (incorrect solution for vertical direction) FRMVECTOR3 side = FrmVector3Normalize (FrmVector3Cross ( FRMVECTOR3(0.0f,0.0f,1.0f), direction)); FRMVECTOR3 up = FrmVector3Normalize (FrmVector3Cross (direction, side)); //vec3 side = normalize(cross(direction, vec3(0.0f,0.0f,1.0f))); //vec3 up = normalize(cross(direction, side)); // bound frustum points FRMVECTOR3 points[8] = { FRMVECTOR3(-1.0f,-1.0f,-1.0f), FRMVECTOR3(1.0f,-1.0f,-1.0f), FRMVECTOR3(-1.0f,1.0f,-1.0f), FRMVECTOR3(1.0f,1.0f,-1.0f), FRMVECTOR3(-1.0f,-1.0f, 1.0f), FRMVECTOR3(1.0f,-1.0f, 1.0f), FRMVECTOR3(-1.0f,1.0f, 1.0f), FRMVECTOR3(1.0f,1.0f, 1.0f), }; // world space bound frustum points for(int i = 0; i < 8; i++) { FRMVECTOR4 point = FrmVector4Transform( FRMVECTOR4( points[i].x, points[i].y, points[i].z, 1.0f), invProj );// mat4((float *)& invProj ) * vec4(points[i]); points[i] = FRMVECTOR3( point.x, point.y, point.z ) / point.w; } // world space bound frustum directions FRMVECTOR3 directions[4]; for(int i = 0; i < 4; i++) { directions[i] = FrmVector3Normalize( points[i + 4] - points[i]); } // split bound frustum for(int i = 0; i < 4; i++) { float k0 = (float)(i + 0) / 4; float k1 = (float)(i + 1) / 4; float fmin = FrmLerp(shadow_distribute, znear * powf(zfar / znear,k0),znear + (zfar - znear) * k0); float fmax = FrmLerp(shadow_distribute, znear * powf(zfar / znear,k1),znear + (zfar - znear) * k1); // none flickering removal if( settings->getFlickering() == Settings::FLICKERING_NONE) { BoundBox bb; for(int j = 0; j < 4; j++) { bb.expand(points[j] + (directions[j] * fmin)); bb.expand(points[j] + (directions[j] * fmax)); } BoundSphere bs(bb); //save out radius squared spheres[i] = FRMVECTOR4( FrmVector3TransformCoord( bs.getCenter(), imodelview), bs.getRadius() * bs.getRadius()); FRMVECTOR3 target = FrmVector3TransformCoord( bs.getCenter(), imodelview ); // This offset is applied to prevent far-plane clipping float zFarOffset = 10.0f; ortho( (float*)&projections[i], bs.getRadius(),-bs.getRadius(),bs.getRadius(),-bs.getRadius(), 0.1f, shadowRange - zFarOffset); modelviews[i] = FrmMatrixLookAtRH(target + (direction * shadowRange / 2.0f),target - (direction * shadowRange / 2.0f),up); } // exact flickering removal else { BoundBox bb; for(int j = 0; j < 4; j++) { bb.expand(points[j] + (directions[j] * fmin)); bb.expand(points[j] + (directions[j] * fmax)); } BoundSphere bs(bb); //save out radius squared spheres[i] = FRMVECTOR4( FrmVector3TransformCoord( bs.getCenter(), imodelview ), bs.getRadius() * bs.getRadius()); float half_size = size / 2.0f; FRMVECTOR3 target = FrmVector3TransformCoord( bs.getCenter(), imodelview ); float x = ceilf( FrmVector3Dot(target,up) * half_size / bs.getRadius()) * bs.getRadius() / half_size; float y = ceilf( FrmVector3Dot(target,side) * half_size / bs.getRadius()) * bs.getRadius() / half_size; target = up * x + side * y + (direction * FrmVector3Dot(target,direction)); // This offset is applied to prevent far-plane clipping float zFarOffset = 10.0f; ortho( (float*)&projections[i],bs.getRadius(),-bs.getRadius(),bs.getRadius(),-bs.getRadius(), 0.1f, shadowRange - zFarOffset); modelviews[i] = FrmMatrixLookAtRH(target + (direction * shadowRange / 2.0f), target - (direction * shadowRange / 2.0f),up); } // Flip the texture coordinates for D3D int flipped = 1; modelviewprojections[i] = FrmMatrixMultiply( modelviews[i], projections[i]); if(settings->getTechnique() == Settings::TECHNIQUE_ATLAS) { modelviewprojections[i] = FrmMatrixMultiply( FrmMatrixMultiply( FrmMatrixMultiply( modelviewprojections[i], FrmMatrixScale(0.25f,(flipped) ? -0.25f : 0.25f,0.5f) ), FrmMatrixTranslate(0.25f,0.25f,0.5f)), FrmMatrixTranslate(0.5f * (i % 2),0.5f * (i / 2),0.0f)); } else { modelviewprojections[i] = FrmMatrixMultiply( FrmMatrixMultiply( modelviewprojections[i], FrmMatrixScale(0.5f,(flipped) ? -0.5f : 0.5f,0.5f)), FrmMatrixTranslate(0.5f,0.5f,0.5f)); } FRMMATRIX4X4 invModel; inverse((float *)& invModel, (float *)& modelviews[i]); offsets[i] = FRMVECTOR3( invModel.M(3, 0), invModel.M(3, 1), invModel.M(3, 2)); } }
bool bounds(const iXY& loc) const { return( bbox.bounds( location, loc ) ); }
void BVH8::refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility) { if (leaf) { int4 *data = &pack.leaf_nodes[idx]; int4 c = data[0]; /* Refit leaf node. */ for (int prim = c.x; prim < c.y; prim++) { int pidx = pack.prim_index[prim]; int tob = pack.prim_object[prim]; Object *ob = objects[tob]; if (pidx == -1) { /* Object instance. */ bbox.grow(ob->bounds); } else { /* Primitives. */ const Mesh *mesh = ob->mesh; if (pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) { /* Curves. */ int str_offset = (params.top_level) ? mesh->curve_offset : 0; Mesh::Curve curve = mesh->get_curve(pidx - str_offset); int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]); curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox); visibility |= PATH_RAY_CURVE; /* Motion curves. */ if (mesh->use_motion_blur) { Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if (attr) { size_t mesh_size = mesh->curve_keys.size(); size_t steps = mesh->motion_steps - 1; float3 *key_steps = attr->data_float3(); for (size_t i = 0; i < steps; i++) { curve.bounds_grow(k, key_steps + i * mesh_size, &mesh->curve_radius[0], bbox); } } } } else { /* Triangles. */ int tri_offset = (params.top_level) ? mesh->tri_offset : 0; Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset); const float3 *vpos = &mesh->verts[0]; triangle.bounds_grow(vpos, bbox); /* Motion triangles. */ if (mesh->use_motion_blur) { Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if (attr) { size_t mesh_size = mesh->verts.size(); size_t steps = mesh->motion_steps - 1; float3 *vert_steps = attr->data_float3(); for (size_t i = 0; i < steps; i++) { triangle.bounds_grow(vert_steps + i * mesh_size, bbox); } } } } } visibility |= ob->visibility; } float4 leaf_data[BVH_ONODE_LEAF_SIZE]; leaf_data[0].x = __int_as_float(c.x); leaf_data[0].y = __int_as_float(c.y); leaf_data[0].z = __uint_as_float(visibility); leaf_data[0].w = __uint_as_float(c.w); memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4) * BVH_ONODE_LEAF_SIZE); } else { float8 *data = (float8 *)&pack.nodes[idx]; bool is_unaligned = (__float_as_uint(data[0].a) & PATH_RAY_NODE_UNALIGNED) != 0; /* Refit inner node, set bbox from children. */ BoundBox child_bbox[8] = {BoundBox::empty, BoundBox::empty, BoundBox::empty, BoundBox::empty, BoundBox::empty, BoundBox::empty, BoundBox::empty, BoundBox::empty}; int child[8]; uint child_visibility[8] = {0}; int num_nodes = 0; for (int i = 0; i < 8; ++i) { child[i] = __float_as_int(data[(is_unaligned) ? 13 : 7][i]); if (child[i] != 0) { refit_node((child[i] < 0) ? -child[i] - 1 : child[i], (child[i] < 0), child_bbox[i], child_visibility[i]); ++num_nodes; bbox.grow(child_bbox[i]); visibility |= child_visibility[i]; } } if (is_unaligned) { Transform aligned_space[8] = {transform_identity(), transform_identity(), transform_identity(), transform_identity(), transform_identity(), transform_identity(), transform_identity(), transform_identity()}; pack_unaligned_node( idx, aligned_space, child_bbox, child, visibility, 0.0f, 1.0f, num_nodes); } else { pack_aligned_node(idx, child_bbox, child, visibility, 0.0f, 1.0f, num_nodes); } } }
ErrorCode BoundBox::update(Interface &iface, const Range& elems) { ErrorCode rval; bMin = CartVect(HUGE_VAL); bMax = CartVect(-HUGE_VAL); CartVect coords; EntityHandle const *conn, *conn2; int len, len2; Range::const_iterator i; // vertices const Range::const_iterator elem_begin = elems.lower_bound( MBEDGE ); for (i = elems.begin(); i != elem_begin; ++i) { rval = iface.get_coords( &*i, 1, coords.array() ); if (MB_SUCCESS != rval) return rval; update_min(coords.array()); update_max(coords.array()); } // elements with vertex-handle connectivity list const Range::const_iterator poly_begin = elems.lower_bound( MBPOLYHEDRON, elem_begin ); std::vector<EntityHandle> dum_vector; for (i = elem_begin; i != poly_begin; ++i) { rval = iface.get_connectivity( *i, conn, len, true, &dum_vector); if (MB_SUCCESS != rval) return rval; for (int j = 0; j < len; ++j) { rval = iface.get_coords( conn+j, 1, coords.array() ); if (MB_SUCCESS != rval) return rval; update_min(coords.array()); update_max(coords.array()); } } // polyhedra const Range::const_iterator set_begin = elems.lower_bound( MBENTITYSET, poly_begin ); for (i = poly_begin; i != set_begin; ++i) { rval = iface.get_connectivity( *i, conn, len, true ); if (MB_SUCCESS != rval) return rval; for (int j = 0; j < len; ++j) { rval = iface.get_connectivity( conn[j], conn2, len2 ); for (int k = 0; k < len2; ++k) { rval = iface.get_coords( conn2+k, 1, coords.array() ); if (MB_SUCCESS != rval) return rval; update_min(coords.array()); update_max(coords.array()); } } } // sets BoundBox box; for (i = set_begin; i != elems.end(); ++i) { Range tmp_elems; rval = iface.get_entities_by_handle(*i, tmp_elems); if (MB_SUCCESS != rval) return rval; rval = box.update(iface, tmp_elems); if (MB_SUCCESS != rval) return rval; update(box); } return MB_SUCCESS; }
void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, int i) { Attribute *attr_mP = NULL; if(mesh->has_motion_blur()) attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); for(uint j = 0; j < mesh->triangles.size(); j++) { Mesh::Triangle t = mesh->triangles[j]; BoundBox bounds = BoundBox::empty; PrimitiveType type = PRIMITIVE_TRIANGLE; t.bounds_grow(&mesh->verts[0], bounds); /* motion triangles */ if(attr_mP) { size_t mesh_size = mesh->verts.size(); size_t steps = mesh->motion_steps - 1; float3 *vert_steps = attr_mP->data_float3(); for(size_t i = 0; i < steps; i++) t.bounds_grow(vert_steps + i*mesh_size, bounds); type = PRIMITIVE_MOTION_TRIANGLE; } if(bounds.valid()) { references.push_back(BVHReference(bounds, j, i, type)); root.grow(bounds); center.grow(bounds.center2()); } } Attribute *curve_attr_mP = NULL; if(mesh->has_motion_blur()) curve_attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); for(uint j = 0; j < mesh->curves.size(); j++) { Mesh::Curve curve = mesh->curves[j]; PrimitiveType type = PRIMITIVE_CURVE; for(int k = 0; k < curve.num_keys - 1; k++) { BoundBox bounds = BoundBox::empty; curve.bounds_grow(k, &mesh->curve_keys[0], bounds); /* motion curve */ if(curve_attr_mP) { size_t mesh_size = mesh->curve_keys.size(); size_t steps = mesh->motion_steps - 1; float4 *key_steps = curve_attr_mP->data_float4(); for(size_t i = 0; i < steps; i++) curve.bounds_grow(k, key_steps + i*mesh_size, bounds); type = PRIMITIVE_MOTION_CURVE; } if(bounds.valid()) { int packed_type = PRIMITIVE_PACK_SEGMENT(type, k); references.push_back(BVHReference(bounds, j, i, packed_type)); root.grow(bounds); center.grow(bounds.center2()); } } } }
bool Object::loadFile(const std::string &path) { using namespace std; using namespace std::chrono; const time_point loadStartTime = high_resolution_clock::now(); ifstream ifs(path.c_str(), ifstream::in); if (!ifs.is_open()) { std::cerr << "File \"" << path << "\" could not be loaded." << std::endl; return false; } BoundBox boundBox; string line; vector<string> tokens; string mtlPath; string mtlName; while (ifs.good()) { tokens.clear(); getline(ifs, line); istringstream iss(line); copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter(tokens)); if (tokens.size() == 0 || tokens[0].size() == 0 || tokens[0][0] == '#') continue; if (tokens[0] == "v") { if (tokens.size() != 4) { cerr << path << ": Vertex command does not have correct number of components\n"; continue; } const Vector3f vertex(FromString<float>(tokens[1]), FromString<float>(tokens[2]), FromString<float>(tokens[3])); boundBox.extend(vertex); vertices.push_back(vertex); } else if (tokens[0] == "vt") { if (tokens.size() != 3) { cerr << path << ": Texture coordinate command does not have correct number of components\n"; continue; } const Vector2f texcoord(FromString<float>(tokens[1]), FromString<float>(tokens[2])); texcoords.push_back(texcoord); } else if (tokens[0] == "vn") { if (tokens.size() != 4) { cerr << path << ": Normal command does not have correct number of components\n"; continue; } const Vector3f normal(FromString<float>(tokens[1]), FromString<float>(tokens[2]), FromString<float>(tokens[3])); normals.push_back(normal); } else if (tokens[0] == "f") { Face face = { }; if (tokens.size() != 4 && tokens.size() != 5) { cerr << path << ": Face command does not have correct number of arguments\n"; continue; } face.isQuad = tokens.size() == 5; face.mat = MaterialLib::load(mtlPath, mtlName); const size_t slashesCount = count(tokens[1].begin(), tokens[1].end(), '/'); switch (slashesCount) { case 0: { for (size_t i = 0; i < 3U + face.isQuad; i++) { face.vertexIdxs[i] = indexFromStr(tokens[i + 1], vertices.size()) - 1; } faces.push_back(face); break; } case 1: { for (size_t i = 0; i < 3U + face.isQuad; i++) { const std::string &token = tokens[i + 1]; const size_t slashPos = token.find('/'); face.vertexIdxs[i] = indexFromStr(token.substr(0, slashPos), vertices.size()) - 1; if (token.size() - slashPos > 1) face.texcoordIdxs[i] = indexFromStr(token.substr(slashPos + 1), texcoords.size()) - 1; } faces.push_back(face); break; } case 2: { for (size_t i = 0; i < 3U + face.isQuad; i++) { const std::string &token = tokens[i + 1]; const size_t slash0Pos = token.find('/'); const size_t slash1Pos = token.find('/', slash0Pos + 1); face.vertexIdxs[i] = indexFromStr(token.substr(0, slash0Pos), vertices.size()) - 1; if (slash1Pos - slash0Pos > 1) face.texcoordIdxs[i] = indexFromStr(token.substr(slash0Pos + 1, slash1Pos - slash0Pos), texcoords.size()) - 1; if (token.size() - slash0Pos > 1) face.normalIdxs[i] = indexFromStr(token.substr(slash1Pos + 1), normals.size()) - 1; } faces.push_back(face); break; } default: cerr << path << ": Invalid face command in \"" << line << "\"\n"; break; } } else if (tokens[0] == "usemtl") { if (tokens.size() != 2) { cerr << path << ": Use material command does not have correct number of arguments\n"; continue; } mtlName = tokens[1]; } else if (tokens[0] == "mtllib") { if (tokens.size() != 2) { cerr << path << ": Material library command does not have correct number of arguments\n"; continue; } mtlPath = tokens[1]; } else { cerr << path << ": Unrecognized token \"" << tokens[0] << "\"\n"; } } ifs.close(); const time_point loadEndTime = high_resolution_clock::now(); cout << "File \"" << path << "\" loaded in " << DurationStr(loadStartTime, loadEndTime) << " with " << faces.size() << " face(s), " << normals.size() << " normal(s), and " << texcoords.size() << " texture coordinate(s).\n" << "\tBounding box: {" << boundBox.min().transpose() << ", " << boundBox.max().transpose() << "}\n"; return true; }
void BVHBuild::add_reference_object(BoundBox& root, BoundBox& center, Object *ob, int i) { references.push_back(BVHReference(ob->bounds, -1, i, 0)); root.grow(ob->bounds); center.grow(ob->bounds.center2()); }