void R3MeshSearchTree:: InsertFace(R3MeshFace *face) { // Check if face intersects box if (!R3Intersects(mesh, face, BBox())) return; // Create container R3MeshSearchTreeFace *face_container = new R3MeshSearchTreeFace(mesh, face); assert(face_container); // Insert face into root InsertFace(face_container, root, BBox(), 0); }
R3MeshSearchTree:: R3MeshSearchTree(R3Mesh *mesh) : mesh(mesh), nnodes(1), mark(1) { // Create root root = new R3MeshSearchTreeNode(NULL); assert(root); // Insert faces into tree for (int i = 0; i < mesh->NFaces(); i++) { R3MeshFace *face = mesh->Face(i); InsertFace(face); } }
cFontLoader::tDistanceFontHandle cFontLoader::LoadDFFFromMemory(cStringRef data) { AlignedBuffer<16> buffer; auto reader = cSerialization::ReaderCompressed(data, buffer); size_t face_length; reader.ReadSize(face_length); std::unique_ptr<cDistanceFieldFont> font; tFaceHandle face_handle = InsertFace(FreeTypeFace::FromReader(mLibrary, reader)); FreeTypeFace& face = TypeFace(face_handle); tDistanceFontHandle df_handle = InsertDistanceFont(cDistanceFieldFont::FromReader(*mFaces.back(), reader)); Log::Info("successfully loaded font: %s ", mDistanceFieldFonts.back()->FontName()); return df_handle; }
tFaceHandle cFontLoader::LoadFont(const Twine& filename) { return InsertFace( std::unique_ptr<FreeTypeFace>(new FreeTypeFace(mLibrary, filename))); }
FreeTypeFace& cFontLoader::DeSerializeFace(cStringRef data) { tFaceHandle handle = InsertFace( FreeTypeFace::FromData(mLibrary, data)); return *mFaces[handle]; }
void R3MeshSearchTree:: InsertFace(R3MeshSearchTreeFace *face, R3MeshSearchTreeNode *node, const R3Box& node_box, int depth) { // Check if face intersects box if (!R3Intersects(mesh, face->face, node_box)) return; // Check if interior node if (node->children[0]) { // Interior node -- Insert into children assert(node->children[1]); const R3Box& face_box = mesh->FaceBBox(face->face); if (face_box[RN_LO][node->split_dimension] <= node->split_coordinate) { R3Box node0_box(node_box); node0_box[RN_HI][node->split_dimension] = node->split_coordinate; InsertFace(face, node->children[0], node0_box, depth + 1); } if (face_box[RN_HI][node->split_dimension] >= node->split_coordinate) { R3Box node1_box(node_box); node1_box[RN_LO][node->split_dimension] = node->split_coordinate; InsertFace(face, node->children[1], node1_box, depth + 1); } } else { // Check face area RNScalar node_diagonal = node_box.DiagonalLength(); if (node_diagonal == 0) return; RNScalar node_area = node_diagonal * node_diagonal; RNScalar area_ratio = face->area / node_area; if ((area_ratio >= max_area_ratio) || (depth >= max_depth)) { // Face is too big/deep to be sorted into children, insert into big faces list node->big_faces.Insert(face); assert(face->reference_count >= 0); face->reference_count++; } else { // Leaf node -- Check if there is room for this face if (node->small_faces.NEntries() < max_faces_per_node) { // Simply insert face into list node->small_faces.Insert(face); face->reference_count++; } else { // Create two children node->children[0] = new R3MeshSearchTreeNode(node); node->children[1] = new R3MeshSearchTreeNode(node); node->split_dimension = node_box.LongestAxis(); node->split_coordinate = node_box.AxisCenter(node->split_dimension); nnodes += 2; // Re-insert faces into subtree InsertFace(face, node, node_box, depth+1); for (int i = 0; i < node->small_faces.NEntries(); i++) { InsertFace(node->small_faces[i], node, node_box, depth+1); } // Clear out faces from node that is now interior for (int i = 0; i < node->small_faces.NEntries(); i++) { assert(node->small_faces[i]->reference_count > 0); node->small_faces[i]->reference_count--; } node->small_faces.Empty(); } } } }