void LLVOCacheEntry::calcSceneContribution(const LLVector4a& camera_origin, bool needs_update, U32 last_update, F32 max_dist) { if(!needs_update && getVisible() >= last_update) { return; //no need to update } LLVector4a lookAt; lookAt.setSub(getPositionGroup(), camera_origin); F32 distance = lookAt.getLength3().getF32(); distance -= sNearRadius; if(distance <= 0.f) { //nearby objects, set a large number const F32 LARGE_SCENE_CONTRIBUTION = 1000.f; //a large number to force to load the object. mSceneContrib = LARGE_SCENE_CONTRIBUTION; } else { F32 rad = getBinRadius(); max_dist += rad; if(distance + sNearRadius < max_dist) { mSceneContrib = (rad * rad) / distance; } else { mSceneContrib = 0.f; //out of draw distance, not to load } } setVisible(); }
BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) { //VECTORIZE THIS //get area of circle around face LLVector4a center; center.load3(getPositionAgent().mV); LLVector4a size; size.setSub(mExtents[1], mExtents[0]); size.mul(0.5f); LLViewerCamera* camera = LLViewerCamera::getInstance(); F32 size_squared = size.dot3(size).getF32(); LLVector4a lookAt; LLVector4a t; t.load3(camera->getOrigin().mV); lookAt.setSub(center, t); F32 dist = lookAt.getLength3().getF32(); dist = llmax(dist-size.getLength3().getF32(), 0.f); lookAt.normalize3fast() ; //get area of circle around node F32 app_angle = atanf((F32) sqrt(size_squared) / dist); radius = app_angle*LLDrawable::sCurPixelAngle; mPixelArea = radius*radius * 3.14159f; LLVector4a x_axis; x_axis.load3(camera->getXAxis().mV); cos_angle_to_view_dir = lookAt.dot3(x_axis).getF32(); if(dist < mBoundingSphereRadius) //camera is very close { cos_angle_to_view_dir = 1.0f; mImportanceToCamera = 1.0f; } else { mImportanceToCamera = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist); } return true; }
void LLVOCacheEntry::setBoundingInfo(const LLVector3& pos, const LLVector3& scale) { LLVector4a center, newMin, newMax; center.load3(pos.mV); LLVector4a size; size.load3(scale.mV); newMin.setSub(center, size); newMax.setAdd(center, size); setPositionGroup(center); setSpatialExtents(newMin, newMax); if(getNumOfChildren() > 0) //has children { updateParentBoundingInfo(); } else { setBinRadius(llmin(size.getLength3().getF32() * 4.f, 256.f)); } }
bool LLViewerOctreeCull::checkProjectionArea(const LLVector4a& center, const LLVector4a& size, const LLVector3& shift, F32 pixel_threshold, F32 near_radius) { LLVector3 local_orig = mCamera->getOrigin() - shift; LLVector4a origin; origin.load3(local_orig.mV); LLVector4a lookAt; lookAt.setSub(center, origin); F32 distance = lookAt.getLength3().getF32(); if(distance <= near_radius) { return true; //always load close-by objects } // treat object as if it were near_radius meters closer than it actually was. // this allows us to get some temporal coherence on visibility...objects that can be reached quickly will tend to be visible distance -= near_radius; F32 squared_rad = size.dot3(size).getF32(); return squared_rad / distance > pixel_threshold; }
//make the parent bounding box to include this child void LLVOCacheEntry::updateParentBoundingInfo(const LLVOCacheEntry* child) { const LLVector4a* child_exts = child->getSpatialExtents(); LLVector4a newMin, newMax; newMin = child_exts[0]; newMax = child_exts[1]; //move to regional space. { const LLVector4a& parent_pos = getPositionGroup(); newMin.add(parent_pos); newMax.add(parent_pos); } //update parent's bbox(min, max) const LLVector4a* parent_exts = getSpatialExtents(); update_min_max(newMin, newMax, parent_exts[0]); update_min_max(newMin, newMax, parent_exts[1]); for(S32 i = 0; i < 4; i++) { llclamp(newMin[i], 0.f, 256.f); llclamp(newMax[i], 0.f, 256.f); } setSpatialExtents(newMin, newMax); //update parent's bbox center LLVector4a center; center.setAdd(newMin, newMax); center.mul(0.5f); setPositionGroup(center); //update parent's bbox size vector LLVector4a size; size.setSub(newMax, newMin); size.mul(0.5f); setBinRadius(llmin(size.getLength3().getF32() * 4.f, 256.f)); }
void LLSpatialBridge::updateSpatialExtents() { LLSpatialGroup* root = (LLSpatialGroup*) mOctree->getListener(0); { LLFastTimer ftm(FTM_CULL_REBOUND); root->rebound(); } LLVector4a offset; LLVector4a size = root->mBounds[1]; //VECTORIZE THIS LLMatrix4a mat; mat.loadu(mDrawable->getXform()->getWorldMatrix()); LLVector4a t; t.splat(0.f); LLVector4a center; mat.affineTransform(t, center); mat.rotate(root->mBounds[0], offset); center.add(offset); LLVector4a v[4]; //get 4 corners of bounding box mat.rotate(size,v[0]); LLVector4a scale; scale.set(-1.f, -1.f, 1.f); scale.mul(size); mat.rotate(scale, v[1]); scale.set(1.f, -1.f, -1.f); scale.mul(size); mat.rotate(scale, v[2]); scale.set(-1.f, 1.f, -1.f); scale.mul(size); mat.rotate(scale, v[3]); LLVector4a& newMin = mExtents[0]; LLVector4a& newMax = mExtents[1]; newMin = newMax = center; for (U32 i = 0; i < 4; i++) { LLVector4a delta; delta.setAbs(v[i]); LLVector4a min; min.setSub(center, delta); LLVector4a max; max.setAdd(center, delta); newMin.setMin(newMin, min); newMax.setMax(newMax, max); } LLVector4a diagonal; diagonal.setSub(newMax, newMin); mRadius = diagonal.getLength3().getF32() * 0.5f; mPositionGroup.setAdd(newMin,newMax); mPositionGroup.mul(0.5f); updateBinRadius(); }
BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, const LLMatrix4& mat_vert_in, const LLMatrix3& mat_normal_in, BOOL global_volume) { LLMemType mt1(LLMemType::MTYPE_DRAWABLE); //get bounding box if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION #if MESH_ENABLED | LLDrawable::REBUILD_RIGGED #endif //MESH_ENABLED )) { //VECTORIZE THIS LLMatrix4a mat_vert; mat_vert.loadu(mat_vert_in); LLMatrix4a mat_normal; mat_normal.loadu(mat_normal_in); //if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) //{ //vertex buffer no longer valid // mVertexBuffer = NULL; // mLastVertexBuffer = NULL; //} //VECTORIZE THIS LLVector4a min,max; if (f >= volume.getNumVolumeFaces()) { llwarns << "Generating bounding box for invalid face index!" << llendl; f = 0; } const LLVolumeFace &face = volume.getVolumeFace(f); min = face.mExtents[0]; max = face.mExtents[1]; llassert(less_than_max_mag(min)); llassert(less_than_max_mag(max)); //min, max are in volume space, convert to drawable render space LLVector4a center; LLVector4a t; t.setAdd(min, max); t.mul(0.5f); mat_vert.affineTransform(t, center); LLVector4a size; size.setSub(max, min); size.mul(0.5f); llassert(less_than_max_mag(min)); llassert(less_than_max_mag(max)); if (!global_volume) { //VECTORIZE THIS LLVector4a scale; scale.load3(mDrawablep->getVObj()->getScale().mV); size.mul(scale); } mat_normal.mMatrix[0].normalize3fast(); mat_normal.mMatrix[1].normalize3fast(); mat_normal.mMatrix[2].normalize3fast(); LLVector4a v[4]; //get 4 corners of bounding box mat_normal.rotate(size,v[0]); //VECTORIZE THIS LLVector4a scale; scale.set(-1.f, -1.f, 1.f); scale.mul(size); mat_normal.rotate(scale, v[1]); scale.set(1.f, -1.f, -1.f); scale.mul(size); mat_normal.rotate(scale, v[2]); scale.set(-1.f, 1.f, -1.f); scale.mul(size); mat_normal.rotate(scale, v[3]); LLVector4a& newMin = mExtents[0]; LLVector4a& newMax = mExtents[1]; newMin = newMax = center; llassert(less_than_max_mag(center)); for (U32 i = 0; i < 4; i++) { LLVector4a delta; delta.setAbs(v[i]); LLVector4a min; min.setSub(center, delta); LLVector4a max; max.setAdd(center, delta); newMin.setMin(newMin,min); newMax.setMax(newMax,max); llassert(less_than_max_mag(newMin)); llassert(less_than_max_mag(newMax)); } if (!mDrawablep->isActive()) { LLVector4a offset; offset.load3(mDrawablep->getRegion()->getOriginAgent().mV); newMin.add(offset); newMax.add(offset); llassert(less_than_max_mag(newMin)); llassert(less_than_max_mag(newMax)); } t.setAdd(newMin, newMax); t.mul(0.5f); llassert(less_than_max_mag(t)); //VECTORIZE THIS mCenterLocal.set(t.getF32ptr()); llassert(less_than_max_mag(newMin)); llassert(less_than_max_mag(newMax)); t.setSub(newMax,newMin); mBoundingSphereRadius = t.getLength3().getF32()*0.5f; updateCenterAgent(); } return TRUE; }