void ofxMarchingCubes::update(float _threshold, bool bCalcNormals){
	threshold = _threshold;
	numTriangles = 0;
	vertices.clear(); 
	normals.clear();
	int numPointsX = gridResX-1;;
	int numPointsY = gridResY-1;
	int numPointsZ = gridResZ-1;
	for(unsigned int i=0; i<numPointsX; ++i){
		for(unsigned int j=0; j<numPointsY; ++j){
			for(unsigned int k=0; k<numPointsZ; ++k){
				polygonise(i, j, k, bCalcNormals);
			}
		}
	}
}	
Пример #2
0
  std::vector<Primitive *> Particles::getSurfacePrims(double isolevel, double fStepSize, BSDF* bsdf) {
    std::vector<Primitive *> prims;
    double xmin = getParticlesAxisMin(0);
    double ymin = getParticlesAxisMin(1);
    double zmin = getParticlesAxisMin(2);
    double xmax = getParticlesAxisMax(0);
    double ymax = getParticlesAxisMax(1);
    double zmax = getParticlesAxisMax(2);
    int xsteps = (int)((xmax-xmin)/fStepSize);
    int ysteps = (int)((ymax-ymin)/fStepSize);
    int zsteps = (int)((zmax-zmin)/fStepSize);

    vector<vector<Index> > polygons;
    vector<Vector3D> vertexPositions;

    for (int ix = 0; ix <= xsteps; ix++)
      for (int iy = 0; iy <= ysteps; iy++)
        for (int iz = 0; iz <= zsteps; iz++) {
          double x1 = xmin+ix*fStepSize;
          double x2 = std::min(xmax, x1+fStepSize);
          double y1 = ymin+iy*fStepSize;
          double y2 = std::min(ymax, y1+fStepSize);
          double z1 = zmin+iz*fStepSize;
          double z2 = std::min(zmax, z1+fStepSize);

          GridCell grid = generateGridCell(x1,x2,y1,y2,z1,z2);
          std::vector<TriangleVertices *> triangles = polygonise(grid, isolevel);
          for (int i=0; i<triangles.size(); i++) {
            Vector3D p1 = triangles[i]->p[0];
            Vector3D p2 = triangles[i]->p[1];
            Vector3D p3 = triangles[i]->p[2];
            Vector3D n1 = getVertexNormal(p1);
            Vector3D n2 = getVertexNormal(p2);
            Vector3D n3 = getVertexNormal(p3);

            MarchingTriangle *tri = new MarchingTriangle(p1, p2, p3, n1, n2, n3, bsdf);
            prims.push_back(tri);
          }
    }
    return prims;
  }
