bool UpdateTextured(Textured & t, Range & r){ //now, set new current_range: V3f center((r.min+r.max)/2); center.x = floorf(center.x); center.y = floorf(center.y); center.z = floorf(center.z); V3f half_diagonal(SIZE/2, SIZE/2, SIZE/2); t.current_range = Range(center-half_diagonal, center+half_diagonal); //fill it with a dummy texture for now (maybe //better done with an external class Range fast_volume_range(V3f(0,0,0), V3f(255,255,255)); unsigned char res; V3f c(t.current_range.min); //start for(int x = 0; x < SIZE; x++) for(int y = 0; y < SIZE; y++) for(int z = 0; z < SIZE; z++){ V3f cur(c.x+x, c.y+y, c.z+z); if(t.texturing_fastvolume){ res = (unsigned char)t.texturing_fastvolume->\ SampleCentered((int)cur.x%255, (int)cur.y%255, (int)cur.z%255); //Color conversion. int r = res * 3; r=(r<0)?0:(r>255?255:r); int g = (res - 80) * 3; g=(g<0)?0:(g>255?255:g); int b = (res - 160) * 3; b=(b<0)?0:(b>255?255:b); ((BYTE)t.data)[Offset(x,y,z)] = r; ((BYTE)t.data)[Offset(x,y,z)+1] = g; ((BYTE)t.data)[Offset(x,y,z)+2] = b; ((BYTE)t.data)[Offset(x,y,z)+3] = 255; }else{ bool line_hit = !((int)cur.x % 10) || !((int)cur.y % 10) || !((int)cur.z % 10); ((BYTE)t.data)[Offset(x,y,z)] = line_hit?30:300; ((BYTE)t.data)[Offset(x,y,z)+1] =line_hit?70:0; ((BYTE)t.data)[Offset(x,y,z)+2] =line_hit?300:30; ((BYTE)t.data)[Offset(x,y,z)+3] = 200; }; }; //ready; now load the texture UploadTexture(t.data); return true; };
TEST(MAIN, RangeExpand){ Range one(V3f(0,0,0), V3f(1,1,1)); //start const V3f pnt(100, -100, -100); const V3f out(100.1, -100.1, -100.1); const V3f in(99.9, -99.9, -99.9); Range expanded( (ExpandRange(one, pnt)) ); EXPECT_TRUE(ContainsPoint(expanded, pnt)); EXPECT_FALSE(ContainsPoint(expanded, out)); EXPECT_TRUE(ContainsPoint(expanded, in)); };
V3f direction (const Box2i &dataWindow, const V2f &pixelPosition) { V2f ll = latLong (dataWindow, pixelPosition); return V3f (sin (ll.y) * cos (ll.x), sin (ll.x), cos (ll.y) * cos (ll.x)); }
//-***************************************************************************** void MeshDrwHelper::updateNormals( V3fArraySamplePtr iN ) { if ( !m_valid || !m_meshP ) { makeInvalid(); return; } //std::cout << "normals - " << m_name << std::endl; // Now see if we need to calculate normals. if ( ( m_meshN && iN == m_meshN ) )//|| // ( !iN && m_customN.size() > 0 ) ) { return; } size_t numPoints = m_meshP->size(); m_meshN = iN; m_customN.clear(); // Right now we only handle "vertex varying" normals, // which have the same cardinality as the points if ( !m_meshN || m_meshN->size() != numPoints ) { // Make some custom normals. m_meshN.reset(); m_customN.resize( numPoints ); std::fill( m_customN.begin(), m_customN.end(), V3f( 0.0f ) ); //std::cout << "Recalcing normals for object: " // << m_host.name() << std::endl; for ( size_t tidx = 0; tidx < m_triangles.size(); ++tidx ) { const Tri &tri = m_triangles[tidx]; const V3f &A = (*m_meshP)[tri[0]]; const V3f &B = (*m_meshP)[tri[1]]; const V3f &C = (*m_meshP)[tri[2]]; V3f AB = B - A; V3f AC = C - A; V3f wN = AB.cross( AC ); m_customN[tri[0]] += wN; m_customN[tri[1]] += wN; m_customN[tri[2]] += wN; } // Normalize normals. for ( size_t nidx = 0; nidx < numPoints; ++nidx ) { m_customN[nidx].normalize(); } } }
MeshModel::MeshModel(GLfloat x,GLfloat y,GLfloat z, vector<V3f> &mv,vector<int> &mvi){ textured=false; for(int i=0; i<mv.size();i++) v.push_back(V3f(mv[i].x+x,mv[i].y+y,mv[i].z+z)); for(int i=0; i<mvi.size(); i+=3) vi.push_back(V3i(mvi[i],mvi[i+1],mvi[i+2])); calcFaceNormals(); calcVertexNormalsAverage(); calcVertexNormalsWeight(); }
MeshPlane::MeshPlane(GLfloat x, GLfloat y, GLfloat z, GLfloat x_len, GLfloat y_len, int x_tiles, int y_tiles){ textured=false; for(int i = 0; i<=x_tiles; i++) for(int j = 0; j<=y_tiles; j++) v.push_back(V3f(i*x_len+x,y, j*y_len+z)); for(int i = 1; i<v.size()-y_tiles-1; i++){ if(i%(y_tiles+1)!=0){ vi.push_back(V3i(i-1,i,i+y_tiles+1)); vi.push_back(V3i( i-1,i+y_tiles+1, i+y_tiles)); } } calcFaceNormals(); calcVertexNormalsAverage(); calcVertexNormalsWeight(); }
// update the trackball state using the current mouse state void Trackball::Update() { V3f *v; // SPIN+DRAG (first two buttons) translates the origin of rotation if (mouse.buttonsPressed == SPIN+DRAG) { v = &p3f_origin; mouse.buttonsPressed = DRAG; } else v = &v3f_trans; // If the user drags the mouse, Spin or [O]Trans are updated. If no // mouse buttons are pressed, just keep on applying the previous spin // rotation, over and over. switch (mouse.buttonsPressed) { case SPIN: Spin(); // updates Spin, which we then apply. qRot = qSpin * qRot; isChanged = true; break; case DRAG: //qRot = qSpin * qRot; *v += V3f(mouse.dx, mouse.dy, 0.); isChanged = true; break; case ZOOM: //qRot = qSpin * qRot; scale *= 1+.001*(mouse.du+mouse.dv); isChanged = true; break; case SPIN+ZOOM: v3f_trans (0,0,0); qSpin(1,0,0,0); p3f_origin(0,0,0); qRot (1,0,0,0); break; case DRAG+ZOOM: scale=1; break; case SPIN+DRAG+ZOOM: v3f_trans (0,0,0); qSpin(1,0,0,0); p3f_origin(0,0,0); qRot (1,0,0,0); scale=1; break; default: //qRot = qSpin * qRot; break; } transformed = !isChanged; } // Update
/// Create an octree over the given set of points with position P /// /// The points for consideration in the current node are the set /// P[inds[beginIndex..endIndex]]; the tree building process sorts the inds /// array in place so that points for the output leaf nodes are held in /// the range P[inds[node.beginIndex, node.endIndex)]]. center is the central /// split point for splitting children of the current node; radius is the /// current node radius measured along one of the axes. static OctreeNode* makeTree(int depth, size_t* inds, size_t beginIndex, size_t endIndex, const V3f* P, const V3f& center, float halfWidth, ProgressFunc& progressFunc) { OctreeNode* node = new OctreeNode(center, halfWidth); const size_t pointsPerNode = 100000; // Limit max depth of tree to prevent infinite recursion when // greater than pointsPerNode points lie at the same position in // space. floats effectively have 24 bit of precision in the // mantissa, so there's never any point splitting more than 24 times. const int maxDepth = 24; size_t* beginPtr = inds + beginIndex; size_t* endPtr = inds + endIndex; if (endIndex - beginIndex <= pointsPerNode || depth >= maxDepth) { // Leaf node: set up indices into point list std::random_shuffle(beginPtr, endPtr); for (size_t i = beginIndex; i < endIndex; ++i) node->bbox.extendBy(P[inds[i]]); node->beginIndex = beginIndex; node->endIndex = endIndex; progressFunc(endIndex - beginIndex); return node; } // Partition points into the 8 child nodes size_t* childRanges[9] = {0}; multi_partition(beginPtr, endPtr, OctreeChildIdx(P, center), &childRanges[1], 8); childRanges[0] = beginPtr; // Recursively generate child nodes float h = halfWidth/2; for (int i = 0; i < 8; ++i) { size_t childBeginIndex = childRanges[i] - inds; size_t childEndIndex = childRanges[i+1] - inds; if (childEndIndex == childBeginIndex) continue; V3f c = center + V3f((i % 2 == 0) ? -h : h, ((i/2) % 2 == 0) ? -h : h, ((i/4) % 2 == 0) ? -h : h); node->children[i] = makeTree(depth+1, inds, childBeginIndex, childEndIndex, P, c, h, progressFunc); node->bbox.extendBy(node->children[i]->bbox); } return node; }
void AcesInputFile::readPixels (int scanLine1, int scanLine2) { // // Copy the pixels from the RgbaInputFile into the frame buffer. // _data->rgbaFile->readPixels (scanLine1, scanLine2); // // If the RGB space of the input file is not the same as the ACES // RGB space, then the pixels in the frame buffer must be transformed // into the ACES RGB space. // if (!_data->mustConvertColor) return; int minY = min (scanLine1, scanLine2); int maxY = max (scanLine1, scanLine2); for (int y = minY; y <= maxY; ++y) { Rgba *base = _data->fbBase + _data->fbXStride * _data->minX + _data->fbYStride * y; for (int x = _data->minX; x <= _data->maxX; ++x) { V3f aces = V3f (base->r, base->g, base->b) * _data->fileToAces; base->r = aces[0]; base->g = aces[1]; base->b = aces[2]; base += _data->fbXStride; } } }
MeshPlane::MeshPlane(GLfloat x, GLfloat y, GLfloat z, GLfloat x_len, GLfloat y_len, int x_tiles, int y_tiles, GLuint texid){ MeshPlane::texid=texid; textured=true; t.push_back(V2f(0,0)); t.push_back(V2f(0,1)); t.push_back(V2f(1,1)); t.push_back(V2f(1,0)); for(int i = 0; i<=x_tiles; i++) for(int j = 0; j<=y_tiles; j++) v.push_back(V3f(i*x_len+x,y, j*y_len+z)); for(int i = 1; i<v.size()-y_tiles-1; i++){ if(i%(y_tiles+1)!=0){ vi.push_back(V3i(i-1,i,i+y_tiles+1)); ti.push_back(V3i(0,1,2)); vi.push_back(V3i( i-1,i+y_tiles+1, i+y_tiles)); ti.push_back(V3i(0,2,3)); } } calcFaceNormals(); calcVertexNormalsAverage(); calcVertexNormalsWeight(); }
V3f Y(){return V3f(ex.y, ey.y, ez.y);};
// Test loading of volume TEST(MAIN, RangeBasic){ Range one(V3f(0,0,0), V3f(1,1,1)); //start Range inside(V3f(0.1,0.1,0.1), V3f(0.9,0.9,0.9)); Range intersecting(V3f(0.1,0.1,0.1), V3f(0.9,5,0.9)); Range outside(V3f(1.1,-2,3), V3f(1.2,-1,3.8)); EXPECT_TRUE(ContainsPoint(one, V3f(0.5, 0.5, 0.5))); // Some common cases EXPECT_FALSE(ContainsPoint(one, V3f(1.1, 0.5, 0.5))); EXPECT_FALSE(ContainsPoint(one, V3f(-0.1, 0.5, 0.5))); EXPECT_FALSE(ContainsPoint(one, V3f(0.5, 1.1, 0.5))); EXPECT_FALSE(ContainsPoint(one, V3f(0.5, -0.1, 0.5))); EXPECT_FALSE(ContainsPoint(one, V3f(0.5, 0.5, 1.1))); EXPECT_FALSE(ContainsPoint(one, V3f(0.5, 0.5, -0.1))); EXPECT_TRUE(ContainsRange(one, inside)); EXPECT_TRUE(IntersectsRange(one, intersecting)); EXPECT_FALSE(ContainsRange(one, intersecting)); EXPECT_FALSE(ContainsRange(one, outside)); };
int mapBranches (V3f pos) { string sline; int axis,nn, ln, descend; //for the python section to get axis lengths FILE *fp; char line[256]; // ifstream mtg; // file containg the details for bulding the Lsystem bool foundStart; char * cstr, *pch; int retValue=1; int nodenum, curBranch,nb,curOrder; float bx,by,bz; int loc; int branchLevel [10]; //keeps track of the branch level we are on for(int i=0;i<10;i++){ branchLevel[i]=0; } foundStart=false; mtg.open(mtgName, ifstream::in); if(mtg.good()){ Printf("all good with %s in mapBranches\n",mtgName); } else { Printf("%s NOT good in mapBranches ", mtgName); if(mtg.fail()){ Printf("it failed\n"); } if(mtg.eof()){ Printf("it eof\n"); } if(mtg.bad()){ Printf("it bad\n"); } } /*use python to create nbranches.txt which is a list of nodes for S types and the length of the axis*/ char cmdLine[256]; sprintf(cmdLine,"%s combined.py %s",PYTHON,mtgName); #ifdef _MSC_VER fp = _popen(cmdLine, "r"); #else fp = popen(cmdLine, "r"); #endif while ( fgets( line, sizeof line, fp)) { Printf("%s", line); } #ifdef _MSC_VER _pclose(fp); #else pclose(fp); #endif fp=fopen("nbranches.txt","r"); while (fscanf(fp,"%i %i %i", &axis, &loc, &nn) != EOF) { //fprintf(stdout,"%i %i\n",axis,nn); nodesPerAxis[axis]=nn; } fclose(fp); fp=fopen("parents.txt","r"); while (fscanf(fp,"%i %i", &nn, &axis) != EOF) { ParentOfNode[nn]=axis; } fclose(fp); fp=fopen("lastNodes.txt","r"); while (fscanf(fp,"%i %i %i", &axis, &ln, &nb) != EOF) { //check=LastNodeOfAxis.find(axis) -> second; //if(check==0) LastNodeOfAxis[axis]=ln; } fclose(fp); fp=fopen("branchXYZ.txt","r"); while (fscanf(fp,"%i %i %f %f %f", &axis, &loc, &bx, &by, &bz) != EOF) { sxXYZ[loc]=V3f(bx+pos.x,by+pos.y,bz+pos.z); //Printf("%i %.2f %.2f %.2f\n",axis,bx,by,bz); } fclose(fp); /*----------------------------------*/ while (!mtg.eof() && mtg.good() ){ getline(mtg,sline); if(foundStart){ cstr = new char [sline.size()+1]; if(foundStart){ strcpy (cstr, sline.c_str()); pch = strtok (cstr,"\t"); int ic=1; while (pch != NULL) { pch = strtok (NULL, "\t"); if(pch!= NULL) if(ic==nodeN){nodenum=atoi(pch);} if(ic==levelN){curOrder=atoi(pch)-1;} ic++; } } if(sline.find("P1") != -1){ // start of plant //get the current branch node number // and store this so it can be used to map branches from this point curBranch=nodenum; } if(sline.find("^/N") != -1 ) { curBranch=branchLevel[curOrder-1]; nb=nbranches.find(curBranch)->second; nb++; nbranches[curBranch]=nb; // if(curBranch==27) // Printf("Branch %i at %i ^/N= %i\n",nb,curBranch,nodenum); } if(sline.find("^<N") != -1 ) { branchLevel[curOrder]=nodenum; } } else { // !foundStart //Printf("%s\n",sline.c_str()); if((int)sline.find("ENTITY-CODE") != -1){ foundStart=true; Printf("Found start of data\n"); //workout the column numbers for the entities cstr = new char [sline.size()+1]; strcpy (cstr, sline.c_str()); pch = strtok (cstr,"\t"); xN=0; yN=0; zN=0; widthN=0; lenN=0; typeN=0; nodeN=0; levelN=0; //order char test[10]; int ic=1; while (pch != NULL) { pch = strtok (NULL, "\t"); if(pch != NULL) { sprintf(test,"%s",pch); //Printf("%s| %s: %i\n",test,pch,ic); if(strcmp("XX",test) ==0) {xN=ic;} if(strcmp("YY",test) ==0){yN=ic;} if(strcmp("ZZ",test) ==0){zN=ic;} if(strcmp("TopDia",test) ==0){widthN=ic;} if(strcmp("ILength",test) ==0){lenN=ic;} if(strcmp("NType",test) ==0){typeN=ic;} if(strcmp("Node",test) ==0){nodeN=ic;} if(strcmp("Level",test) ==0){levelN=ic;} ic++; } } Printf("Test we have all the data\n"); if( xN==0 || yN==0 || zN==0 || widthN==0 || lenN==0 || typeN==0 || nodeN==0 || levelN==0){ Printf("Not all of the the required features were found\n"); Printf("%i %i %i %i %i %i %i %i \n",xN,yN,zN,widthN,lenN,typeN,nodeN, levelN); retValue=1; } else { Printf("Found all the bits we want\n"); Printf("%i %i %i %i %i %i %i %i \n",xN,yN,zN,widthN,lenN,typeN,nodeN, levelN); retValue=0; } } } } Printf("Finished with ret = %i\n\n",retValue); mtg.close(); return retValue; }
int runScene(Drawable & scene){ glfwInit(); if( !glfwOpenWindow( 500, 500, 0,0,0,0, 16,0, GLFW_WINDOW ) ) { glfwTerminate(); } glfwSetWindowTitle( "3D" ); glfwEnable( GLFW_STICKY_KEYS ); glfwEnable( GLFW_MOUSE_CURSOR ); glfwDisable( GLFW_AUTO_POLL_EVENTS ); setupCallbacks(); do //Main Loop. { setupProjection(); // stereo_state.Ping(); projection_state.Load(); float zoom=2.0; glScalef(zoom*2.0/256.0, zoom*2.0/256.0, zoom*2.0/256.0); glDisable (GL_BLEND); glDisable(GL_LIGHTING); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); setupModelview(); /* Temporary light insertion: */ navigator.Draw(); //reference plane DrawPlane(V3f(0,0,0), V3f(20,0,0), V3f(0,20,0), 5); SetupLighting(); scene.Draw(); //Clear modified mouse state. mouse_state.Moved(); glfwSwapBuffers(); if(!stereo_state.enabled){ glfwWaitEvents(); }else{ glfwPollEvents(); glfwSleep(0.01); //just sleep. }; navigator.idle_move(); } while(!glfwGetKey( GLFW_KEY_ESC ) && glfwGetWindowParam( GLFW_OPENED )); return true; };
Navigator(): cur_x(0), cur_y(0), center(V3f(0,0,0)), dx(V3f(1,0,0)), dy(V3f(0,1,0)){};
V3f Z(){return V3f(ex.z, ey.z, ez.z);};
V3f X(){return V3f(ex.x, ey.x, ez.x);};
static void renderNode(IntegratorT& integrator, V3f P, V3f N, float cosConeAngle, float sinConeAngle, float maxSolidAngle, int dataSize, const PointOctree::Node* node) { // This is an iterative traversal of the point hierarchy, since it's // slightly faster than a recursive traversal. // // The max required size for the explicit stack should be < 200, since // tree depth shouldn't be > 24, and we have a max of 8 children per node. const PointOctree::Node* nodeStack[200]; nodeStack[0] = node; int stackSize = 1; while(stackSize > 0) { node = nodeStack[--stackSize]; { // Examine node bound and cull if possible // TODO: Reinvestigate using (node->aggP - P) with spherical harmonics V3f c = node->center - P; if(sphereOutsideCone(c, c.length2(), node->boundRadius, N, cosConeAngle, sinConeAngle)) continue; } float r = node->aggR; V3f p = node->aggP - P; float plen2 = p.length2(); // Examine solid angle of interior node bounding sphere to see whether we // can render it directly or not. // // TODO: Would be nice to use dot(node->aggN, p.normalized()) in the solid // angle estimation. However, we get bad artifacts if we do this naively. // Perhaps with spherical harmoics it'll be better. float solidAngle = M_PI*r*r / plen2; if(solidAngle < maxSolidAngle) { integrator.setPointData(reinterpret_cast<const float*>(&node->aggCol)); renderDisk(integrator, N, p, node->aggN, r, cosConeAngle, sinConeAngle); } else { // If we get here, the solid angle of the current node was too large // so we must consider the children of the node. // // The render order is sorted so that points are rendered front to // back. This greatly improves the correctness of the hider. // // FIXME: The sorting procedure gets things wrong sometimes! The // problem is that points may stick outside the bounds of their octree // nodes. Probably we need to record all the points, sort, and // finally render them to get this right. if(node->npoints != 0) { // Leaf node: simply render each child point. std::pair<float, int> childOrder[8]; assert(node->npoints <= 8); for(int i = 0; i < node->npoints; ++i) { const float* data = &node->data[i*dataSize]; V3f p = V3f(data[0], data[1], data[2]) - P; childOrder[i].first = p.length2(); childOrder[i].second = i; } std::sort(childOrder, childOrder + node->npoints); for(int i = 0; i < node->npoints; ++i) { const float* data = &node->data[childOrder[i].second*dataSize]; V3f p = V3f(data[0], data[1], data[2]) - P; V3f n = V3f(data[3], data[4], data[5]); float r = data[6]; integrator.setPointData(data+7); renderDisk(integrator, N, p, n, r, cosConeAngle, sinConeAngle); } continue; } else { // Interior node: render children. std::pair<float, const PointOctree::Node*> children[8]; int nchildren = 0; for(int i = 0; i < 8; ++i) { PointOctree::Node* child = node->children[i]; if(!child) continue; children[nchildren].first = (child->center - P).length2(); children[nchildren].second = child; ++nchildren; } std::sort(children, children + nchildren); // Interior node: render each non-null child. Nodes we want to // render first must go onto the stack last. for(int i = nchildren-1; i >= 0; --i) nodeStack[stackSize++] = children[i].second; } } } }
bool PointArray::loadFile(QString fileName, size_t maxPointCount) { QTime loadTimer; loadTimer.start(); setFileName(fileName); // Read file into point data fields. Use very basic file type detection // based on extension. uint64_t totPoints = 0; Imath::Box3d bbox; V3d offset(0); V3d centroid(0); emit loadStepStarted("Reading file"); if (fileName.endsWith(".las") || fileName.endsWith(".laz")) { if (!loadLas(fileName, maxPointCount, m_fields, offset, m_npoints, totPoints, bbox, centroid)) { return false; } } else if (fileName.endsWith(".ply")) { if (!loadPly(fileName, maxPointCount, m_fields, offset, m_npoints, totPoints, bbox, centroid)) { return false; } } #if 0 else if (fileName.endsWith(".dat")) { // Load crappy db format for debugging std::ifstream file(fileName.toUtf8(), std::ios::binary); file.seekg(0, std::ios::end); totPoints = file.tellg()/(4*sizeof(float)); file.seekg(0); m_fields.push_back(GeomField(TypeSpec::vec3float32(), "position", totPoints)); m_fields.push_back(GeomField(TypeSpec::float32(), "intensity", totPoints)); float* position = m_fields[0].as<float>(); float* intensity = m_fields[1].as<float>(); for (size_t i = 0; i < totPoints; ++i) { file.read((char*)position, 3*sizeof(float)); file.read((char*)intensity, 1*sizeof(float)); bbox.extendBy(V3d(position[0], position[1], position[2])); position += 3; intensity += 1; } m_npoints = totPoints; } #endif else { // Last resort: try loading as text if (!loadText(fileName, maxPointCount, m_fields, offset, m_npoints, totPoints, bbox, centroid)) { return false; } } // Search for position field m_positionFieldIdx = -1; for (size_t i = 0; i < m_fields.size(); ++i) { if (m_fields[i].name == "position" && m_fields[i].spec.count == 3) { m_positionFieldIdx = (int)i; break; } } if (m_positionFieldIdx == -1) { g_logger.error("No position field found in file %s", fileName); return false; } m_P = (V3f*)m_fields[m_positionFieldIdx].as<float>(); setBoundingBox(bbox); setOffset(offset); setCentroid(centroid); emit loadProgress(100); g_logger.info("Loaded %d of %d points from file %s in %.2f seconds", m_npoints, totPoints, fileName, loadTimer.elapsed()/1000.0); if (totPoints == 0) { m_rootNode.reset(new OctreeNode(V3f(0), 1)); return true; } // Sort points into octree order emit loadStepStarted("Sorting points"); std::unique_ptr<size_t[]> inds(new size_t[m_npoints]); for (size_t i = 0; i < m_npoints; ++i) inds[i] = i; // Expand the bound so that it's cubic. Not exactly sure it's required // here, but cubic nodes sometimes work better the points are better // distributed for LoD, splitting is unbiased, etc. Imath::Box3f rootBound(bbox.min - offset, bbox.max - offset); V3f diag = rootBound.size(); float rootRadius = std::max(std::max(diag.x, diag.y), diag.z) / 2; ProgressFunc progressFunc(*this); m_rootNode.reset(makeTree(0, &inds[0], 0, m_npoints, &m_P[0], rootBound.center(), rootRadius, progressFunc)); // Reorder point fields into octree order emit loadStepStarted("Reordering fields"); for (size_t i = 0; i < m_fields.size(); ++i) { g_logger.debug("Reordering field %d: %s", i, m_fields[i]); reorder(m_fields[i], inds.get(), m_npoints); emit loadProgress(int(100*(i+1)/m_fields.size())); } m_P = (V3f*)m_fields[m_positionFieldIdx].as<float>(); return true; }
TEST(MAIN, DrawSphere){ DrawSphere a(V3f(0,0,0), 10, 8); Scene::run(a); };