void DrawMolItem::draw_volume_isosurface_lines (const VolumetricData * v, float isovalue, int stepsize, int thickness) { int i, usecolor; IsoSurface *s = new IsoSurface; s->clear (); s->compute (v, isovalue, stepsize); if (s->numtriangles > 0) { append (DMATERIALOFF); // enable lighting and shading cmdLineType.putdata (SOLIDLINE, cmdList); cmdLineWidth.putdata (thickness, cmdList); usecolor = draw_volume_get_colorid (); cmdColorIndex.putdata (usecolor, cmdList); // draw triangles for (i = 0; i < s->numtriangles; i++) { float *addr; addr = &(s->v[i * 9]); cmdLine.putdata (&addr[0], &addr[3], cmdList); cmdLine.putdata (&addr[3], &addr[6], cmdList); cmdLine.putdata (&addr[6], &addr[0], cmdList); } } delete s; // we don't need this stuff after this point }
void DrawMolItem::draw_volume_isosurface_trimesh (const VolumetricData * v, float isovalue, int stepsize) { int i, usecolor; IsoSurface s; s.clear (); // initialize isosurface data s.compute (v, isovalue, stepsize); // compute the isosurface s.vertexfusion (v, 36, 36); // identify and eliminate duplicated vertices s.normalize (); // normalize interpolated gradient/surface normals if (s.numtriangles > 0) { append (DMATERIALON); // enable lighting and shading usecolor = draw_volume_get_colorid (); cmdColorIndex.putdata (usecolor, cmdList); // draw surface with per-vertex normals using a vertex array float *c = new float[s.numtriangles * 9]; const float *fp = scene->color_value (usecolor); for (i = 0; i < s.numtriangles; i++) { int ind = i * 9; c[ind] = fp[0]; // Red c[ind + 1] = fp[1]; // Green c[ind + 2] = fp[2]; // Blue ind += 3; c[ind] = fp[0]; // Red c[ind + 1] = fp[1]; // Green c[ind + 2] = fp[2]; // Blue ind += 3; c[ind] = fp[0]; // Red c[ind + 1] = fp[1]; // Green c[ind + 2] = fp[2]; // Blue } // Create a triangle mesh // XXX don't try to stripify it since this triggers a crash in ACTC for // unknown reasons cmdTriMesh.putdata (&s.v[0], &s.n[0], c, s.v.num () / 3, &s.f[0], s.numtriangles, 0, cmdList, &cmdTriMesh); delete[] c; } }
void DefaultState::Load(void) { // < Add a light to our sample scene. m_pLight = Leadwerks::DirectionalLight::Create(); m_pLight->SetRotation(35.0f, -35.0f, 0.0f); // < Create a base for the sample scene. m_pGround = Leadwerks::Model::Box(10.0f, 0.5f, 10.0f); m_pGround->Move(0.0f, 0.0f, 4.0f); // < Create the world for our components and a sample camera to move // * about our scene. m_pWorld = new Components::World(); m_cameraDynamic = Entities::CameraDynamic::Create(m_pWorld, m_pCameraHndl, "./Scripts/Camera.lua"); m_pCameraHndl->getInst()->SetDrawMode(DRAW_WIREFRAME); // < Set the input manager to reset the mouse-position to the center of the // * screen every frame. m_pInputMgr->ToggleMouseCenter(); // < Initialize our isosurface and the voxel buffer we will be using. m_pIsosurface = new IsoSurface<float>(); m_pBuffer = new VoxelBuffer<float>(NUM_VOXELS, NUM_VOXELS, NUM_VOXELS); ModelerInput<float> input; Modeler<float> modeler; modeler.Assign(*m_pBuffer); // < Here, lets use the modeler to feed out voxel data into our isosurface. for (unsigned z = 0; z <= 8; z += 1) for (unsigned y = 0; y <= 8; y += 1) for (unsigned x = 0; x <= 8; x += 1) { input.pt[0] = x; input.pt[1] = y; input.pt[2] = z; // < Formula for a circle. if ( (sqrt((x - 4) * (x - 4) + (y - 4) * (y - 4) + (z - 4) * (z - 4)) < 4) ) input.val = -1.0f; else input.val = 1.0f; modeler.AddInput(input); } // end for modeler.Execute(); // < Generate our isosurface. m_pModel = Leadwerks::Model::Create(); m_pModel->Move(-4.0f, 0.0f, 0.0f); unsigned nTriangles = m_pIsosurface->GenerateSurface(*m_pModel, *m_pBuffer, 0.0, CELLS_PER_ISOSURFACE, CELLS_PER_ISOSURFACE, CELLS_PER_ISOSURFACE, VOXEL_SIZE, VOXEL_SIZE, VOXEL_SIZE); }
int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) { if(! isSimworldOk() ) return 1; // already inited? if(mpLbm) return 0; mpGlob = glob; if(!getVisible()) { mpAttrs->setAllUsed(); return 0; } mGeoInitId = mpAttrs->readInt("geoinitid", mGeoInitId,"LbmSolverInterface", "mGeoInitId", false); //mDimension, mSolverType are deprecated string mSolverType(""); mSolverType = mpAttrs->readString("solver", mSolverType, "SimulationObject","mSolverType", false ); mpLbm = createSolver(); /* check lbm pointer */ if(mpLbm == NULL) { errFatal("SimulationObject::initializeLbmSimulation","Unable to init LBM solver! ", SIMWORLD_INITERROR); return 2; } debMsgStd("SimulationObject::initialized",DM_MSG,"IdStr:"<<mpLbm->getIdString() <<" LBM solver! ", 2); mpParts = new ParticleTracer(); // for non-param simulations mpLbm->setParametrizer( mpParam ); mpParam->setAttrList( getAttributeList() ); // not needed.. done in solver_init: mpParam->setSize ... in solver_interface mpParam->parseAttrList(); mpLbm->setAttrList( getAttributeList() ); mpLbm->setSwsAttrList( getSwsAttributeList() ); mpLbm->parseAttrList(); mpParts->parseAttrList( getAttributeList() ); if(! isSimworldOk() ) return 3; mpParts->setName( getName() + "_part" ); mpParts->initialize( glob ); if(! isSimworldOk() ) return 4; // init material settings string matMc("default"); matMc = mpAttrs->readString("material_surf", matMc, "SimulationObject","matMc", false ); mShowSurface = mpAttrs->readInt("showsurface", mShowSurface, "SimulationObject","mShowSurface", false ); mShowParticles = mpAttrs->readInt("showparticles", mShowParticles, "SimulationObject","mShowParticles", false ); checkBoundingBox( mGeoStart, mGeoEnd, "SimulationObject::initializeSimulation" ); mpLbm->setLbmInitId( mGeoInitId ); mpLbm->setGeoStart( mGeoStart ); mpLbm->setGeoEnd( mGeoEnd ); mpLbm->setRenderGlobals( mpGlob ); mpLbm->setName( getName() + "_lbm" ); mpLbm->setParticleTracer( mpParts ); if(mpElbeemSettings) { // set further settings from API struct init if(mpElbeemSettings->outputPath) this->mOutFilename = string(mpElbeemSettings->outputPath); mpLbm->initDomainTrafo( mpElbeemSettings->surfaceTrafo ); mpLbm->setSmoothing(1.0 * mpElbeemSettings->surfaceSmoothing, 1.0 * mpElbeemSettings->surfaceSmoothing); mpLbm->setIsoSubdivs(mpElbeemSettings->surfaceSubdivs); mpLbm->setSizeX(mpElbeemSettings->resolutionxyz); mpLbm->setSizeY(mpElbeemSettings->resolutionxyz); mpLbm->setSizeZ(mpElbeemSettings->resolutionxyz); mpLbm->setPreviewSize(mpElbeemSettings->previewresxyz); mpLbm->setRefinementDesired(mpElbeemSettings->maxRefine); mpLbm->setGenerateParticles(mpElbeemSettings->generateParticles); // set initial particles mpParts->setNumInitialParticles(mpElbeemSettings->numTracerParticles); // surface generation flag mpLbm->setSurfGenSettings(mpElbeemSettings->mFsSurfGenSetting); string dinitType = string("no"); if (mpElbeemSettings->domainobsType==FLUIDSIM_OBSTACLE_PARTSLIP) dinitType = string("part"); else if(mpElbeemSettings->domainobsType==FLUIDSIM_OBSTACLE_FREESLIP) dinitType = string("free"); else /*if(mpElbeemSettings->domainobsType==FLUIDSIM_OBSTACLE_NOSLIP)*/ dinitType = string("no"); mpLbm->setDomainBound(dinitType); mpLbm->setDomainPartSlip(mpElbeemSettings->domainobsPartslip); mpLbm->setDumpVelocities(mpElbeemSettings->generateVertexVectors); mpLbm->setFarFieldSize(mpElbeemSettings->farFieldSize); debMsgStd("SimulationObject::initialize",DM_MSG,"Added domain bound: "<<dinitType<<" ps="<<mpElbeemSettings->domainobsPartslip<<" vv"<<mpElbeemSettings->generateVertexVectors<<","<<mpLbm->getDumpVelocities(), 9 ); debMsgStd("SimulationObject::initialize",DM_MSG,"Set ElbeemSettings values "<<mpLbm->getGenerateParticles(),10); } if(! mpLbm->initializeSolverMemory() ) { errMsg("SimulationObject::initialize","initializeSolverMemory failed"); mPanic=true; return 10; } if(checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0)) { errMsg("SimulationObject::initialize","initializeSolverMemory status"); mPanic=true; return 11; } if(! mpLbm->initializeSolverGrids() ) { errMsg("SimulationObject::initialize","initializeSolverGrids failed"); mPanic=true; return 12; } if(checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0)) { errMsg("SimulationObject::initialize","initializeSolverGrids status"); mPanic=true; return 13; } if(! mpLbm->initializeSolverPostinit() ) { errMsg("SimulationObject::initialize","initializeSolverPostin failed"); mPanic=true; return 14; } if(checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0)) { errMsg("SimulationObject::initialize","initializeSolverPostin status"); mPanic=true; return 15; } // print cell type stats bool printStats = true; if(glob_mpnum>0) printStats=false; // skip in this case if(printStats) { const int jmax = sizeof(CellFlagType)*8; int totalCells = 0; int flagCount[jmax]; for(int j=0; j<jmax ; j++) flagCount[j] = 0; int diffInits = 0; LbmSolverInterface::CellIdentifier cid = mpLbm->getFirstCell(); for(; mpLbm->noEndCell( cid ); mpLbm->advanceCell( cid ) ) { int flag = mpLbm->getCellFlag(cid,0); int flag2 = mpLbm->getCellFlag(cid,1); if(flag != flag2) { diffInits++; } for(int j=0; j<jmax ; j++) { if( flag&(1<<j) ) flagCount[j]++; } totalCells++; } mpLbm->deleteCellIterator( &cid ); char charNl = '\n'; debugOutNnl("SimulationObject::initializeLbmSimulation celltype stats: " <<charNl, 5); debugOutNnl("no. of cells = "<<totalCells<<", "<<charNl ,5); for(int j=0; j<jmax ; j++) { std::ostringstream out; if(flagCount[j]>0) { out<<"\t" << flagCount[j] <<" x "<< convertCellFlagType2String( (CellFlagType)(1<<j) ) <<", " << charNl; debugOutNnl(out.str(), 5); } } // compute dist. of empty/bnd - fluid - if // cfEmpty = (1<<0), cfBnd = (1<< 2), cfFluid = (1<<10), cfInter = (1<<11), if(1){ std::ostringstream out; out.precision(2); out.width(4); int totNum = flagCount[1]+flagCount[2]+flagCount[7]+flagCount[8]; double ebFrac = (double)(flagCount[1]+flagCount[2]) / totNum; double flFrac = (double)(flagCount[7]) / totNum; double ifFrac = (double)(flagCount[8]) / totNum; //??? out<<"\tFractions: [empty/bnd - fluid - interface - ext. if] = [" << ebFrac<<" - " << flFrac<<" - " << ifFrac<<"] "<< charNl; if(diffInits > 0) { debMsgStd("SimulationObject::initializeLbmSimulation",DM_MSG,"celltype Warning: Diffinits="<<diffInits<<"!" , 5); } debugOutNnl(out.str(), 5); } } // cellstats // might be modified by mpLbm //mpParts->setStart( mGeoStart );? mpParts->setEnd( mGeoEnd );? mpParts->setStart( mpLbm->getGeoStart() ); mpParts->setEnd( mpLbm->getGeoEnd() ); mpParts->setCastShadows( false ); mpParts->setReceiveShadows( false ); mpParts->searchMaterial( glob->getMaterials() ); // this has to be inited here - before, the values might be unknown IsoSurface *surf = mpLbm->getSurfaceGeoObj(); if(surf) { surf->setName( "final" ); // final surface mesh // warning - this might cause overwriting effects for multiple sims and geom dump... surf->setCastShadows( true ); surf->setReceiveShadows( false ); surf->searchMaterial( glob->getMaterials() ); if(mShowSurface) mObjects.push_back( surf ); } #ifdef ELBEEM_PLUGIN mShowParticles=1; // for e.g. dumping #endif // ELBEEM_PLUGIN if((mpLbm->getGenerateParticles()>0.0)||(mpParts->getNumInitialParticles()>0)) { mShowParticles=1; mpParts->setDumpParts(true); } //debMsgStd("SimulationObject::init",DM_NOTIFY,"Using envvar ELBEEM_DUMPPARTICLE to set mShowParticles, DEBUG!",1); //} // DEBUG ENABLE!!!!!!!!!! if(mShowParticles) { mObjects.push_back(mpParts); } // add objects to display for debugging (e.g. levelset particles) vector<ntlGeometryObject *> debugObjs = mpLbm->getDebugObjects(); for(size_t i=0;i<debugObjs.size(); i++) { debugObjs[i]->setCastShadows( false ); debugObjs[i]->setReceiveShadows( false ); debugObjs[i]->searchMaterial( glob->getMaterials() ); mObjects.push_back( debugObjs[i] ); debMsgStd("SimulationObject::init",DM_NOTIFY,"Added debug obj "<<debugObjs[i]->getName(), 10 ); } return 0; }
/* * March through the grid, creating the tesselation of an isosurface. * The somewhat convoluted logic is necessary to prevent any single cube * edge from being examined more than once. This allows for a compact * mesh representation, with each vertex stored only once and each face * stored simply as three integer indices into the vertex array. */ void MarchCube::march (IsoSurface& surface) { surface.clear(); ImpSurface* function = surface.getFunction(); /* * */ initVertices(0, vtxGrid[0], function); initVertices(1, vtxGrid[1], function); setCubeFlags(); /* * Fill in the back of the grid first (where "forward" is the +z * direction. This is done by checking the left- and bottom-edges * of each square at the very back of the grid, then all the edges * along the top of the back, then all those along the right. */ for (int i = 0; i < resx; ++i) { for (int j = 0; j < resy; ++j) { if (edgeFlags[i][j] & LEFTBACK) edgeGrid[0][i][j][0] = surface.addVertex(vtxGrid[0][i][j].findSurface( vtxGrid[0][i][j + 1], threshold)); if (edgeFlags[i][j] & BOTBACK) edgeGrid[0][i][j][2] = surface.addVertex(vtxGrid[0][i][j].findSurface( vtxGrid[0][i + 1][j], threshold)); } if (edgeFlags[i][resy - 1] & TOPBACK) edgeGrid[0][i][resy][2] = surface.addVertex(vtxGrid[0][i][resy].findSurface( vtxGrid[0][i + 1][resy], threshold)); } for (int i = 0; i < resy; ++i) { if (edgeFlags[resx - 1][i] & RIGHTBACK) edgeGrid[0][resx][i][0] = surface.addVertex(vtxGrid[0][resx][i].findSurface( vtxGrid[0][resx][i + 1], threshold)); } /* * Step forward (in the +z direction) through the grid. We first * consider the bottom-left, front-left, and bottom-front edges from * each cube. The top edges from the top row of cubes are then * examined, followed by those on the right edge of the grid. */ for (int layer = 1; layer <= resz; ++layer) { // cerr << "filling in layer " << layer << endl; if (layer > 1) { initVertices(layer, vtxGrid[1], function); setCubeFlags(); } for (int i = 0; i < resx; ++i) { for (int j = 0; j < resy; ++j) { if (edgeFlags[i][j] & BOTLEFT) edgeGrid[0][i][j][1] = surface.addVertex(vtxGrid[0][i][j].findSurface( vtxGrid[1][i][j], threshold)); if (edgeFlags[i][j] & LEFTFRONT) edgeGrid[1][i][j][0] = surface.addVertex(vtxGrid[1][i][j].findSurface( vtxGrid[1][i][j + 1], threshold)); if (edgeFlags[i][j] & BOTFRONT) edgeGrid[1][i][j][2] = surface.addVertex(vtxGrid[1][i][j].findSurface( vtxGrid[1][i + 1][j], threshold)); } if (edgeFlags[i][resy - 1] & TOPLEFT) edgeGrid[0][i][resy][1] = surface.addVertex(vtxGrid[0][i][resy].findSurface( vtxGrid[1][i][resy], threshold)); if (edgeFlags[i][resy - 1] & TOPFRONT) edgeGrid[1][i][resy][2] = surface.addVertex(vtxGrid[1][i][resy].findSurface( vtxGrid[1][i + 1][resy], threshold)); } for (int i = 0; i < resy; ++i) { if (edgeFlags[resx - 1][i] & RIGHTFRONT) edgeGrid[1][resx][i][0] = surface.addVertex(vtxGrid[1][resx][i].findSurface( vtxGrid[1][resx][i + 1], threshold)); if (edgeFlags[resx - 1][i] & BOTRIGHT) edgeGrid[0][resx][i][1] = surface.addVertex(vtxGrid[0][resx][i].findSurface( vtxGrid[1][resx][i], threshold)); } if (edgeFlags[resx - 1][resy - 1] & TOPRIGHT) edgeGrid[0][resx][resy][1] = surface.addVertex(vtxGrid[0][resx][resy].findSurface( vtxGrid[1][resx][resy], threshold)); /* * Now that we've found all the vertices on the edges of the cubes * in the layer, extract the set of triangles defined. */ int* indices; int e0, e1, e2; int v0, v1, v2; static int badV = 0; for (int i = 0; i < resx; ++i) { for (int j = 0; j < resy; ++j) { indices = triTable[vtxFlags[i][j]]; while(*indices != -1) { e0 = *indices++; e1 = *indices++; e2 = *indices++; v0 = getVertex(i, j, e0); v1 = getVertex(i, j, e1); v2 = getVertex(i, j, e2); surface.addFace(v0, v1, v2); } } } /* * Move the vertex/edge-index grids one step forward */ CubeVtx** vTemp = vtxGrid[0]; vtxGrid[0] = vtxGrid[1]; vtxGrid[1] = vTemp; int*** eTemp = edgeGrid[0]; edgeGrid[0] = edgeGrid[1]; edgeGrid[1] = eTemp; } surface.calcVNorms(); }