void LLDrawable::updateTexture() { LLMemType mt(LLMemType::MTYPE_DRAWABLE); if (isDead()) { llwarns << "Dead drawable updating texture!" << llendl; return; } if (getNumFaces() != mVObjp->getNumTEs()) { //drawable is transitioning its face count return; } if (getVOVolume()) { /*if (isActive()) { if (isRoot()) { mQuietCount = 0; } else { getParent()->mQuietCount = 0; } }*/ gPipeline.markRebuild(this, LLDrawable::REBUILD_MATERIAL, TRUE); } }
const LLVector3 LLDrawable::getPositionAgent() const { if (getVOVolume()) { if (isActive()) { if (!isRoot()) { LLVector4a pos; pos.load3(mVObjp->getPosition().mV); getRenderMatrix().affineTransform(pos,pos); return LLVector3(pos.getF32ptr()); } else { return LLVector3(getRenderMatrix().getRow<3>().getF32ptr()); } } else { return mVObjp->getPositionAgent(); } } else { return getWorldPosition(); } }
void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp) { //precondition: mSpatialGroupp MUST be null or DEAD or mSpatialGroupp MUST NOT contain this llassert(!mSpatialGroupp || mSpatialGroupp->isDead() || !mSpatialGroupp->hasElement(this)); //precondition: groupp MUST be null or groupp MUST contain this llassert(!groupp || groupp->hasElement(this)); /*if (mSpatialGroupp && (groupp != mSpatialGroupp)) { mSpatialGroupp->setState(LLSpatialGroup::GEOM_DIRTY); }*/ if (mSpatialGroupp != groupp && getVOVolume()) { //NULL out vertex buffer references for volumes on spatial group change to maintain //requirement that every face vertex buffer is either NULL or points to a vertex buffer //contained by its drawable's spatial group for (S32 i = 0; i < getNumFaces(); ++i) { LLFace* facep = getFace(i); if (facep) { facep->clearVertexBuffer(); } } } //postcondition: if next group is NULL, previous group must be dead OR NULL OR binIndex must be -1 //postcondition: if next group is NOT NULL, binIndex must not be -1 llassert(groupp == NULL ? (mSpatialGroupp == NULL || mSpatialGroupp->isDead()) || getBinIndex() == -1 : getBinIndex() != -1); mSpatialGroupp = groupp; }
void LLDrawable::shiftPos(const LLVector3 &shift_vector) { if (isDead()) { llwarns << "Shifting dead drawable" << llendl; return; } if (mParent) { mXform.setPosition(mVObjp->getPosition()); } else { mXform.setPosition(mVObjp->getPositionAgent()); } mXform.setRotation(mVObjp->getRotation()); mXform.setScale(1,1,1); mXform.updateMatrix(); if (isStatic()) { LLVOVolume* volume = getVOVolume(); if (!volume) { gPipeline.markRebuild(this, LLDrawable::REBUILD_ALL, TRUE); } for (S32 i = 0; i < getNumFaces(); i++) { LLFace *facep = getFace(i); facep->mCenterAgent += shift_vector; facep->mExtents[0] += shift_vector; facep->mExtents[1] += shift_vector; if (!volume && facep->hasGeometry()) { facep->mVertexBuffer = NULL; facep->mLastVertexBuffer = NULL; } } mExtents[0] += shift_vector; mExtents[1] += shift_vector; mPositionGroup += LLVector3d(shift_vector); } else if (mSpatialBridge) { mSpatialBridge->shiftPos(shift_vector); } else if (isAvatar()) { mExtents[0] += shift_vector; mExtents[1] += shift_vector; mPositionGroup += LLVector3d(shift_vector); } mVObjp->onShift(shift_vector); }
void LLDrawable::updateDistance(LLCamera& camera, bool force_update) { if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD) { llwarns << "Attempted to update distance for non-world camera." << llendl; return; } //switch LOD with the spatial group to avoid artifacts //LLSpatialGroup* sg = getSpatialGroup(); LLVector3 pos; //if (!sg || sg->changeLOD()) { LLVOVolume* volume = getVOVolume(); if (volume) { if (getSpatialGroup()) { pos.set(getPositionGroup().getF32ptr()); } else { pos = getPositionAgent(); } if (isState(LLDrawable::HAS_ALPHA)) { for (S32 i = 0; i < getNumFaces(); i++) { LLFace* facep = getFace(i); if (force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA) { LLVector4a box; box.setSub(facep->mExtents[1], facep->mExtents[0]); box.mul(0.25f); LLVector3 v = (facep->mCenterLocal-camera.getOrigin()); const LLVector3& at = camera.getAtAxis(); for (U32 j = 0; j < 3; j++) { v.mV[j] -= box[j] * at.mV[j]; } facep->mDistance = v * camera.getAtAxis(); } } } } else { pos = LLVector3(getPositionGroup().getF32ptr()); } pos -= camera.getOrigin(); mDistanceWRTCamera = llround(pos.magVec(), 0.01f); mVObjp->updateLOD(); } }
void LLDrawable::updateDistance(LLCamera& camera, bool force_update) { //switch LOD with the spatial group to avoid artifacts //LLSpatialGroup* sg = getSpatialGroup(); LLVector3 pos; //if (!sg || sg->changeLOD()) { LLVOVolume* volume = getVOVolume(); if (volume) { volume->updateRelativeXform(); pos = volume->getRelativeXform().getTranslation(); if (isStatic()) { pos += volume->getRegion()->getOriginAgent(); } if (isState(LLDrawable::HAS_ALPHA)) { for (S32 i = 0; i < getNumFaces(); i++) { LLFace* facep = getFace(i); if (facep->getPoolType() == LLDrawPool::POOL_ALPHA) { LLVector3 box = (facep->mExtents[1] - facep->mExtents[0]) * 0.25f; LLVector3 v = (facep->mCenterLocal-camera.getOrigin()); const LLVector3& at = camera.getAtAxis(); for (U32 j = 0; j < 3; j++) { v.mV[j] -= box.mV[j] * at.mV[j]; } facep->mDistance = v * camera.getAtAxis(); } } } } else { pos = LLVector3(getPositionGroup()); } pos -= camera.getOrigin(); mDistanceWRTCamera = llround(pos.magVec(), 0.01f); mVObjp->updateLOD(); } }
void LLDrawable::updatePartition() { if (!getVOVolume()) { movePartition(); } else if (mSpatialBridge) { gPipeline.markMoved(mSpatialBridge, FALSE); } else { //a child prim moved and needs its verts regenerated gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } }
void LLDrawable::updateTexture() { if (isDead()) { LL_WARNS() << "Dead drawable updating texture!" << LL_ENDL; return; } if (getNumFaces() != mVObjp->getNumTEs()) { //drawable is transitioning its face count return; } if (getVOVolume()) { gPipeline.markRebuild(this, LLDrawable::REBUILD_MATERIAL, TRUE); } }
F32 LLDrawable::getVisibilityRadius() const { if (isDead()) { return 0.f; } else if (isLight()) { const LLVOVolume *vov = getVOVolume(); if (vov) { return llmax(getRadius(), vov->getLightRadius()); } else { // llwarns ? } } return getRadius(); }
LLSpatialPartition* LLDrawable::getSpatialPartition() { LLSpatialPartition* retval = NULL; if (!mVObjp || !getVOVolume() || isStatic()) { retval = gPipeline.getSpatialPartition((LLViewerObject*) mVObjp); } else if (isRoot()) { //must be an active volume if (!mSpatialBridge) { if (mVObjp->isHUDAttachment()) { setSpatialBridge(new LLHUDBridge(this)); } else if (mVObjp->isAttachment()) { setSpatialBridge(new LLAttachmentBridge(this)); } else { setSpatialBridge(new LLVolumeBridge(this)); } } return mSpatialBridge->asPartition(); } else { retval = getParent()->getSpatialPartition(); } if (retval && mSpatialBridge.notNull()) { mSpatialBridge->markDead(); setSpatialBridge(NULL); } return retval; }
void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp) { /*if (mSpatialGroupp && (groupp != mSpatialGroupp)) { mSpatialGroupp->setState(LLSpatialGroup::GEOM_DIRTY); }*/ if (mSpatialGroupp != groupp && getVOVolume()) { //NULL out vertex buffer references for volumes on spatial group change to maintain //requirement that every face vertex buffer is either NULL or points to a vertex buffer //contained by its drawable's spatial group for (S32 i = 0; i < getNumFaces(); ++i) { LLFace* facep = getFace(i); facep->clearVertexBuffer(); } } mSpatialGroupp = groupp; }
void LLDrawable::updateTexture() { LLMemType mt(LLMemType::MTYPE_DRAWABLE); if (isDead()) { llwarns << "Dead drawable updating texture!" << llendl; return; } if (getNumFaces() != mVObjp->getNumTEs()) { //drawable is transitioning its face count return; } if (getVOVolume()) { //getVOVolume()->mFaceMappingChanged = TRUE; gPipeline.markRebuild(this, LLDrawable::REBUILD_MATERIAL, TRUE); } }
const LLVector3 LLDrawable::getPositionAgent() const { if (getVOVolume()) { if (isActive()) { LLVector3 pos(0,0,0); if (!isRoot()) { pos = mVObjp->getPosition(); } return pos * getRenderMatrix(); } else { return mVObjp->getPositionAgent(); } } else { return getWorldPosition(); } }
void LLDrawable::setVisible(LLCamera& camera, std::vector<LLDrawable*>* results, BOOL for_select) { mVisible = sCurVisible; #if 0 && !LL_RELEASE_FOR_DOWNLOAD //crazy paranoid rules checking if (getVOVolume()) { if (!isRoot()) { if (isActive() && !mParent->isActive()) { llerrs << "Active drawable has static parent!" << llendl; } if (isStatic() && !mParent->isStatic()) { llerrs << "Static drawable has active parent!" << llendl; } if (mSpatialBridge) { llerrs << "Child drawable has spatial bridge!" << llendl; } } else if (isActive() && !mSpatialBridge) { llerrs << "Active root drawable has no spatial bridge!" << llendl; } else if (isStatic() && mSpatialBridge.notNull()) { llerrs << "Static drawable has spatial bridge!" << llendl; } } #endif }
void LLDrawable::shiftPos(const LLVector4a &shift_vector) { if (isDead()) { LL_WARNS() << "Shifting dead drawable" << LL_ENDL; return; } if (mParent) { mXform.setPosition(mVObjp->getPosition()); } else { mXform.setPosition(mVObjp->getPositionAgent()); } mXform.updateMatrix(); if (isStatic()) { LLVOVolume* volume = getVOVolume(); bool rebuild = (!volume && getRenderType() != LLPipeline::RENDER_TYPE_TREE && getRenderType() != LLPipeline::RENDER_TYPE_TERRAIN && getRenderType() != LLPipeline::RENDER_TYPE_SKY && getRenderType() != LLPipeline::RENDER_TYPE_GROUND); if (rebuild) { gPipeline.markRebuild(this, LLDrawable::REBUILD_ALL, TRUE); } for (S32 i = 0; i < getNumFaces(); i++) { LLFace *facep = getFace(i); if (facep) { facep->mCenterAgent += LLVector3(shift_vector.getF32ptr()); facep->mExtents[0].add(shift_vector); facep->mExtents[1].add(shift_vector); if (rebuild && facep->hasGeometry()) { facep->clearVertexBuffer(); } } } mExtents[0].add(shift_vector); mExtents[1].add(shift_vector); mPositionGroup.add(shift_vector); } else if (mSpatialBridge) { mSpatialBridge->shiftPos(shift_vector); } else if (isAvatar()) { mExtents[0].add(shift_vector); mExtents[1].add(shift_vector); mPositionGroup.add(shift_vector); } mVObjp->onShift(shift_vector); }
// Returns "distance" between target destination and resulting xfrom F32 LLDrawable::updateXform(BOOL undamped) { BOOL damped = !undamped; // Position LLVector3 old_pos(mXform.getPosition()); LLVector3 target_pos; if (mXform.isRoot()) { // get root position in your agent's region target_pos = mVObjp->getPositionAgent(); } else { // parent-relative position target_pos = mVObjp->getPosition(); } // Rotation LLQuaternion old_rot(mXform.getRotation()); LLQuaternion target_rot = mVObjp->getRotation(); //scaling LLVector3 target_scale = mVObjp->getScale(); LLVector3 old_scale = mCurrentScale; // Damping F32 dist_squared = 0.f; F32 camdist2 = (mDistanceWRTCamera * mDistanceWRTCamera); if (damped && isVisible()) { F32 lerp_amt = llclamp(LLCriticalDamp::getInterpolant(OBJECT_DAMPING_TIME_CONSTANT), 0.f, 1.f); LLVector3 new_pos = lerp(old_pos, target_pos, lerp_amt); dist_squared = dist_vec_squared(new_pos, target_pos); LLQuaternion new_rot = nlerp(lerp_amt, old_rot, target_rot); // FIXME: This can be negative! It is be possible for some rots to 'cancel out' pos or size changes. dist_squared += (1.f - dot(new_rot, target_rot)) * 10.f; LLVector3 new_scale = lerp(old_scale, target_scale, lerp_amt); dist_squared += dist_vec_squared(new_scale, target_scale); if ((dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED * camdist2) && (dist_squared <= MAX_INTERPOLATE_DISTANCE_SQUARED)) { // interpolate target_pos = new_pos; target_rot = new_rot; target_scale = new_scale; } else if (mVObjp->getAngularVelocity().isExactlyZero()) { // snap to final position (only if no target omega is applied) dist_squared = 0.0f; if (getVOVolume() && !isRoot()) { //child prim snapping to some position, needs a rebuild gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } } } else { // The following fixes MAINT-1742 but breaks vehicles similar to MAINT-2275 // dist_squared = dist_vec_squared(old_pos, target_pos); // The following fixes MAINT-2247 but causes MAINT-2275 //dist_squared += (1.f - dot(old_rot, target_rot)) * 10.f; //dist_squared += dist_vec_squared(old_scale, target_scale); } LLVector3 vec = mCurrentScale-target_scale; if (vec*vec > MIN_INTERPOLATE_DISTANCE_SQUARED) { //scale change requires immediate rebuild mCurrentScale = target_scale; gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } else if (!isRoot() && (!mVObjp->getAngularVelocity().isExactlyZero() || dist_squared > 0.f)) { //child prim moving relative to parent, tag as needing to be rendered atomically and rebuild dist_squared = 1.f; //keep this object on the move list if (!isState(LLDrawable::ANIMATED_CHILD)) { setState(LLDrawable::ANIMATED_CHILD); gPipeline.markRebuild(this, LLDrawable::REBUILD_ALL, TRUE); mVObjp->dirtySpatialGroup(); } } else if (!isRoot() && ((dist_vec_squared(old_pos, target_pos) > 0.f) || (1.f - dot(old_rot, target_rot)) > 0.f)) { //fix for BUG-840, MAINT-2275, MAINT-1742, MAINT-2247 gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } else if (!getVOVolume() && !isAvatar()) { movePartition(); } // Update mXform.setPosition(target_pos); mXform.setRotation(target_rot); mXform.setScale(LLVector3(1,1,1)); //no scale in drawable transforms (IT'S A RULE!) mXform.updateMatrix(); if (mSpatialBridge) { gPipeline.markMoved(mSpatialBridge, FALSE); } return dist_squared; }
// Returns "distance" between target destination and resulting xfrom F32 LLDrawable::updateXform(BOOL undamped) { BOOL damped = !undamped; // Position LLVector3 old_pos(mXform.getPosition()); LLVector3 target_pos; if (mXform.isRoot()) { // get root position in your agent's region target_pos = mVObjp->getPositionAgent(); } else { // parent-relative position target_pos = mVObjp->getPosition(); } // Rotation LLQuaternion old_rot(mXform.getRotation()); LLQuaternion target_rot = mVObjp->getRotation(); //scaling LLVector3 target_scale = mVObjp->getScale(); LLVector3 old_scale = mCurrentScale; LLVector3 dest_scale = target_scale; // Damping F32 dist_squared = 0.f; F32 camdist2 = (mDistanceWRTCamera * mDistanceWRTCamera); if (damped && isVisible()) { F32 lerp_amt = llclamp(LLCriticalDamp::getInterpolant(OBJECT_DAMPING_TIME_CONSTANT), 0.f, 1.f); LLVector3 new_pos = lerp(old_pos, target_pos, lerp_amt); dist_squared = dist_vec_squared(new_pos, target_pos); LLQuaternion new_rot = nlerp(lerp_amt, old_rot, target_rot); dist_squared += (1.f - dot(new_rot, target_rot)) * 10.f; LLVector3 new_scale = lerp(old_scale, target_scale, lerp_amt); dist_squared += dist_vec_squared(new_scale, target_scale); if ((dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED * camdist2) && (dist_squared <= MAX_INTERPOLATE_DISTANCE_SQUARED)) { // interpolate target_pos = new_pos; target_rot = new_rot; target_scale = new_scale; } else { // snap to final position dist_squared = 0.0f; if (getVOVolume() && !isRoot()) { //child prim snapping to some position, needs a rebuild gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } } } if ((mCurrentScale != target_scale) || (!isRoot() && (dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED || !mVObjp->getAngularVelocity().isExactlyZero() || target_pos != mXform.getPosition() || target_rot != mXform.getRotation()))) { //child prim moving or scale change requires immediate rebuild gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } else if (!getVOVolume() && !isAvatar()) { movePartition(); } // Update mXform.setPosition(target_pos); mXform.setRotation(target_rot); mXform.setScale(LLVector3(1,1,1)); //no scale in drawable transforms (IT'S A RULE!) mXform.updateMatrix(); mCurrentScale = target_scale; if (mSpatialBridge) { gPipeline.markMoved(mSpatialBridge, FALSE); } return dist_squared; }