//-***************************************************************************** void meshUnderXformOut( const std::string &iName ) { OArchive archive( Alembic::AbcCoreHDF5::WriteArchive(), iName ); TimeSamplingPtr ts( new TimeSampling( 1.0 / 24.0, 0.0 ) ); OXform xfobj( archive.getTop(), "xf", ts ); OPolyMesh meshobj( xfobj, "mesh", ts ); OPolyMeshSchema::Sample mesh_samp( V3fArraySample( ( const V3f * )g_verts, g_numVerts ), Int32ArraySample( g_indices, g_numIndices ), Int32ArraySample( g_counts, g_numCounts ) ); XformSample xf_samp; XformOp rotOp( kRotateYOperation ); Box3d childBounds; childBounds.makeEmpty(); childBounds.extendBy( V3d( 1.0, 1.0, 1.0 ) ); childBounds.extendBy( V3d( -1.0, -1.0, -1.0 ) ); xf_samp.setChildBounds( childBounds ); double rotation = 0.0; for ( std::size_t i = 0 ; i < 100 ; ++i ) { xf_samp.addOp( rotOp, rotation ); xfobj.getSchema().set( xf_samp ); meshobj.getSchema().set( mesh_samp ); rotation += 30.0; } }
Imath::Box3d AlembicInput::boundAtTime( double time ) const { if( hasStoredBound() ) { size_t index0, index1; double lerpFactor = sampleIntervalAtTime( time, index0, index1 ); if( index0 == index1 ) { return boundAtSample( index0 ); } else { Box3d bound0 = boundAtSample( index0 ); Box3d bound1 = boundAtSample( index1 ); Box3d result; result.min = lerp( bound0.min, bound1.min, lerpFactor ); result.max = lerp( bound0.max, bound1.max, lerpFactor ); return result; } } else { Box3d result; for( size_t i=0, n=numChildren(); i<n; i++ ) { AlembicInputPtr c = child( i ); Box3d childBound = c->boundAtTime( time ); childBound = Imath::transform( childBound, c->transformAtTime( time ) ); result.extendBy( childBound ); } return result; } }
int AdFront2 :: AddLine (int pi1, int pi2, const PointGeomInfo & gi1, const PointGeomInfo & gi2) { int minfn; int li; FrontPoint2 & p1 = points[pi1]; FrontPoint2 & p2 = points[pi2]; nfl++; p1.AddLine(); p2.AddLine(); minfn = min2 (p1.FrontNr(), p2.FrontNr()); p1.DecFrontNr (minfn+1); p2.DecFrontNr (minfn+1); if (dellinel.Size() != 0) { li = dellinel.Last(); dellinel.DeleteLast (); lines[li] = FrontLine (INDEX_2(pi1, pi2)); } else { li = lines.Append(FrontLine (INDEX_2(pi1, pi2))) - 1; } if (!gi1.trignum || !gi2.trignum) { cout << "ERROR: in AdFront::AddLine, illegal geominfo" << endl; } lines[li].SetGeomInfo (gi1, gi2); Box3d lbox; lbox.SetPoint(p1.P()); lbox.AddPoint(p2.P()); linesearchtree.Insert (lbox.PMin(), lbox.PMax(), li); if (allflines) { if (allflines->Used (INDEX_2 (GetGlobalIndex (pi1), GetGlobalIndex (pi2)))) { cerr << "ERROR Adfront2::AddLine: line exists" << endl; (*testout) << "ERROR Adfront2::AddLine: line exists" << endl; } allflines->Set (INDEX_2 (GetGlobalIndex (pi1), GetGlobalIndex (pi2)), 1); } return li; }
//-***************************************************************************** //-***************************************************************************** // WRITING OUT AN ANIMATED MESH // // Here we'll create an "Archive", which is Alembic's term for the actual // file on disk containing all of the scene geometry. The Archive will contain // a single animated Transform with a single static PolyMesh as its child. //-***************************************************************************** //-***************************************************************************** void Example1_MeshOut() { // Create an OArchive. // Like std::iostreams, we have a completely separate-but-parallel class // hierarchy for output and for input (OArchive, IArchive, and so on). This // maintains the important abstraction that Alembic is for storage, // representation, and archival. (as opposed to being a dynamic scene // manipulation framework). OArchive archive( // The hard link to the implementation. Alembic::AbcCoreHDF5::WriteArchive(), // The file name. // Because we're an OArchive, this is creating (or clobbering) // the archive with this filename. "polyMesh1.abc" ); // Create a PolyMesh class. OPolyMesh meshyObj( OObject( archive, kTop ), "meshy" ); OPolyMeshSchema &mesh = meshyObj.getSchema(); // UVs and Normals use GeomParams, which can be written or read // as indexed or not, as you'd like. OV2fGeomParam::Sample uvsamp( V2fArraySample( (const V2f *)g_uvs, g_numUVs ), kFacevaryingScope ); // indexed normals ON3fGeomParam::Sample nsamp( N3fArraySample( (const N3f *)g_normals, g_numNormals ), kFacevaryingScope ); // Set a mesh sample. // We're creating the sample inline here, // but we could create a static sample and leave it around, // only modifying the parts that have changed. OPolyMeshSchema::Sample mesh_samp( V3fArraySample( ( const V3f * )g_verts, g_numVerts ), Int32ArraySample( g_indices, g_numIndices ), Int32ArraySample( g_counts, g_numCounts ), uvsamp, nsamp ); // not actually the right data; just making it up Box3d cbox; cbox.extendBy( V3d( 1.0, -1.0, 0.0 ) ); cbox.extendBy( V3d( -1.0, 1.0, 3.0 ) ); mesh_samp.setChildBounds( cbox ); // Set the sample twice mesh.set( mesh_samp ); mesh.set( mesh_samp ); // Alembic objects close themselves automatically when they go out // of scope. So - we don't have to do anything to finish // them off! std::cout << "Writing: " << archive.getName() << std::endl; }
//-***************************************************************************** void ISubDDrw::setTime( chrono_t iSeconds ) { IObjectDrw::setTime( iSeconds ); if ( !valid() ) { m_drwHelper.makeInvalid(); return; } // Use nearest for now. ISampleSelector ss( iSeconds, ISampleSelector::kNearIndex ); ISubDSchema::Sample psamp; if ( m_subD.getSchema().isConstant() ) { psamp = m_samp; } else if ( m_subD.getSchema().getNumSamples() > 0 ) { m_subD.getSchema().get( psamp, ss ); } // Get the stuff. P3fArraySamplePtr P = psamp.getPositions(); Int32ArraySamplePtr indices = psamp.getFaceIndices(); Int32ArraySamplePtr counts = psamp.getFaceCounts(); Box3d bounds; bounds.makeEmpty(); if ( m_boundsProp && m_boundsProp.getNumSamples() > 0 ) { bounds = m_boundsProp.getValue( ss ); } // Update the mesh hoo-ha. m_drwHelper.update( P, V3fArraySamplePtr(), indices, counts, bounds ); if ( !m_drwHelper.valid() ) { m_subD.reset(); return; } // The Object update computed child bounds. // Extend them by this. if ( !m_drwHelper.getBounds().isEmpty() ) { m_bounds.extendBy( m_drwHelper.getBounds() ); } }
Imath::Box3f SceneReader::computeBound( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { ConstSceneInterfacePtr s = scene( path ); if( !s ) { return Box3f(); } Box3d b = s->readBound( context->getFrame() / g_frameRate ); if( b.isEmpty() ) { return Box3f(); } return Box3f( b.min, b.max ); }
void BulletWorld::setBoundary(const Box3d<float>& box) { btBoxShape* worldBoxShape = new btBoxShape( BulletConverter::convert( box.getLength() * 0.5 )); ///create 6 planes/half spaces for (int i = 0; i < 6; i++) { btTransform groundTransform; groundTransform.setIdentity(); groundTransform.setOrigin(BulletConverter::convert( box.getCenter()) ); btVector4 planeEq; worldBoxShape->getPlaneEquation(planeEq, i); btCollisionShape* shape = new btStaticPlaneShape(-planeEq, planeEq[3]); btDefaultMotionState* state = new btDefaultMotionState(groundTransform); btRigidBody::btRigidBodyConstructionInfo plain_body_ci(0.0f, state, shape); btRigidBody* body = new btRigidBody(plain_body_ci); world->addRigidBody(body); } /* { btStaticPlaneShape* shape = new btBoxShape(BulletConverter::convert(box)); btDefaultMotionState* state = new btDefaultMotionState(); btRigidBody::btRigidBodyConstructionInfo plain_body_ci(0.0f, state, shape); btRigidBody* body = new btRigidBody(plain_body_ci); world->addRigidBody(body); } { btStaticPlaneShape* shape = new btStaticPlaneShape(btVector3(1.0f, 0.0f, 0.0f), box.getMinX()); btDefaultMotionState* state = new btDefaultMotionState(); btRigidBody::btRigidBodyConstructionInfo plain_body_ci(0.0f, state, shape); btRigidBody* body = new btRigidBody(plain_body_ci); world->addRigidBody(body); } { btCollisionShape* shape = new btStaticPlaneShape(btVector3(0.0f, 0.0f, 1.0f), box.getMinZ()); btDefaultMotionState* state = new btDefaultMotionState(); btRigidBody::btRigidBodyConstructionInfo plain_body_ci(0.0f, state, shape); btRigidBody* body = new btRigidBody(plain_body_ci); world->addRigidBody(body); } */ }
void VisualSceneSpecPoints :: BuildScene (int zoomall) { if (!mesh) { VisualScene::BuildScene(zoomall); return; } Box3d box; if (mesh->GetNSeg()) { box.SetPoint (mesh->Point (mesh->LineSegment(1)[0])); for (int i = 1; i <= mesh->GetNSeg(); i++) { box.AddPoint (mesh->Point (mesh->LineSegment(i)[0])); box.AddPoint (mesh->Point (mesh->LineSegment(i)[1])); } } else if (specpoints.Size() >= 2) { box.SetPoint (specpoints.Get(1).p); for (int i = 2; i <= specpoints.Size(); i++) box.AddPoint (specpoints.Get(i).p); } else { box = Box3d (Point3d (0,0,0), Point3d (1,1,1)); } if (zoomall == 2 && ((vispar.centerpoint >= 1 && vispar.centerpoint <= mesh->GetNP()) || vispar.use_center_coords)) { if (vispar.use_center_coords) { center.X() = vispar.centerx; center.Y() = vispar.centery; center.Z() = vispar.centerz; } else center = mesh->Point (vispar.centerpoint); } else center = Center (box.PMin(), box.PMax()); rad = 0.5 * Dist (box.PMin(), box.PMax()); CalcTransformationMatrices(); }
PhysicsObject::PhysicsObject(const Box3d<float>& box, const float divideLength, const SPHConstant& constant): constant(constant), nextId(0) { const auto points = box.toPoints(divideLength); for (const auto& pos : points) { SPHParticle* p = new SPHParticle(pos, divideLength*0.5f, &this->constant, nextId++); particles.push_back(p); } }
std::vector<SPHParticle*> PhysicsObject::createParticles(const Box3d<float>& box, const float divideLength) { std::vector<SPHParticle*> newParticles; const auto points = box.toPoints(divideLength); for (const auto& pos : points) { SPHParticle* p = new SPHParticle(pos, divideLength*0.5f, &this->constant, nextId++); particles.push_back(p); newParticles.push_back(p); } return newParticles; }
Imath::Box3f SceneReader::computeBound( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { std::string fileName = fileNamePlug()->getValue(); if( !fileName.size() ) { return Box3f(); } ConstSceneInterfacePtr s = SharedSceneInterfaces::get( fileName ); s = s->scene( path ); Box3d b = s->readBound( context->getFrame() / g_frameRate ); if( b.isEmpty() ) { return Box3f(); } return Box3f( b.min, b.max ); }
Imath::Box3f SceneReader::computeBound( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { ConstSceneInterfacePtr s = scene( path ); if( !s ) { return Box3f(); } if( s->hasBound() ) { const Box3d b = s->readBound( context->getTime() ); if( b.isEmpty() ) { return Box3f(); } return Box3f( b.min, b.max ); } else { return unionOfTransformedChildBounds( path, parent ); } }
/* Funzione chiamata dalla Align ad ogni ciclo Riempie i vettori <MovVert> e <MovNorm> con i coordinate e normali presi dal vettore di vertici mov della mesh da muovere trasformata secondo la matrice <In> Calcola anche il nuovo bounding box di tali vertici trasformati. */ bool AlignPair::InitMov( vector< Point3d > &MovVert, vector< Point3d > &MovNorm, Box3d &trgbox, const Matrix44d &in ) // trasformazione Iniziale (che porta i punti di trg su src) { Point3d pp,nn; MovVert.clear(); MovNorm.clear(); trgbox.SetNull(); A2Mesh::VertexIterator vi; for(vi=mov->begin(); vi!=mov->end(); vi++) { pp=in*(*vi).P(); nn=in*Point3d((*vi).P()+(*vi).N())-pp; nn.Normalize(); MovVert.push_back(pp); MovNorm.push_back(nn); trgbox.Add(pp); } return true; }
Intervald Sphere::proc(const Box<double>& x) { Box3d x1; Box3d center; Box3d diff; Intervald m_rtemp; if (x.size() == 3) { x1 = x; center = Box<double>(convert(m_x)); m_rtemp = Intervald(m_r); } else { x1 = Box3d(x[0],x[1],x[2]); center = m_xlrp(x[3]); m_rtemp = m_rlrp(x[3]); } diff = x1 - center; return diff.length() - m_rtemp; }
void worldToVoxel(const Field3D::FieldMapping* mapping, const Box3d &wsBounds, Box3d &vsBounds) { V3d test1, test2; mapping->worldToVoxel(test1, test2); //! \todo Make this integrate over time V3d wsVerts[] = { V3d(wsBounds.min.x, wsBounds.min.y, wsBounds.min.z), V3d(wsBounds.max.x, wsBounds.min.y, wsBounds.min.z), V3d(wsBounds.min.x, wsBounds.max.y, wsBounds.min.z), V3d(wsBounds.max.x, wsBounds.max.y, wsBounds.min.z), V3d(wsBounds.min.x, wsBounds.min.y, wsBounds.max.z), V3d(wsBounds.max.x, wsBounds.min.y, wsBounds.max.z), V3d(wsBounds.min.x, wsBounds.max.y, wsBounds.max.z), V3d(wsBounds.max.x, wsBounds.max.y, wsBounds.max.z) }; vsBounds.makeEmpty(); V3d vsP; for (int i = 0; i < 8; i++) { mapping->worldToVoxel(wsVerts[i], vsP); vsBounds.extendBy(vsP); } }
Box3d Sphere::grad(const Box<double>& x) { Box3d x1; Box3d center; Box3d g; if (x.size() == 3) { x1 = x; center = Box<double>(convert(m_x)); } else { x1 = Box3d(x[0],x[1],x[2]); center = m_xlrp(x[3]); } g = x1 - center; Intervald l = g.lengthSquared(); if (l.isZero()) return Box3d(0.0); else return g / l.sqrt(); }
void ParticleObject::add(const Box3d<float>& box, const float diameter, const float charge) { for (auto x = box.getMinX(); x < box.getMaxX(); x += diameter) { for (auto y = box.getMinY(); y < box.getMaxY(); y += diameter) { for (auto z = box.getMinZ(); z < box.getMaxZ(); z += diameter) { const Vector3d<float> pos(x, y, z); particles.push_back(new Particle(pos, 1.0f, diameter * 0.5f)); } } } sort(); }
void PaintCanvas::fitScreen() { Object* obj = activeObject(); if (obj) { Box3d box; if (dynamic_cast<Map*>(obj)) box = Geom::bounding_box(dynamic_cast<Map*>(obj)); else if (dynamic_cast<PointSet*>(obj)) box = Geom::bounding_box(dynamic_cast<PointSet*>(obj)); qglviewer::Vec vmin(box.x_min(), box.y_min(), box.z_min()); qglviewer::Vec vmax(box.x_max(), box.y_max(), box.z_max()); //Vec vmin(-2.0f, -2.0f, -2.0f); //Vec vmax(2.0f, 2.0f, 2.0f); setSceneBoundingBox(vmin, vmax); showEntireScene(); } updateGL(); }
//-***************************************************************************** //-***************************************************************************** // DO IT. //-***************************************************************************** //-***************************************************************************** int main( int argc, char *argv[] ) { if ( argc != 2 ) { std::cerr << "USAGE: " << argv[0] << " <AlembicArchive.abc>" << std::endl; exit( -1 ); } // Scoped. g_bounds.makeEmpty(); { IArchive archive( Alembic::AbcCoreHDF5::ReadArchive(), argv[1], ErrorHandler::kQuietNoopPolicy ); visitObject( archive.getTop() ); } std::cout << "/" << " " << g_bounds.min << " " << g_bounds.max << std::endl; return 0; }
//-***************************************************************************** Box3d getBounds( IObject iObj ) { Box3d bnds; bnds.makeEmpty(); M44d xf = getFinalMatrix( iObj ); if ( IPolyMesh::matches( iObj.getMetaData() ) ) { IPolyMesh mesh( iObj, kWrapExisting ); IPolyMeshSchema ms = mesh.getSchema(); V3fArraySamplePtr positions = ms.getValue().getPositions(); size_t numPoints = positions->size(); for ( size_t i = 0 ; i < numPoints ; ++i ) { bnds.extendBy( (*positions)[i] ); } } else if ( ISubD::matches( iObj.getMetaData() ) ) { ISubD mesh( iObj, kWrapExisting ); ISubDSchema ms = mesh.getSchema(); V3fArraySamplePtr positions = ms.getValue().getPositions(); size_t numPoints = positions->size(); for ( size_t i = 0 ; i < numPoints ; ++i ) { bnds.extendBy( (*positions)[i] ); } } bnds.extendBy( Imath::transform( bnds, xf ) ); g_bounds.extendBy( bnds ); return bnds; }
bool AlignPair::Align( A2Grid &u, A2GridVert &uv, const Matrix44d &in, // trasformazione Iniziale (che porta i punti di mov su fix) Matrix44d &out, // trasformazione calcolata vector<Point3d> &Pfix, // vertici corrispondenti su src (rossi) vector<Point3d> &Nfix, // normali corrispondenti su src (rossi) vector<Point3d> &OPmov, // vertici scelti su trg (verdi) prima della trasformazione in ingresso (Original Point Target) vector<Point3d> &ONmov, // normali scelti su trg (verdi) Histogramf &H, AlignPair::Stat &as) { vector<char> beyondCntVec; // vettore per marcare i movvert che sicuramente non si devono usare // ogni volta che un vertice si trova a distanza oltre max dist viene incrementato il suo contatore; // i movvert che sono stati scartati piu' di MaxCntDist volte non si guardano piu'; const int maxBeyondCnt=3; vector< Point3d > movvert; vector< Point3d > movnorm; vector<Point3d> Pmov; // vertici scelti dopo la trasf iniziale status=SUCCESS; int tt0=clock(); out=in; int i; double CosAngleThr=cos(ap.MaxAngleRad); double StartMinDist=ap.MinDistAbs; int tt1=clock(); int ttsearch=0; int ttleast=0; int nc=0; as.clear(); as.StartTime=clock(); beyondCntVec.resize(mov->size(),0); /**************** BEGIN ICP LOOP ****************/ do { Stat::IterInfo ii; Box3d movbox; InitMov(movvert,movnorm,movbox,out); H.SetRange(0,StartMinDist,512,2.5); Pfix.clear(); Nfix.clear(); Pmov.clear(); OPmov.clear(); ONmov.clear(); int tts0=clock(); ii.MinDistAbs=StartMinDist; int LocSampleNum=min(ap.SampleNum,int(movvert.size())); Box3d fixbox; if(u.Empty()) fixbox = uv.bbox; else fixbox = u.bbox; for(i=0;i<LocSampleNum;++i) { if( beyondCntVec[i] < maxBeyondCnt ) if(! fixbox.IsIn(movvert[i]) ) beyondCntVec[i]=maxBeyondCnt+1; else { double error=StartMinDist; Point3d closestPoint, closestNormal; double maxd= StartMinDist; ii.SampleTested++; if(u.Empty()) // using the point cloud grid { A2Mesh::VertexPointer vp = tri::GetClosestVertex(*fix,uv,movvert[i], maxd, error); if(error>=StartMinDist) { ii.DistanceDiscarded++; ++beyondCntVec[i]; continue; } if(movnorm[i].dot(vp->N()) < CosAngleThr) { ii.AngleDiscarded++; continue; } closestPoint=vp->P(); closestNormal=vp->N(); } else // using the standard faces and grid { A2Mesh::FacePointer f=vcg::tri::GetClosestFaceBase<vcg::AlignPair::A2Mesh, vcg::AlignPair::A2Grid >(*fix, u, movvert[i], maxd, error, closestPoint); if(error>=StartMinDist) { ii.DistanceDiscarded++; ++beyondCntVec[i]; continue; } if(movnorm[i].dot(f->N()) < CosAngleThr) { ii.AngleDiscarded++; continue; } Point3d ip; InterpolationParameters<A2Face,double>(*f,f->N(),closestPoint, ip); const double IP_EPS = 0.00001; // If ip[i] == 0 it means that we are on the edge opposite to i if( (fabs(ip[0])<=IP_EPS && f->IsB(1)) || (fabs(ip[1])<=IP_EPS && f->IsB(2)) || (fabs(ip[2])<=IP_EPS && f->IsB(0)) ){ ii.BorderDiscarded++; continue; } closestNormal = f->N(); } // The sample was accepted. Store it. Pmov.push_back(movvert[i]); OPmov.push_back((*mov)[i].P()); ONmov.push_back((*mov)[i].N()); Nfix.push_back( closestNormal ); Pfix.push_back( closestPoint ); H.Add(float(error)); ii.SampleUsed++; } } // End for each pmov int tts1=clock(); //printf("Found %d pairs\n",(int)Pfix.size()); if(!ChoosePoints(Pfix,Nfix,Pmov,OPmov,ap.PassHiFilter,H)) if(int(Pfix.size())<ap.MinPointNum) { status = TOO_FEW_POINTS; ii.Time=clock(); as.I.push_back(ii); return false; } Matrix44d newout; switch(ap.MatchMode) { case AlignPair::Param::MMSimilarity : ComputeRotoTranslationScalingMatchMatrix(newout,Pfix,OPmov); break; case AlignPair::Param::MMRigid : ComputeRigidMatchMatrix(Pfix,OPmov,newout); break; default : status = UNKNOWN_MODE; ii.Time=clock(); as.I.push_back(ii); return false; } // double sum_before=0; // double sum_after=0; // for(unsigned int iii=0;iii<Pfix.size();++iii) // { // sum_before+=Distance(Pfix[iii], out*OPmov[iii]); // sum_after+=Distance(Pfix[iii], newout*OPmov[iii]); // } // //printf("Distance %f -> %f\n",sum_before/double(Pfix.size()),sum_after/double(Pfix.size()) ) ; // le passate successive utilizzano quindi come trasformazione iniziale questa appena trovata. // Nei prossimi cicli si parte da questa matrice come iniziale. out=newout; assert(Pfix.size()==Pmov.size()); int tts2=clock(); ttsearch+=tts1-tts0; ttleast +=tts2-tts1; ii.pcl50=H.Percentile(.5); ii.pclhi=H.Percentile(ap.PassHiFilter); ii.AVG=H.Avg(); ii.RMS=H.RMS(); ii.StdDev=H.StandardDeviation(); ii.Time=clock(); as.I.push_back(ii); nc++; // The distance of the next points to be considered is lowered according to the <ReduceFactor> parameter. // We use 5 times the <ReduceFactor> percentile of the found points. if(ap.ReduceFactorPerc<1) StartMinDist=max(ap.MinDistAbs*ap.MinMinDistPerc, min(StartMinDist,5.0*H.Percentile(ap.ReduceFactorPerc))); } while ( nc<=ap.MaxIterNum && H.Percentile(.5) > ap.TrgDistAbs && (nc<ap.EndStepNum+1 || ! as.Stable(ap.EndStepNum) ) ); /**************** END ICP LOOP ****************/ int tt2=clock(); Matrix44d ResCopy=out; Point3d scv,shv,rtv,trv; Decompose(ResCopy,scv,shv,rtv,trv); if(math::Abs(1-scv[0])>ap.MaxScale || math::Abs(1-scv[1])>ap.MaxScale || math::Abs(1-scv[2])>ap.MaxScale ) { status = TOO_MUCH_SCALE; return false; } if(shv[0]>ap.MaxShear || shv[1]>ap.MaxShear || shv[2]>ap.MaxShear ) { status = TOO_MUCH_SHEAR; return false; } printf("Grid %i %i %i - fn %i\n",u.siz[0],u.siz[1],u.siz[2],fix->fn); printf("Init %8.3f Loop %8.3f Search %8.3f least sqrt %8.3f\n", float(tt1-tt0)/CLOCKS_PER_SEC, float(tt2-tt1)/CLOCKS_PER_SEC, float(ttsearch)/CLOCKS_PER_SEC,float(ttleast)/CLOCKS_PER_SEC ); return true; }
void FixedRenderer::drawScene(Scene * scene, OCamera * camera) { struct MEntityLight { Box3d lightBox; OLight * light; }; struct MSubMeshPass { unsigned int subMeshId; unsigned int lightsNumber; Object3d * object; OLight * lights[4]; }; // sub objects #define MAX_TRANSP_SUBOBJ 4096 static int transpList[MAX_TRANSP_SUBOBJ]; static float transpZList[MAX_TRANSP_SUBOBJ]; static MSubMeshPass transpSubObjs[MAX_TRANSP_SUBOBJ]; // lights list #define MAX_ENTITY_LIGHTS 256 static int entityLightsList[MAX_ENTITY_LIGHTS]; static float entityLightsZList[MAX_ENTITY_LIGHTS]; static MEntityLight entityLights[MAX_ENTITY_LIGHTS]; // get render RenderingContext * render = NeoEngine::getInstance()->getRenderingContext(); render->enableLighting(); render->enableBlending(); // make frustum Frustum * frustum = camera->getFrustum(); frustum->makeVolume(camera); // update visibility updateVisibility(scene, camera); // fog enableFog(camera); // camera Vector3 cameraPos = camera->getTransformedPosition(); // transp sub obj number unsigned int transpSubObsNumber = 0; // lights unsigned int l; unsigned int lSize = scene->getLightsNumber(); // entities unsigned int i; unsigned int eSize = scene->getEntitiesNumber(); for(i=0; i<eSize; i++) { // get entity OEntity * entity = scene->getEntityByIndex(i); Mesh * mesh = entity->getMesh(); if(! entity->isActive()) continue; if(! entity->isVisible()) { if(mesh) { Armature * armature = mesh->getArmature(); ArmatureAnim * armatureAnim = mesh->getArmatureAnim(); if(armature) { // animate armature if(mesh->getArmature()) { Armature * armature = mesh->getArmature(); if(mesh->getArmatureAnim()) { animateArmature( mesh->getArmature(), mesh->getArmatureAnim(), entity->getCurrentFrame() ); } else { armature->processBonesLinking(); armature->updateBonesSkinMatrix(); } } // TODO : optimize and add a tag to desactivate it updateSkinning(mesh, armature); (*entity->getBoundingBox()) = (*mesh->getBoundingBox()); } } continue; } // draw mesh if(mesh) { Vector3 scale = entity->getTransformedScale(); Box3d * entityBox = entity->getBoundingBox(); float minScale = scale.x; minScale = MIN(minScale, scale.y); minScale = MIN(minScale, scale.z); minScale = 1.0f / minScale; unsigned int entityLightsNumber = 0; for(l=0; l<lSize; l++) { // get entity OLight * light = scene->getLightByIndex(l); if(! light->isActive()) continue; if(! light->isVisible()) continue; // light box Vector3 lightPos = light->getTransformedPosition(); Vector3 localPos = entity->getInversePosition(lightPos); float localRadius = light->getRadius() * minScale; Box3d lightBox( Vector3(localPos - localRadius), Vector3(localPos + localRadius) ); if(! entityBox->isInCollisionWith(lightBox)) continue; MEntityLight * entityLight = &entityLights[entityLightsNumber]; entityLight->lightBox = lightBox; entityLight->light = light; entityLightsNumber++; if(entityLightsNumber == MAX_ENTITY_LIGHTS) break; } // animate armature if(mesh->getArmature()) { Armature * armature = mesh->getArmature(); if(mesh->getArmatureAnim()) { animateArmature( mesh->getArmature(), mesh->getArmatureAnim(), entity->getCurrentFrame() ); } else { armature->processBonesLinking(); armature->updateBonesSkinMatrix(); } } // animate textures if(mesh->getTexturesAnim()) animateTextures(mesh, mesh->getTexturesAnim(), entity->getCurrentFrame()); // animate materials if(mesh->getMaterialsAnim()) animateMaterials(mesh, mesh->getMaterialsAnim(), entity->getCurrentFrame()); unsigned int s; unsigned int sSize = mesh->getSubMeshsNumber(); for(s=0; s<sSize; s++) { SubMesh * subMesh = &mesh->getSubMeshs()[s]; Box3d * box = subMesh->getBoundingBox(); // check if submesh visible if(sSize > 1) { Vector3 * min = &box->min; Vector3 * max = &box->max; Vector3 points[8] = { entity->getTransformedVector(Vector3(min->x, min->y, min->z)), entity->getTransformedVector(Vector3(min->x, max->y, min->z)), entity->getTransformedVector(Vector3(max->x, max->y, min->z)), entity->getTransformedVector(Vector3(max->x, min->y, min->z)), entity->getTransformedVector(Vector3(min->x, min->y, max->z)), entity->getTransformedVector(Vector3(min->x, max->y, max->z)), entity->getTransformedVector(Vector3(max->x, max->y, max->z)), entity->getTransformedVector(Vector3(max->x, min->y, max->z)) }; if(! frustum->isVolumePointsVisible(points, 8)) continue; } // subMesh center Vector3 center = box->min + (box->max - box->min)*0.5f; center = entity->getTransformedVector(center); // sort entity lights unsigned int lightsNumber = 0; for(l=0; l<entityLightsNumber; l++) { MEntityLight * entityLight = &entityLights[l]; if(! box->isInCollisionWith(entityLight->lightBox)) continue; OLight * light = entityLight->light; float z = (center - light->getTransformedPosition()).getLength(); entityLightsList[lightsNumber] = l; entityLightsZList[l] = (1.0f/z)*light->getRadius(); lightsNumber++; } if(lightsNumber > 1) sortFloatList(entityLightsList, entityLightsZList, 0, (int)lightsNumber-1); // local lights if(lightsNumber > 4) lightsNumber = 4; for(l=0; l<lightsNumber; l++) { MEntityLight * entityLight = &entityLights[entityLightsList[l]]; OLight * light = entityLight->light; // attenuation float quadraticAttenuation = (8.0f / light->getRadius()); quadraticAttenuation = (quadraticAttenuation*quadraticAttenuation)*light->getIntensity(); // color Vector3 color = light->getFinalColor(); // set light render->enableLight(l); render->setLightPosition(l, light->getTransformedPosition()); render->setLightDiffuse(l, Vector4(color)); render->setLightSpecular(l, Vector4(color)); render->setLightAmbient(l, Vector3(0, 0, 0)); render->setLightAttenuation(l, 1, 0, quadraticAttenuation); // spot render->setLightSpotAngle(l, light->getSpotAngle()); if(light->getSpotAngle() < 90){ render->setLightSpotDirection(l, light->getRotatedVector(Vector3(0, 0, -1)).getNormalized()); render->setLightSpotExponent(l, light->getSpotExponent()); } else { render->setLightSpotExponent(l, 0.0f); } } for(l=lightsNumber; l<4; l++){ render->disableLight(l); } render->pushMatrix(); render->multMatrix(entity->getMatrix()); // draw opaques drawOpaques(subMesh, mesh->getArmature()); if(subMesh->hasTransparency()) { if(transpSubObsNumber < MAX_TRANSP_SUBOBJ) { // transparent subMesh pass MSubMeshPass * subMeshPass = &transpSubObjs[transpSubObsNumber]; // lights subMeshPass->lightsNumber = lightsNumber; for(l=0; l<lightsNumber; l++) subMeshPass->lights[l] = entityLights[entityLightsList[l]].light; // z distance to camera float z = getDistanceToCam(camera, center); // set values transpList[transpSubObsNumber] = transpSubObsNumber; transpZList[transpSubObsNumber] = z; subMeshPass->subMeshId = s; subMeshPass->object = entity; transpSubObsNumber++; } } render->popMatrix(); } mesh->updateBoundingBox(); (*entity->getBoundingBox()) = (*mesh->getBoundingBox()); } } // texts unsigned int tSize = scene->getTextsNumber(); for(i=0; i<tSize; i++) { OText * text = scene->getTextByIndex(i); if(text->isActive() && text->isVisible()) { // transparent pass MSubMeshPass * subMeshPass = &transpSubObjs[transpSubObsNumber]; // center Box3d * box = text->getBoundingBox(); Vector3 center = box->min + (box->max - box->min)*0.5f; center = text->getTransformedVector(center); // z distance to camera float z = getDistanceToCam(camera, center); // set values transpList[transpSubObsNumber] = transpSubObsNumber; transpZList[transpSubObsNumber] = z; subMeshPass->object = text; transpSubObsNumber++; } } // sort transparent list if(transpSubObsNumber > 1) sortFloatList(transpList, transpZList, 0, (int)transpSubObsNumber-1); // draw transparents render->setDepthMask(0); for(i=0; i<transpSubObsNumber; i++) { MSubMeshPass * subMeshPass = &transpSubObjs[transpList[i]]; Object3d * object = subMeshPass->object; // objects switch(object->getType()) { case M_OBJECT3D_ENTITY: { OEntity * entity = (OEntity *)object; unsigned int subMeshId = subMeshPass->subMeshId; Mesh * mesh = entity->getMesh(); SubMesh * subMesh = &mesh->getSubMeshs()[subMeshId]; // animate armature if(mesh->getArmature()) { Armature * armature = mesh->getArmature(); if(mesh->getArmatureAnim()) { animateArmature( mesh->getArmature(), mesh->getArmatureAnim(), entity->getCurrentFrame() ); } else { armature->processBonesLinking(); armature->updateBonesSkinMatrix(); } } // animate textures if(mesh->getTexturesAnim()) animateTextures(mesh, mesh->getTexturesAnim(), entity->getCurrentFrame()); // animate materials if(mesh->getMaterialsAnim()) animateMaterials(mesh, mesh->getMaterialsAnim(), entity->getCurrentFrame()); // lights for(l=0; l<subMeshPass->lightsNumber; l++) { OLight * light = subMeshPass->lights[l]; // attenuation float quadraticAttenuation = (8.0f / light->getRadius()); quadraticAttenuation = (quadraticAttenuation*quadraticAttenuation)*light->getIntensity(); // color Vector3 color = light->getFinalColor(); // set light render->enableLight(l); render->setLightPosition(l, light->getTransformedPosition()); render->setLightDiffuse(l, Vector4(color)); render->setLightSpecular(l, Vector4(color)); render->setLightAmbient(l, Vector3(0, 0, 0)); render->setLightAttenuation(l, 1, 0, quadraticAttenuation); // spot render->setLightSpotAngle(l, light->getSpotAngle()); if(light->getSpotAngle() < 90){ render->setLightSpotDirection(l, light->getRotatedVector(Vector3(0, 0, -1)).getNormalized()); render->setLightSpotExponent(l, light->getSpotExponent()); } else { render->setLightSpotExponent(l, 0.0f); } } for(l=subMeshPass->lightsNumber; l<4; l++){ render->disableLight(l); } render->pushMatrix(); render->multMatrix(entity->getMatrix()); drawTransparents(subMesh, mesh->getArmature()); render->popMatrix(); mesh->updateBoundingBox(); (*entity->getBoundingBox()) = (*mesh->getBoundingBox()); } break; case M_OBJECT3D_TEXT: { OText * text = (OText *)object; render->pushMatrix(); render->multMatrix(text->getMatrix()); drawText(text); render->popMatrix(); } break; } } render->setDepthMask(1); render->disableLighting(); render->disableFog(); }