Пример #3
0
/** 
	Uses modified marching cubes algorithm
*/
int Dataset::calculate_surface()
{
	Gridcell grid;
	int index, in,
		i,j,k;
	
	int num_triangles = 0, 
		new_triangles = 0, 
		*buffer_count;
		
	buffer_count = (int*) malloc(sizeof(int)*num_grains);
	if (buffer_count == NULL) { return 0; }	
	
	double sa = 0,
		   AB[3], AC[3], ABAC;
	
	Triangle *t;
			 
	bool already_marked;



	// For each grain allocate initial buffer and set surface count to zero
	//--------------------------------------------------
	for(i=0;i<num_grains;i++){

		if (grains[i].surface_triangles != NULL) {
			free(grains[i].surface_triangles);
		}
					
		grains[i].surface_triangles = (Triangle*) malloc(sizeof(Triangle)*TRIANGLE_BUFFER);
		if (grains[i].surface_triangles == NULL) { return 0; }
					
		grains[i].num_triangles = 0;
		buffer_count[i] = 1;
	}
	
	XYZ pi;
	
	int present[9];
	int num_present;

	present[0] = -1;

	// Cycle through each 'cube' in dataset and calculate the surface for 
	// each of the grains present in the cube. 
	//--------------------------------------------------
	for(index=0;index<nv;index++){
		
		if (index%1000 == 0) {  
			//#pragma omp critial(display)
			progress_callback((float)index / nv,"Calculating surfaces", false);
		}
		
		pi.x = (index % tx)-1;
		pi.y = (index/dy % ty)-1;
		pi.z = (index/dz % tz)-1;
		
		num_present = 1;
		
		for(j=0;j<8;j++) {
			grid.p[j].x = pi.x + grid_offset[j][X];
			grid.p[j].y = pi.y + grid_offset[j][Y];
			grid.p[j].z = pi.z + grid_offset[j][Z];
			
			if (grid.p[j].x<0       || grid.p[j].y<0       || grid.p[j].z<0 ||
				grid.p[j].x>=(tx-2) || grid.p[j].y>=(ty-2) || grid.p[j].z>=(tz-2)) { 
				grid.grain[j] = -1;
			} else {
				in = index - dz + grid_offset[j][X] + grid_offset[j][Y]*dy + grid_offset[j][Z]*dz;
				grid.grain[j] = data[in].grain;

				// Keep track of which grains are present
				//--------------------------------------------------
				if (data[in].grain >= 0) {
					already_marked = false;
					for(k=0;k<num_present;k++){
						if (data[in].grain == present[k]) {
							already_marked = true;
						}
					}
					if (!already_marked) {
						present[ num_present++ ] = data[in].grain;
					}
				}
			}
		}
		
		
		for(j=1;j<num_present;j++){
			num_triangles = grains[ present[j] ].num_triangles;
			
			// Make sure there's enough space in the buffer
			//--------------------------------------------------
			if(num_triangles+12 > buffer_count[ present[j] ]*TRIANGLE_BUFFER) {
				grains[ present[j] ].surface_triangles = (Triangle*) realloc(grains[ present[j] ].surface_triangles, sizeof(Triangle)*(++buffer_count[present[j]])*TRIANGLE_BUFFER);
				if (grains[ present[j] ].surface_triangles == NULL) { return 0; }
			}	
			
			new_triangles = polygonise(grid, present[j], grains[ present[j] ].surface_triangles+num_triangles);
			grains[ present[j] ].num_triangles += new_triangles;
		}
	}

	for(i=0;i<num_grains;i++){			
		
		sa = 0;	
		
		t = grains[i].surface_triangles;
		
		// Calculate surface area of grains
		//--------------------------------------------------
		for(j=0;j<grains[i].num_triangles;j++){
					
			AB[X] = (t->p[0].x - t->p[1].x)*(double)steps[X];
			AB[Y] = (t->p[0].y - t->p[1].y)*(double)steps[Y];
			AB[Z] = (t->p[0].z - t->p[1].z)*(double)steps[Z];
			
			AC[X] = (t->p[0].x - t->p[2].x)*(double)steps[X];
			AC[Y] = (t->p[0].y - t->p[2].y)*(double)steps[Y];
			AC[Z] = (t->p[0].z - t->p[2].z)*(double)steps[Z];
			
			ABAC = AB[X]*AC[X]+AB[Y]*AC[Y]+AB[Z]*AC[Z];
			
			sa += 0.5 * sqrt( (AB[X]*AB[X] + AB[Y]*AB[Y] + AB[Z]*AB[Z])*
							  (AC[X]*AC[X] + AC[Y]*AC[Y] + AC[Z]*AC[Z])-
							  ABAC*ABAC ); 

			t++;
								
		}
	
		grains[i].surface_area = (float) sa;
	}
	
	free(buffer_count);
	
	progress_callback(1,"Calculating grain surfaces", false);
}
//--------------------------------------------------------------------------------------------------
/// Generate surface representation of the specified cut plane
/// 
/// \note Will compute normals before returning geometry
//--------------------------------------------------------------------------------------------------
void StructGridCutPlane::computeCutPlane() 
{
    DebugTimer tim("StructGridCutPlane::computeCutPlane", DebugTimer::DISABLED);

    bool doMapScalar = false;
    if (m_mapScalarSetIndex != UNDEFINED_UINT && m_scalarMapper.notNull())
    {
        doMapScalar = true;
    }

    uint cellCountI = m_grid->cellCountI();
    uint cellCountJ = m_grid->cellCountJ();
    uint cellCountK = m_grid->cellCountK();

    // Clear any current data
    m_vertices.clear();
    m_vertexScalars.clear();
    m_triangleIndices.clear();
    m_meshLineIndices.clear();


    // The indexing conventions for vertices and 
    // edges used in the algorithm:
    //                                                                   edg   verts
    //      4-------------5                     *------4------*           0    0 - 1
    //     /|            /|                    /|            /|           1    1 - 2
    //    / |           / |                  7/ |          5/ |           2    2 - 3
    //   /  |          /  |      |z          /  8          /  9           3    3 - 0
    //  7-------------6   |      | /y       *------6------*   |           4    4 - 5
    //  |   |         |   |      |/         |   |         |   |           5    5 - 6
    //  |   0---------|---1      *---x      |   *------0--|---*           6    6 - 7
    //  |  /          |  /                 11  /         10  /            7    7 - 4
    //  | /           | /                   | /3          | /1            8    0 - 4
    //  |/            |/                    |/            |/              9    1 - 5
    //  3-------------2                     *------2------*              10    2 - 6
    //  vertex indices                       edge indices                11    3 - 7
    //                                                                 

    uint k;
    for (k = 0; k < cellCountK; k++)
    {
        uint j;
        for (j = 0; j < cellCountJ; j++)
        {
            uint i;
            for (i = 0; i < cellCountI; i++)
            {
                size_t cellIndex = m_grid->cellIndexFromIJK(i, j, k);

                Vec3d minCoord;
                Vec3d maxCoord;
                m_grid->cellMinMaxCordinates(cellIndex, &minCoord, &maxCoord);

                // Early reject for cells outside clipping box
                if (m_clippingBoundingBox.isValid())
                {
                    BoundingBox cellBB(minCoord, maxCoord);
                    if (!m_clippingBoundingBox.intersects(cellBB))
                    {
                        continue;
                    }
                }

                // Check if plane intersects this cell and skip if it doesn't
                if (!isCellIntersectedByPlane(m_plane, minCoord, maxCoord))
                {
                    continue;
                }

                GridCell cell;

                bool isClipped = false;
                if (m_clippingBoundingBox.isValid())
                {
                    if (!m_clippingBoundingBox.contains(minCoord) || !m_clippingBoundingBox.contains(maxCoord))
                    {
                        isClipped = true;

                        minCoord.x() = CVF_MAX(minCoord.x(), m_clippingBoundingBox.min().x());
                        minCoord.y() = CVF_MAX(minCoord.y(), m_clippingBoundingBox.min().y());
                        minCoord.z() = CVF_MAX(minCoord.z(), m_clippingBoundingBox.min().z());

                        maxCoord.x() = CVF_MIN(maxCoord.x(), m_clippingBoundingBox.max().x());
                        maxCoord.y() = CVF_MIN(maxCoord.y(), m_clippingBoundingBox.max().y());
                        maxCoord.z() = CVF_MIN(maxCoord.z(), m_clippingBoundingBox.max().z());
                    }
                }

                cell.p[0].set(minCoord.x(), maxCoord.y(), minCoord.z());
                cell.p[1].set(maxCoord.x(), maxCoord.y(), minCoord.z());
                cell.p[2].set(maxCoord.x(), minCoord.y(), minCoord.z());
                cell.p[3].set(minCoord.x(), minCoord.y(), minCoord.z());
                cell.p[4].set(minCoord.x(), maxCoord.y(), maxCoord.z());
                cell.p[5].set(maxCoord.x(), maxCoord.y(), maxCoord.z());
                cell.p[6].set(maxCoord.x(), minCoord.y(), maxCoord.z());
                cell.p[7].set(minCoord.x(), minCoord.y(), maxCoord.z());


                // Fetch scalar values
                double cellScalarValue = 0;
                if (doMapScalar)
                {
                    cellScalarValue = m_grid->cellScalar(m_mapScalarSetIndex, i, j, k);

                    // If we're doing node averaging we must populate grid cell with scalar values interpolated to the grid points
                    if (m_mapNodeAveragedScalars)
                    {
                        if (isClipped)
                        {
                            double scalarVal;
                            if (m_grid->pointScalar(m_mapScalarSetIndex, cell.p[0], &scalarVal)) cell.s[0] = scalarVal;
                            if (m_grid->pointScalar(m_mapScalarSetIndex, cell.p[1], &scalarVal)) cell.s[1] = scalarVal;
                            if (m_grid->pointScalar(m_mapScalarSetIndex, cell.p[2], &scalarVal)) cell.s[2] = scalarVal;
                            if (m_grid->pointScalar(m_mapScalarSetIndex, cell.p[3], &scalarVal)) cell.s[3] = scalarVal;
                            if (m_grid->pointScalar(m_mapScalarSetIndex, cell.p[4], &scalarVal)) cell.s[4] = scalarVal;
                            if (m_grid->pointScalar(m_mapScalarSetIndex, cell.p[5], &scalarVal)) cell.s[5] = scalarVal;
                            if (m_grid->pointScalar(m_mapScalarSetIndex, cell.p[6], &scalarVal)) cell.s[6] = scalarVal;
                            if (m_grid->pointScalar(m_mapScalarSetIndex, cell.p[7], &scalarVal)) cell.s[7] = scalarVal;
                        }
                        else
                        {
                            cell.s[0] = m_grid->gridPointScalar(m_mapScalarSetIndex, i,     j + 1, k);
                            cell.s[1] = m_grid->gridPointScalar(m_mapScalarSetIndex, i + 1, j + 1, k);
                            cell.s[2] = m_grid->gridPointScalar(m_mapScalarSetIndex, i + 1, j,     k);
                            cell.s[3] = m_grid->gridPointScalar(m_mapScalarSetIndex, i,     j,     k);
                            cell.s[4] = m_grid->gridPointScalar(m_mapScalarSetIndex, i,     j + 1, k + 1);
                            cell.s[5] = m_grid->gridPointScalar(m_mapScalarSetIndex, i + 1, j + 1, k + 1);
                            cell.s[6] = m_grid->gridPointScalar(m_mapScalarSetIndex, i + 1, j,     k + 1);
                            cell.s[7] = m_grid->gridPointScalar(m_mapScalarSetIndex, i,     j,     k + 1);
                        }
                    }
                }


                Triangles triangles;
                uint numTriangles = polygonise(m_plane, cell, &triangles);
                if (numTriangles > 0)
                {
                    // Add all the referenced vertices
                    // At the same time registering their index in the 'global' vertex list
                    uint globalVertexIndices[12];
                    int iv;
                    for (iv = 0; iv < 12; iv++)
                    {
                        if (triangles.usedVertices[iv])
                        {
                            globalVertexIndices[iv] = static_cast<uint>(m_vertices.size());
                            m_vertices.push_back(Vec3f(triangles.vertices[iv]));

                            if (doMapScalar)
                            {
                                if (m_mapNodeAveragedScalars)
                                {
                                    m_vertexScalars.push_back(triangles.scalars[iv]);
                                }
                                else
                                {
                                    m_vertexScalars.push_back(cellScalarValue);
                                }
                            }
                        }
                        else
                        {
                            globalVertexIndices[iv] = UNDEFINED_UINT;
                        }
                    }

                    // Build triangles from the cell
                    const size_t prevNumTriangleIndices = m_triangleIndices.size();
                    uint t;
                    for (t = 0; t < numTriangles; t++)
                    {
                        m_triangleIndices.push_back(globalVertexIndices[triangles.triangleIndices[3*t]]);
                        m_triangleIndices.push_back(globalVertexIndices[triangles.triangleIndices[3*t + 1]]);
                        m_triangleIndices.push_back(globalVertexIndices[triangles.triangleIndices[3*t + 2]]);
                    }

                    // Add mesh line indices 
                    addMeshLineIndices(&m_triangleIndices[prevNumTriangleIndices], numTriangles);
                }
            }
        }
    }

    //Trace::show("Vertices:%d  TriConns:%d  Tris:%d", m_vertices.size(), m_triangleIndices.size(), m_triangleIndices.size()/3);
    tim.reportTimeMS();
}
Пример #5
0
void render() {
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	zviewpointSetupView();

	const int MAX_TRIS = 1000000;
	static Triangle tris[MAX_TRIS];
	int triCount = 0;
	
	const int steps = 60;
	const float stepsf = (float)steps;
	
	Rod r0( FVec3(-0.3f,0.f,0.f), FVec3(+0.f,0.f,0.f), Cloud_r );
	Rod r1( FVec3(0.f,0.f,0.f), FVec3(0.2f,0.5f,0.f), Cloud_r );
	Sphere s0( FVec3(-.5f, -.5f, 0.f), 0.25f );
	
	Surface *surfaces[] = {
		(Surface *)&r0,
		(Surface *)&r1,
		(Surface *)&s0
	};
	int surfacesCount = sizeof(surfaces) / sizeof(surfaces[0]);

	float f[steps][steps][steps];
	for( int xi=0; xi<steps; xi++ ) {
		for( int yi=0; yi<steps; yi++ ) {
			for( int zi=0; zi<steps; zi++ ) {
				FVec3 p( 2.f*(float)xi/stepsf-1.f, 2.f*(float)yi/stepsf-1.f, 2.f*(float)zi/stepsf-1.f );
				f[xi][yi][zi] = 0.f;
				for( int i=0; i<surfacesCount; i++ ) {
					f[xi][yi][zi] += surfaces[i]->surface( p );
				}
			}
		}
	}

	for( int xi=0; xi<steps-1; xi++ ) {
		for( int yi=0; yi<steps-1; yi++ ) {
			for( int zi=0; zi<steps-1; zi++ ) {
				GridCell g;
				float x0 = 2.f*(float)(xi+0)/stepsf-1.f;
				float x1 = 2.f*(float)(xi+1)/stepsf-1.f;
				float y0 = 2.f*(float)(yi+0)/stepsf-1.f;
				float y1 = 2.f*(float)(yi+1)/stepsf-1.f;
				float z0 = 2.f*(float)(zi+0)/stepsf-1.f;
				float z1 = 2.f*(float)(zi+1)/stepsf-1.f;
				g.p[0] = FVec3( x0, y0, z0 );
				g.p[1] = FVec3( x1, y0, z0 );
				g.p[2] = FVec3( x1, y1, z0 );
				g.p[3] = FVec3( x0, y1, z0 );
				g.p[4] = FVec3( x0, y0, z1 );
				g.p[5] = FVec3( x1, y0, z1 );
				g.p[6] = FVec3( x1, y1, z1 );
				g.p[7] = FVec3( x0, y1, z1 );
				g.val[0] =	f[xi+0][yi+0][zi+0];
				g.val[1] =	f[xi+1][yi+0][zi+0];
				g.val[2] =	f[xi+1][yi+1][zi+0];
				g.val[3] =	f[xi+0][yi+1][zi+0];
				g.val[4] =	f[xi+0][yi+0][zi+1];
				g.val[5] =	f[xi+1][yi+0][zi+1];
				g.val[6] =	f[xi+1][yi+1][zi+1];
				g.val[7] =	f[xi+0][yi+1][zi+1];

				triCount += polygonise( g, Cloud_r, &tris[triCount] );
				assert( triCount < MAX_TRIS );
			}
		}
	}

	DiscWarp dw( FVec3(-0.2f,0.f,0.f), FVec3(1.f,0.f,0.f) );
	for( int i=0; i<triCount; i++ ) {
		tris[i].p[0] = dw.warp( tris[i].p[0] );
		tris[i].p[1] = dw.warp( tris[i].p[1] );
		tris[i].p[2] = dw.warp( tris[i].p[2] );
	}
	
	dw.draw();
	
	static unsigned int triList[MAX_TRIS*3];
	static FVec3 normals[MAX_TRIS*3];

	ZGLLight light0;
	light0.resetToDefaults();
	light0.active = 1;
	light0.ambient[0] = 0.05f;
	light0.ambient[1] = 0.05f;
	light0.ambient[2] = 0.05f;
	light0.diffuse[0] = 0.8f;
	light0.diffuse[1] = 0.2f;
	light0.diffuse[2] = 0.2f;
	light0.dir[0] = 10.f;
	light0.dir[1] = 0.f;
	light0.dir[2] = 0.f;
	light0.makeDirectional();
	light0.setLightNumber( 0 );

	ZGLLight light1;
	light1.resetToDefaults();
	light1.active = 1;
	light1.ambient[0] = 0.05f;
	light1.ambient[1] = 0.05f;
	light1.ambient[2] = 0.05f;
	light1.diffuse[0] = 0.2f;
	light1.diffuse[1] = 0.2f;
	light1.diffuse[2] = 0.8f;
	light1.dir[0] = -10.f;
	light1.dir[1] = -10.f;
	light1.dir[2] = 0.f;
	light1.makeDirectional();
	light1.setLightNumber( 1 );

	glEnable( GL_COLOR_MATERIAL );
	glEnable( GL_LIGHTING );
	glEnable( GL_LIGHT0 );
	glEnable( GL_LIGHT1 );
	glEnable( GL_DEPTH_TEST );
	glEnable( GL_NORMALIZE );
	light0.setGL();
	light1.setGL();

	for( int i=0; i<triCount; i++ ) {
		FVec3 d10( tris[i].p[1] );
		d10.sub( tris[i].p[0] );
		FVec3 d20( tris[i].p[2] );
		d20.sub( tris[i].p[0] );
		normals[i*3+0] = d20;
		normals[i*3+0].cross( d10 );

		FVec3 d01( tris[i].p[0] );
		d01.sub( tris[i].p[1] );
		FVec3 d21( tris[i].p[2] );
		d21.sub( tris[i].p[1] );
		normals[i*3+1] = d01;
		normals[i*3+1].cross( d21 );

		FVec3 d02( tris[i].p[0] );
		d02.sub( tris[i].p[2] );
		FVec3 d12( tris[i].p[1] );
		d12.sub( tris[i].p[2] );
		normals[i*3+2] = d12;
		normals[i*3+2].cross( d02 );
	
		triList[i*3+0] = i*3+0;
		triList[i*3+1] = i*3+1;
		triList[i*3+2] = i*3+2;
	}
	
	glColor3ub( 255, 255, 255 );
	glEnableClientState( GL_VERTEX_ARRAY );
	glVertexPointer( 3, GL_FLOAT, 0, &tris[0] );
	glEnableClientState( GL_NORMAL_ARRAY );
	glNormalPointer( GL_FLOAT, 0, &normals[0] );
	glDrawElements( GL_TRIANGLES, triCount*3, GL_UNSIGNED_INT, &triList[0] );
}