int Grid::computeBounds(std::vector<Object::BoundingVolumeHierarchy::Node> &nodes, int uMin, int vMin, int uMax, int vMax) const { nodes.push_back(Object::BoundingVolumeHierarchy::Node()); int nodeIndex = nodes.size() - 1; Object::BoundingVolumeHierarchy::Node &node = nodes[nodeIndex]; if (uMax - uMin == 1 && vMax - vMin == 1) { node.index = -(vMin * mWidth + uMin); for (int i = uMin; i <= uMax; i++) { for (int j = vMin; j <= vMax; j++) { node.volume.expand(vertex(i, j).point); } } } else { if (uMax - uMin >= vMax - vMin) { int uSplit = (uMin + uMax) / 2; computeBounds(nodes, uMin, vMin, uSplit, vMax); node.index = computeBounds(nodes, uSplit, vMin, uMax, vMax); } else { int vSplit = (vMin + vMax) / 2; computeBounds(nodes, uMin, vMin, uMax, vSplit); node.index = computeBounds(nodes, uMin, vSplit, uMax, vMax); } node.volume.expand(nodes[nodeIndex + 1].volume); node.volume.expand(nodes[node.index].volume); } return nodeIndex; }
void GPBFile::adjust() { // calculate the ambient color for each scene for (std::list<Object*>::iterator i = _objects.begin(); i != _objects.end(); ++i) { Object* obj = *i; if (obj->getTypeId() == Object::SCENE_ID) { Scene* scene = dynamic_cast<Scene*>(obj); scene->calcAmbientColor(); } } for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i) { computeBounds(*i); } // try to convert joint transform animations into rotation animations //optimizeTransformAnimations(); // TODO: // remove ambient _lights // for each node // if node has ambient light // if node has no camera, mesh or children but 1 ambient light // delete node and remove from ref table // delete light and remove from ref table // // merge animations if possible // Search for animations that have the same target and key times and see if they can be merged. // Blender will output a simple translation animation to 3 separate animations with the same key times but targeting X, Y and Z. // This can be merged into one animation. Same for scale animations. }
void Shape::init(VertexList& vertexList, FaceList& faceList, STLVectorf& UVList) { setVertexList(vertexList); setFaceList(faceList); setUVCoord(UVList); color_list.resize(vertex_list.size(), 0.5); std::cout<<"Building face adjacent list...\n"; buildFaceAdj(); std::cout<<"Building 1-ring neighbors list...\n"; buildVertexShareFaces(); std::cout<<"Building vertex adjacent list...\n"; buildVertexAdj(); std::cout << "Building edge connectivity...\n"; computeEdgeConnectivity(); std::cout<<"Computing bounding box...\n"; computeBounds(); std::cout<<"Computing face normals...\n"; computeFaceNormal(); computeVertexNormal(); buildKDTree(); }
//-***************************************************************************** void MeshDrwHelper::update( P3fArraySamplePtr iP, V3fArraySamplePtr iN, Abc::Box3d iBounds ) { // Check validity. if ( !m_valid || !iP || !m_meshP || ( iP->size() != m_meshP->size() ) ) { makeInvalid(); return; } // Set meshP m_meshP = iP; if ( iBounds.isEmpty() ) { computeBounds(); } else { m_bounds = iBounds; } updateNormals( iN ); }
static void initEllipse(ellipse_t * ep, double cx, double cy, double a, double b, double theta, double lambda1, double lambda2) { ep->cx = cx; ep->cy = cy; ep->a = a; ep->b = b; ep->theta = theta; ep->eta1 = atan2(sin(lambda1) / b, cos(lambda1) / a); ep->eta2 = atan2(sin(lambda2) / b, cos(lambda2) / a); ep->cosTheta = cos(theta); ep->sinTheta = sin(theta); // make sure we have eta1 <= eta2 <= eta1 + 2*PI ep->eta2 -= TWOPI * floor((ep->eta2 - ep->eta1) / TWOPI); // the preceding correction fails if we have exactly eta2 - eta1 = 2*PI // it reduces the interval to zero length if ((lambda2 - lambda1 > M_PI) && (ep->eta2 - ep->eta1 < M_PI)) { ep->eta2 += TWOPI; } computeFoci(ep); computeEndPoints(ep); computeBounds(ep); /* Flatness parameters */ ep->f = (ep->a - ep->b) / ep->a; ep->e2 = ep->f * (2.0 - ep->f); ep->g = 1.0 - ep->f; ep->g2 = ep->g * ep->g; }
void Mesh::writeBinaryVertices(FILE* file) { if (vertices.size() > 0) { // Assumes that all vertices are the same size. // Write the number of bytes for the vertex data const Vertex& vertex = vertices.front(); write(vertices.size() * vertex.byteSize(), file); // (vertex count) * (vertex size) // for each vertex for (std::vector<Vertex>::const_iterator i = vertices.begin(); i != vertices.end(); ++i) { // Write this vertex i->writeBinary(file); } } else { // No vertex data write((unsigned int)0, file); } // Write bounds computeBounds(); write(&bounds.min.x, 3, file); write(&bounds.max.x, 3, file); write(&bounds.center.x, 3, file); write(bounds.radius, file); }
BVH2Builder::BVH2Builder(const BuildTriangle* triangles, size_t numTriangles, Ref<BVH2<Triangle4> > bvh) : triangles(triangles), numTriangles(numTriangles), bvh(bvh) { size_t numThreads = scheduler->getNumThreads(); /*! Allocate storage for nodes. Each thread should at least be able to get one block. */ allocatedNodes = numTriangles+numThreads*allocBlockSize; bvh->nodes = (BVH2<Triangle4>::Node*)alignedMalloc(allocatedNodes*sizeof(BVH2<Triangle4>::Node)); /*! Allocate storage for triangles. Each thread should at least be able to get one block. */ allocatedPrimitives = numTriangles+numThreads*allocBlockSize; bvh->triangles = (Triangle4*)alignedMalloc(allocatedPrimitives*sizeof(Triangle4)); /*! Allocate array for splitting primitive lists. 2*N required for parallel splits. */ prims = (Box*)alignedMalloc(2*numTriangles*sizeof(Box)); /*! initiate parallel computation of bounds */ ComputeBoundsTask computeBounds(triangles,numTriangles,prims); computeBounds.go(); /*! start build */ recurse(bvh->root,1,BuildRange(0,numTriangles,computeBounds.geomBound,computeBounds.centBound)); scheduler->go(); /*! rotate top part of tree */ for (int i=0; i<5; i++) bvh->rotate(bvh->root,4); /*! free temporary memory again */ bvh->nodes = (BVH2<Triangle4>::Node*) alignedRealloc(bvh->nodes ,atomicNextNode *sizeof(BVH2<Triangle4>::Node)); bvh->triangles = (Triangle4* ) alignedRealloc(bvh->triangles,atomicNextPrimitive*sizeof(Triangle4 )); bvh->allocatedNodes = atomicNextNode; bvh->allocatedTriangles = atomicNextPrimitive; alignedFree(prims); prims = NULL; }
void LayerBase::setGeometry( const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer) { layer.setDefaultState(); // this gives us only the "orientation" component of the transform const State& s(drawingState()); const uint32_t finalTransform = s.transform.getOrientation(); // we can only handle simple transformation if (finalTransform & Transform::ROT_INVALID) { layer.setTransform(0); } else { layer.setTransform(finalTransform); } if (!isOpaque()) { layer.setBlending(mPremultipliedAlpha ? HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE); } const Transform& tr = hw->getTransform(); Rect transformedBounds(computeBounds()); transformedBounds = tr.transform(transformedBounds); // scaling is already applied in transformedBounds layer.setFrame(transformedBounds); layer.setCrop(transformedBounds.getBounds()); }
const void * AbstractNode::getBounds() const { if (bounds==NULL) { bounds = computeBounds(); } return bounds; }
Model::Model(string filename) { readObj(filename); orientPoints(); computeBounds(); normalize(); findPointSizes(); }
Grid::Grid(int width, int height, std::vector<Vertex> &&vertices) : mWidth(width), mHeight(height), mVertices(std::move(vertices)) { std::vector<Object::BoundingVolumeHierarchy::Node> nodes; nodes.reserve(mWidth * mHeight * 2); computeBounds(nodes, 0, 0, mWidth - 1, mHeight - 1); mBoundingVolumeHierarchy = Object::BoundingVolumeHierarchy(std::move(nodes)); }
void Geometry::preCommit(RenderContext &) { auto ospGeometry = valueAs<OSPGeometry>(); if (!ospGeometry) { auto type = child("type").valueAs<std::string>(); ospGeometry = ospNewGeometry(type.c_str()); setValue(ospGeometry); child("bounds") = computeBounds(); } }
void Shape::updateShape(VertexList& new_vertex_list) { vertex_list = new_vertex_list; computeFaceNormal(); computeVertexNormal(); computeBounds(); buildKDTree(); }
void MeshAlg::computeBounds( const Array<Vector3>& vertexArray, const Array<int>& indexArray, AABox& box, Sphere& sphere) { Array<Vector3> newArray; newArray.resize(indexArray.size()); for (int i = 0; i < indexArray.size(); ++i) { newArray[i] = vertexArray[indexArray[i]]; } computeBounds(newArray, box, sphere); }
void BoundsDescriptor::operator+=(const BoundsDescriptor &bounds) { Tuple3f min, max; min.x = (minEndAABB.x < bounds.minEndAABB.x) ? minEndAABB.x : bounds.minEndAABB.x; min.y = (minEndAABB.y < bounds.minEndAABB.y) ? minEndAABB.y : bounds.minEndAABB.y; min.z = (minEndAABB.z < bounds.minEndAABB.z) ? minEndAABB.z : bounds.minEndAABB.z; max.x = (maxEndAABB.x > bounds.maxEndAABB.x) ? maxEndAABB.x : bounds.maxEndAABB.x; max.y = (maxEndAABB.y > bounds.maxEndAABB.y) ? maxEndAABB.y : bounds.maxEndAABB.y; max.z = (maxEndAABB.z > bounds.maxEndAABB.z) ? maxEndAABB.z : bounds.maxEndAABB.z; computeBounds(min, max); }
DrawGlyphs::DrawGlyphs(const Font& font, const GlyphBufferGlyph* glyphs, const GlyphBufferAdvance* advances, unsigned count, const FloatPoint& blockLocation, const FloatSize& localAnchor, FontSmoothingMode smoothingMode) : DrawingItem(ItemType::DrawGlyphs) , m_font(const_cast<Font&>(font)) , m_blockLocation(blockLocation) , m_localAnchor(localAnchor) , m_smoothingMode(smoothingMode) { m_glyphs.reserveInitialCapacity(count); m_advances.reserveInitialCapacity(count); for (unsigned i = 0; i < count; ++i) { m_glyphs.uncheckedAppend(glyphs[i]); m_advances.uncheckedAppend(advances[i]); } computeBounds(); }
void Model::postCommit(RenderContext &ctx) { auto model = valueAs<OSPModel>(); ctx.currentOSPModel = model; //instancegroup caches render calls in commit. for (auto &child : properties.children) child.second->finalize(ctx); ospCommit(model); ctx.currentOSPModel = stashedModel; // reset bounding box child("bounds") = box3f(empty); computeBounds(); }
//-***************************************************************************** void MeshDrwHelper::update( V3fArraySamplePtr iP, V3fArraySamplePtr iN ) { // Check validity. if ( !m_valid || !iP || !m_meshP || ( iP->size() != m_meshP->size() ) ) { makeInvalid(); return; } // Set meshP m_meshP = iP; computeBounds(); updateNormals( iN ); }
void Crop::ready(PointContext ctx) { #ifdef PDAL_HAVE_GEOS if (!m_poly.empty()) { m_geosEnvironment = initGEOS_r(pdal::geos::_GEOSWarningHandler, pdal::geos::_GEOSErrorHandler); m_geosGeometry = GEOSGeomFromWKT_r(m_geosEnvironment, m_poly.c_str()); if (!m_geosGeometry) throw pdal_error("unable to import polygon WKT"); int gtype = GEOSGeomTypeId_r(m_geosEnvironment, m_geosGeometry); if (!(gtype == GEOS_POLYGON || gtype == GEOS_MULTIPOLYGON)) throw pdal_error("input WKT was not a POLYGON or MULTIPOLYGON"); char* out_wkt = GEOSGeomToWKT_r(m_geosEnvironment, m_geosGeometry); log()->get(LogLevel::Debug2) << "Ingested WKT for filters.crop: " << std::string(out_wkt) <<std::endl; GEOSFree_r(m_geosEnvironment, out_wkt); if (!GEOSisValid_r(m_geosEnvironment, m_geosGeometry)) { char* reason = GEOSisValidReason_r(m_geosEnvironment, m_geosGeometry); std::ostringstream oss; oss << "WKT is invalid: " << std::string(reason) << std::endl; GEOSFree_r(m_geosEnvironment, reason); throw pdal_error(oss.str()); } m_geosPreparedGeometry = GEOSPrepare_r(m_geosEnvironment, m_geosGeometry); if (!m_geosPreparedGeometry) throw pdal_error("unable to prepare geometry for " "index-accelerated intersection"); m_bounds = computeBounds(m_geosGeometry); log()->get(LogLevel::Debug) << "Computed bounds from given WKT: " << m_bounds <<std::endl; } else { log()->get(LogLevel::Debug) << "Using simple bounds for " "filters.crop: " << m_bounds << std::endl; } #endif }
void Mesh::writeText(FILE* file) { fprintElementStart(file); // for each VertexFormat if (vertices.size() > 0 ) { for (std::vector<VertexElement>::iterator i = _vertexFormat.begin(); i != _vertexFormat.end(); i++) { i->writeText(file); } } // for each Vertex fprintf(file, "<vertices count=\"%lu\">\n", vertices.size()); for (std::vector<Vertex>::iterator i = vertices.begin(); i != vertices.end(); ++i) { i->writeText(file); } fprintf(file, "</vertices>\n"); // write bounds computeBounds(); fprintf(file, "<bounds>\n"); fprintf(file, "<min>\n"); writeVectorText(bounds.min, file); fprintf(file, "</min>\n"); fprintf(file, "<max>\n"); writeVectorText(bounds.max, file); fprintf(file, "</max>\n"); fprintf(file, "<center>\n"); writeVectorText(bounds.center, file); fprintf(file, "</center>\n"); fprintf(file, "<radius>%f</radius>\n", bounds.radius); fprintf(file, "</bounds>\n"); // for each MeshPart for (std::vector<MeshPart*>::iterator i = parts.begin(); i != parts.end(); ++i) { (*i)->writeText(file); } fprintElementEnd(file); }
void GPBFile::computeBounds(Node* node) { assert(node); if (Model* model = node->getModel()) { if (Mesh* mesh = model->getMesh()) { mesh->computeBounds(); } if (MeshSkin* skin = model->getSkin()) { skin->computeBounds(); } } for (Node* child = node->getFirstChild(); child != NULL; child = child->getNextSibling()) { computeBounds(child); } }
void MeshBuilder::centerTriList() { // Compute the range of the vertices Vector3 vmin, vmax; computeBounds(vmin, vmax); Vector3 diagonal = vmax - vmin; double scale = max(max(diagonal.x, diagonal.y), diagonal.z) / 2; debugAssert(scale > 0); Vector3 translation = vmin + diagonal / 2; // Center and scale all vertices in the input list int v; //Matrix3 rot90 = Matrix3::fromAxisAngle(Vector3::UNIT_Y, toRadians(180)) * Matrix3::fromAxisAngle(Vector3::UNIT_X, toRadians(90)); for (v = 0; v < triList.size(); ++v) { triList[v] = (triList[v] - translation) / scale; //triList[v] = rot90 * triList[v]; } }
void ArticulatedModel::moveToOrigin(bool centerY) { BoundsCallback boundsCallback; computeBounds(); forEachPart(boundsCallback); Vector3 translate = -boundsCallback.bounds.center(); if (! centerY) { translate.y += boundsCallback.bounds.extent().y * 0.5f; } alwaysAssertM(translate.isFinite(), "Cannot translate by non-finite amount or NaN"); const Matrix4& xform = Matrix4::translation(translate); // Center for (int p = 0; p < m_rootArray.size(); ++p) { Part* part = m_rootArray[p]; // Done so that moveToOrigin() and transformGeometry are commutative in the preprocessor part->transformGeometry(dynamic_pointer_cast<ArticulatedModel>(shared_from_this()), xform); //part->cframe.translation += translate; } }
/** Returns the bounding sphere (\p guaranteed to be up to date) that contains this Actor. \sa boundingSphere() */ const Sphere& boundingSphereSafe() { computeBounds(); return mSphere; }
bool PtexViewer::loadFile(std::string filename, int face) { Ptex::String ptexError; PtexPtr<PtexTexture> r(PtexTexture::open(filename.c_str(), ptexError, true)); _quads = true; if (!r) { fprintf(stderr,"%s\n",ptexError.c_str()); return false; } if (face>=r->numFaces()) { std::cerr << "Invalid face ID requested" << std::endl; return false; } removeSceneData(); _numFaces = r->numFaces(); _typeStr = Ptex::DataTypeName(r->dataType()); _quads = r->meshType()==Ptex::mt_quad; _mode3d = false; _envCube = false; if (_enable3D && r->numFaces()==6 && face<0) { // Test for environment cube case _envCube = true; int adjfaces[6][4] = { { 3, 5, 2, 4 }, // px { 3, 4, 2, 5 }, // nx { 4, 0, 5, 1 }, // py { 5, 0, 4, 1 }, // ny { 3, 0, 2, 1 }, // pz { 3, 1, 2, 0 } // nz }; int fi = 0; while (fi<6 && _envCube) { const Ptex::FaceInfo& f = r->getFaceInfo(fi); for (int v=0; v<4; v++) if (f.adjfaces[v]!=adjfaces[fi][v]) _envCube = false; fi++; } } if (_envCube) { // Construct environment cube geometry float cubeVerts[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,-1, 1}, {-1,-1, 1}, {-1, 1,-1}, {1, 1,-1}, {1, 1, 1}, {-1, 1, 1} }; int cubeInds[6][4] = { {2,1,5,6}, {0,3,7,4}, {7,6,5,4}, {0,1,2,3}, {3,2,6,7}, {1,0,4,5} }; for (int i=0; i<8; i++) _geometry.addVertex(cubeVerts[i]); for (int fi=0; fi<6; fi++) { const Ptex::FaceInfo& f = r->getFaceInfo(fi); polygon q; for (int v=0; v<4; v++) q.indices[v] = cubeInds[fi][v]; q.ures = f.res.u(); q.vres = f.res.v(); _geometry.addFace(q); } _mode3d = true; } else { if (_enable3D) _mode3d = _geometry.loadFromMetaData(r); if (_geometry.empty()) _geometry.makeFlatGeom(r); for (int fi=0; fi<r->numFaces(); fi++) { polygon* q = _geometry.getFace(fi); if (!q) continue; const Ptex::FaceInfo& f = r->getFaceInfo(fi); q->ures = f.res.u(); q->vres = f.res.v(); } } _geometry.makePages(r); computeBounds(); return true; }
void AttributeFilter::UpdateGEOSBuffer(PointBuffer& buffer, AttributeInfo& info) { QuadIndex idx(buffer); idx.build(); if (!info.lyr) // wake up the layer { if (info.layer.size()) info.lyr = OGR_DS_GetLayerByName(info.ds.get(), info.layer.c_str()); else if (info.query.size()) { info.lyr = OGR_DS_ExecuteSQL(info.ds.get(), info.query.c_str(), 0, 0); } else info.lyr = OGR_DS_GetLayer(info.ds.get(), 0); if (!info.lyr) { std::ostringstream oss; oss << "Unable to select layer '" << info.layer << "'"; throw pdal_error(oss.str()); } } OGRFeaturePtr feature = OGRFeaturePtr(OGR_L_GetNextFeature(info.lyr), OGRFeatureDeleter()); int field_index(1); // default to first column if nothing was set if (info.column.size()) { field_index = OGR_F_GetFieldIndex(feature.get(), info.column.c_str()); if (field_index == -1) { std::ostringstream oss; oss << "No column name '" << info.column << "' was found."; throw pdal_error(oss.str()); } } while(feature) { OGRGeometryH geom = OGR_F_GetGeometryRef(feature.get()); OGRwkbGeometryType t = OGR_G_GetGeometryType(geom); int f_count = OGR_F_GetFieldCount (feature.get()); if (!(t == wkbPolygon || t == wkbMultiPolygon || t == wkbPolygon25D || t == wkbMultiPolygon25D)) { std::ostringstream oss; oss << "Geometry is not Polygon or MultiPolygon!"; throw pdal::pdal_error(oss.str()); } OGRGeometry* ogr_g = (OGRGeometry*) geom; GEOSGeometry* geos_g (0); if (!m_geosEnvironment) { #if (GDAL_VERSION_MINOR < 11) && (GDAL_VERSION_MAJOR == 1) geos_g = ogr_g->exportToGEOS(); #else m_geosEnvironment = ogr_g->createGEOSContext(); geos_g = ogr_g->exportToGEOS(m_geosEnvironment); #endif } GEOSPreparedGeometry const* geos_pg = GEOSPrepare_r(m_geosEnvironment, geos_g); if (!geos_pg) throw pdal_error("unable to prepare geometry for index-accelerated intersection"); // Compute a total bounds for the geometry. Query the QuadTree to // find out the points that are inside the bbox. Then test each // point in the bbox against the prepared geometry. BOX3D box = computeBounds(m_geosEnvironment, geos_g); std::vector<std::size_t> ids = idx.getPoints(box); for (const auto& i : ids) { double x = buffer.getFieldAs<double>(Dimension::Id::X, i); double y = buffer.getFieldAs<double>(Dimension::Id::Y, i); double z = buffer.getFieldAs<double>(Dimension::Id::Z, i); GEOSGeometry* p = createGEOSPoint(m_geosEnvironment, x, y ,z); if (static_cast<bool>(GEOSPreparedContains_r(m_geosEnvironment, geos_pg, p))) { // We're in the poly, write the attribute value int32_t v = OGR_F_GetFieldAsInteger(feature.get(), field_index); buffer.setField(info.dim, i, v); // log()->get(LogLevel::Debug) << "Setting value: " << v << std::endl; } GEOSGeom_destroy_r(m_geosEnvironment, p); } feature = OGRFeaturePtr(OGR_L_GetNextFeature(info.lyr), OGRFeatureDeleter()); } }
void computePathBounds(const SkPath* path, const SkPaint* paint, float& left, float& top, float& offset, uint32_t& width, uint32_t& height) { const SkRect& bounds = path->getBounds(); computeBounds(bounds, paint, left, top, offset, width, height); }
// Install into the TSShape, the shape is expected to be empty. // Data is not copied, the TSShape is modified to point to memory // managed by this object. This object is also bound to the TSShape // object and will be deleted when it's deleted. void TSShapeLoader::install() { // Arrays that are filled in by ts shape init, but need // to be allocated beforehand. shape->subShapeFirstTranslucentObject.setSize(shape->subShapeFirstObject.size()); // Construct TS sub-meshes shape->meshes.setSize(appMeshes.size()); for (U32 m = 0; m < appMeshes.size(); m++) shape->meshes[m] = appMeshes[m] ? appMeshes[m]->constructTSMesh() : NULL; // Remove empty meshes and objects for (S32 iObj = shape->objects.size()-1; iObj >= 0; iObj--) { TSShape::Object& obj = shape->objects[iObj]; for (S32 iMesh = obj.numMeshes-1; iMesh >= 0; iMesh--) { TSMesh *mesh = shape->meshes[obj.startMeshIndex + iMesh]; if (mesh && !mesh->primitives.size()) { S32 oldMeshCount = obj.numMeshes; destructInPlace(mesh); shape->removeMeshFromObject(iObj, iMesh); iMesh -= (oldMeshCount - obj.numMeshes - 1); // handle when more than one mesh is removed } } if (!obj.numMeshes) shape->removeObject(shape->getName(obj.nameIndex)); } // Add a dummy object if needed so the shape loads and renders ok if (!shape->details.size()) { shape->addDetail("detail", 2, 0); shape->subShapeNumObjects.last() = 1; shape->meshes.push_back(NULL); shape->objects.increment(); shape->objects.last().nameIndex = shape->addName("dummy"); shape->objects.last().nodeIndex = 0; shape->objects.last().startMeshIndex = 0; shape->objects.last().numMeshes = 1; shape->objectStates.increment(); shape->objectStates.last().frameIndex = 0; shape->objectStates.last().matFrameIndex = 0; shape->objectStates.last().vis = 1.0f; } // Update smallest visible detail shape->mSmallestVisibleDL = -1; shape->mSmallestVisibleSize = 999999; for (S32 i = 0; i < shape->details.size(); i++) { if ((shape->details[i].size >= 0) && (shape->details[i].size < shape->mSmallestVisibleSize)) { shape->mSmallestVisibleDL = i; shape->mSmallestVisibleSize = shape->details[i].size; } } computeBounds(shape->bounds); if (!shape->bounds.isValidBox()) shape->bounds = Box3F(1.0f); shape->bounds.getCenter(&shape->center); shape->radius = (shape->bounds.maxExtents - shape->center).len(); shape->tubeRadius = shape->radius; shape->init(); }
//-***************************************************************************** void MeshDrwHelper::update( P3fArraySamplePtr iP, V3fArraySamplePtr iN, Int32ArraySamplePtr iIndices, Int32ArraySamplePtr iCounts, Abc::Box3d iBounds ) { // Before doing a ton, just have a quick look. if ( m_meshP && iP && ( m_meshP->size() == iP->size() ) && m_meshIndices && ( m_meshIndices == iIndices ) && m_meshCounts && ( m_meshCounts == iCounts ) ) { if ( m_meshP == iP ) { updateNormals( iN ); } else { update( iP, iN ); } return; } // Okay, if we're here, the indices are not equal or the counts // are not equal or the P-array size changed. // So we can clobber those three, but leave N alone for now. m_meshP = iP; m_meshIndices = iIndices; m_meshCounts = iCounts; m_triangles.clear (); // Check stuff. if ( !m_meshP || !m_meshIndices || !m_meshCounts ) { std::cerr << "Mesh update quitting because no input data" << std::endl; makeInvalid(); return; } // Get the number of each thing. size_t numFaces = m_meshCounts->size(); size_t numIndices = m_meshIndices->size(); size_t numPoints = m_meshP->size(); if ( numFaces < 1 || numIndices < 1 || numPoints < 1 ) { // Invalid. std::cerr << "Mesh update quitting because bad arrays" << ", numFaces = " << numFaces << ", numIndices = " << numIndices << ", numPoints = " << numPoints << std::endl; makeInvalid(); return; } // Make triangles. size_t faceIndexBegin = 0; size_t faceIndexEnd = 0; for ( size_t face = 0; face < numFaces; ++face ) { faceIndexBegin = faceIndexEnd; size_t count = (*m_meshCounts)[face]; faceIndexEnd = faceIndexBegin + count; // Check this face is valid if ( faceIndexEnd > numIndices || faceIndexEnd < faceIndexBegin ) { std::cerr << "Mesh update quitting on face: " << face << " because of wonky numbers" << ", faceIndexBegin = " << faceIndexBegin << ", faceIndexEnd = " << faceIndexEnd << ", numIndices = " << numIndices << ", count = " << count << std::endl; // Just get out, make no more triangles. break; } // Checking indices are valid. bool goodFace = true; for ( size_t fidx = faceIndexBegin; fidx < faceIndexEnd; ++fidx ) { if ( ( size_t ) ( (*m_meshIndices)[fidx] ) >= numPoints ) { std::cout << "Mesh update quitting on face: " << face << " because of bad indices" << ", indexIndex = " << fidx << ", vertexIndex = " << (*m_meshIndices)[fidx] << ", numPoints = " << numPoints << std::endl; goodFace = false; break; } } // Make triangles to fill this face. if ( goodFace && count > 2 ) { m_triangles.push_back( Tri( ( unsigned int )(*m_meshIndices)[faceIndexBegin+0], ( unsigned int )(*m_meshIndices)[faceIndexBegin+1], ( unsigned int )(*m_meshIndices)[faceIndexBegin+2] ) ); for ( size_t c = 3; c < count; ++c ) { m_triangles.push_back( Tri( ( unsigned int )(*m_meshIndices)[faceIndexBegin+0], ( unsigned int )(*m_meshIndices)[faceIndexBegin+c-1], ( unsigned int )(*m_meshIndices)[faceIndexBegin+c] ) ); } } } // Cool, we made triangles. // Pretend the mesh is made... m_valid = true; // And now update just the P and N, which will update bounds // and calculate new normals if necessary. if ( iBounds.isEmpty() ) { computeBounds(); } else { m_bounds = iBounds; } updateNormals( iN ); // And that's it. }
/** Returns the bounding box (\p guaranteed to be up to date) that contains this Actor. \sa boundingBox() */ const AABB& boundingBoxSafe() { computeBounds(); return mAABB; }