void LLViewerObjectList::shiftObjects(const LLVector3 &offset) { // This is called when we shift our origin when we cross region boundaries... // We need to update many object caches, I'll document this more as I dig through the code // cleaning things out... if (gNoRender || 0 == offset.magVecSquared()) { return; } LLViewerObject *objectp; for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) { objectp = *iter; // There could be dead objects on the object list, so don't update stuff if the object is dead. if (objectp && !objectp->isDead()) { objectp->updatePositionCaches(); if (objectp->mDrawable.notNull() && !objectp->mDrawable->isDead()) { gPipeline.markShift(objectp->mDrawable); } } } gPipeline.shiftObjects(offset); LLWorld::getInstance()->shiftRegions(offset); }
void LLViewerObjectList::shiftObjects(const LLVector3 &offset) { // This is called when we shift our origin when we cross region boundaries... // We need to update many object caches, I'll document this more as I dig through the code // cleaning things out... if (gNoRender || 0 == offset.magVecSquared()) { return; } LLViewerObject *objectp; S32 i; for (i = 0; i < mObjects.count(); i++) { objectp = getObject(i); // There could be dead objects on the object list, so don't update stuff if the object is dead. if (objectp) { objectp->updatePositionCaches(); if (objectp->mDrawable.notNull() && !objectp->mDrawable->isDead()) { gPipeline.markShift(objectp->mDrawable); } } } gPipeline.shiftObjects(offset); gWorldPointer->mPartSim.shift(offset); }
BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TREE))) { return TRUE; } S32 trunk_LOD = sMAX_NUM_TREE_LOD_LEVELS ; F32 app_angle = getAppAngle()*LLVOTree::sTreeFactor; for (S32 j = 0; j < sMAX_NUM_TREE_LOD_LEVELS; j++) { if (app_angle > LLVOTree::sLODAngles[j]) { trunk_LOD = j; break; } } if (mReferenceBuffer.isNull()) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); } else if (trunk_LOD != mTrunkLOD) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, FALSE); } else { // we're not animating but we may *still* need to // regenerate the mesh if we moved, since position // and rotation are baked into the mesh. // *TODO: I don't know what's so special about trees // that they don't get REBUILD_POSITION automatically // at a higher level. const LLVector3 &this_position = getPositionAgent(); if (this_position != mLastPosition) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION); mLastPosition = this_position; } else { const LLQuaternion &this_rotation = getRotation(); if (this_rotation != mLastRotation) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION); mLastRotation = this_rotation; } } } mTrunkLOD = trunk_LOD; return TRUE; }
void LLViewerJointAttachment::setupDrawable(LLViewerObject *object) { if (!object->mDrawable) return; if (object->mDrawable->isActive()) { object->mDrawable->makeStatic(FALSE); } object->mDrawable->mXform.setParent(getXform()); // LLViewerJointAttachment::lazyAttach object->mDrawable->makeActive(); LLVector3 current_pos = object->getRenderPosition(); LLQuaternion current_rot = object->getRenderRotation(); LLQuaternion attachment_pt_inv_rot = ~(getWorldRotation()); current_pos -= getWorldPosition(); current_pos.rotVec(attachment_pt_inv_rot); current_rot = current_rot * attachment_pt_inv_rot; object->mDrawable->mXform.setPosition(current_pos); object->mDrawable->mXform.setRotation(current_rot); gPipeline.markMoved(object->mDrawable); gPipeline.markTextured(object->mDrawable); // face may need to change draw pool to/from POOL_HUD object->mDrawable->setState(LLDrawable::USE_BACKLIGHT); if(mIsHUDAttachment) { for (S32 face_num = 0; face_num < object->mDrawable->getNumFaces(); face_num++) { object->mDrawable->getFace(face_num)->setState(LLFace::HUD_RENDER); } } LLViewerObject::const_child_list_t& child_list = object->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); iter != child_list.end(); ++iter) { LLViewerObject* childp = *iter; if (childp && childp->mDrawable.notNull()) { childp->mDrawable->setState(LLDrawable::USE_BACKLIGHT); gPipeline.markTextured(childp->mDrawable); // face may need to change draw pool to/from POOL_HUD gPipeline.markMoved(childp->mDrawable); if(mIsHUDAttachment) { for (S32 face_num = 0; face_num < childp->mDrawable->getNumFaces(); face_num++) { childp->mDrawable->getFace(face_num)->setState(LLFace::HUD_RENDER); } } } } }
void LLSky::updateCull() { /*if (mVOSkyp.notNull() && mVOSkyp->mDrawable.notNull()) { gPipeline.markVisible(mVOSkyp->mDrawable); } else { llinfos << "No sky drawable!" << llendl; }*/ if (mVOStarsp.notNull() && mVOStarsp->mDrawable.notNull()) { gPipeline.markVisible(mVOStarsp->mDrawable, *gCamera); } else { llinfos << "No stars drawable!" << llendl; } /*if (mVOGroundp.notNull() && mVOGroundp->mDrawable.notNull()) { gPipeline.markVisible(mVOGroundp->mDrawable); }*/ }
//static added one block for openregion ----- voodoo void LLSurface::rebuildWater() { //lldebugs << "Rebuilding Water..."; //BOOL renderwater = gSavedSettings.getBOOL("RenderWater") && LLWorld::getInstance()->getAllowRenderWater(); if(!mWaterObjp.isNull()) //if(prev_renderwater && !renderwater) { //lldebugs << "Removing Water"; //Remove the old gObjectList.killObject(mWaterObjp); } if (gSavedSettings.getBOOL("RenderWater") && gHippoLimits->mRenderWater) //if (!prev_renderwater && renderwater) { //lldebugs << "Building Water"; createWaterTexture(); mWaterObjp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, mRegionp); gPipeline.createObject(mWaterObjp); LLVector3d water_pos_global = from_region_handle(mRegionp->getHandle()); water_pos_global += LLVector3d(128.0, 128.0, DEFAULT_WATER_HEIGHT); //water_pos_global += LLVector3d(mRegionp->getWidth()/2, mRegionp->getWidth()/2, DEFAULT_WATER_HEIGHT); mWaterObjp->setPositionGlobal(water_pos_global); } //lldebugs << "Rebuilding Water Complete"; }
void LLCloudGroup::updatePuffs(const F32 dt) { mDensity = mCloudLayerp->getDensityRegion(mCenterRegion); if (!mVOCloudsp) { mVOCloudsp = (LLVOClouds *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_CLOUDS, mCloudLayerp->getRegion()); if(mVOCloudsp) { mVOCloudsp->setCloudGroup(this); mVOCloudsp->setPositionRegion(mCenterRegion); mVOCloudsp->setScale(LLVector3(256.f/CLOUD_GROUPS_PER_EDGE + CLOUD_PUFF_WIDTH, 256.f/CLOUD_GROUPS_PER_EDGE + CLOUD_PUFF_WIDTH, CLOUD_HEIGHT_RANGE + CLOUD_PUFF_HEIGHT)*0.5f); gPipeline.createObject(mVOCloudsp); } } LLVector3 velocity; LLVector3d vel_d; // Update the positions of all of the clouds for (U32 i = 0; i < mCloudPuffs.size(); i++) { LLCloudPuff &puff = mCloudPuffs[i]; velocity = mCloudLayerp->getRegion()->mWind.getCloudVelocity(mCloudLayerp->getRegion()->getPosRegionFromGlobal(puff.mPositionGlobal)); velocity *= CLOUD_VELOCITY_SCALE*CLOUD_UPDATE_RATE; vel_d.setVec(velocity); mCloudPuffs[i].mPositionGlobal += vel_d; mCloudPuffs[i].mAlpha += mCloudPuffs[i].mRate * dt; mCloudPuffs[i].mAlpha = llmin(1.f, mCloudPuffs[i].mAlpha); mCloudPuffs[i].mAlpha = llmax(0.f, mCloudPuffs[i].mAlpha); } }
void LLSurface::initTextures() { /////////////////////// // // Main surface texture // createSTexture(); /////////////////////// // // Water texture // if (gSavedSettings.getBOOL("RenderWater") ) { createWaterTexture(); mWaterObjp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, mRegionp); gPipeline.createObject(mWaterObjp); LLVector3d water_pos_global = from_region_handle(mRegionp->getHandle()); // <FS:CR> Aurora Sim //water_pos_global += LLVector3d(128.0, 128.0, DEFAULT_WATER_HEIGHT); // region doesn't have a valid water height yet water_pos_global += LLVector3d(mRegionp->getWidth()/2, mRegionp->getWidth()/2, DEFAULT_WATER_HEIGHT); mWaterObjp->setPositionGlobal(water_pos_global); // </FS:CR> Aurora Sim } }
void LLViewerObjectList::renderPickList(const LLRect& screen_rect, BOOL pick_parcel_wall, BOOL render_transparent) { gRenderForSelect = TRUE; gPipeline.renderForSelect(mSelectPickList, render_transparent, screen_rect); // // Render pass for selected objects // gGL.color4f(1,1,1,1); gViewerWindow->renderSelections( TRUE, pick_parcel_wall, FALSE ); //fix for DEV-19335. Don't pick hud objects when customizing avatar (camera mode doesn't play nice with nametags). if (!gAgent.cameraCustomizeAvatar()) { // render pickable ui elements, like names, etc. LLHUDObject::renderAllForSelect(); } gGL.flush(); LLVertexBuffer::unbind(); gRenderForSelect = FALSE; //llinfos << "Rendered " << count << " for select" << llendl; //llinfos << "Took " << pick_timer.getElapsedTimeF32()*1000.f << "ms to pick" << llendl; }
void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp, void** user_data, U32 i, const EObjectUpdateType update_type, LLDataPacker* dpp, BOOL just_created) { LLMessageSystem* msg = gMessageSystem; // ignore returned flags objectp->processUpdateMessage(msg, user_data, i, update_type, dpp); if (objectp->isDead()) { // The update failed return; } updateActive(objectp); // Also sets the approx. pixel area objectp->setPixelAreaAndAngle(gAgent); // Update the image levels of textures for this object. objectp->updateTextures(gAgent); if (just_created) { gPipeline.addObject(objectp); } else { primbackup::getInstance()->prim_update(objectp); } // RN: this must be called after we have a drawable // (from gPipeline.addObject) // so that the drawable parent is set properly findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort()); // If we're just wandering around, don't create new objects selected. if (just_created && update_type != OUT_TERSE_IMPROVED && objectp->mCreateSelected) { if ( gToolMgr->getCurrentTool() != gToolPie ) { //llinfos << "DEBUG selecting " << objectp->mID << " " // << objectp->mLocalID << llendl; gSelectMgr->selectObjectAndFamily(objectp); dialog_refresh_all(); } objectp->mCreateSelected = false; gViewerWindow->getWindow()->decBusyCount(); gViewerWindow->getWindow()->setCursor( UI_CURSOR_ARROW ); primbackup::getInstance()->newprim(objectp); } }
void LLViewerObjectList::relightAllObjects() { for (S32 i = 0; i < mObjects.count(); i++) { LLDrawable *drawable = mObjects[i]->mDrawable; if (drawable) { gPipeline.markRelight(drawable); } } }
void LLVOTree::updateTextures() { if (mTreeImagep) { if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { setDebugText(llformat("%4.0f", fsqrtf(mPixelArea))); } mTreeImagep->addTextureStats(mPixelArea); } }
void LLSurfacePatch::setSurface(LLSurface *surfacep) { mSurfacep = surfacep; if (mVObjp == (LLVOSurfacePatch *)NULL) { llassert(mSurfacep->mType == 'l'); mVObjp = (LLVOSurfacePatch *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_SURFACE_PATCH, mSurfacep->getRegion()); mVObjp->setPatch(this); mVObjp->setPositionRegion(mCenterRegion); gPipeline.addObject(mVObjp); } }
LLSurface::~LLSurface() { delete [] mSurfaceZ; mSurfaceZ = NULL; delete [] mNorm; mGridsPerEdge = 0; mGridsPerPatchEdge = 0; mPatchesPerEdge = 0; mNumberOfPatches = 0; destroyPatchData(); LLDrawPoolTerrain *poolp = (LLDrawPoolTerrain*) gPipeline.findPool(LLDrawPool::POOL_TERRAIN, mSTexturep); if (!poolp) { llwarns << "No pool for terrain on destruction!" << llendl; } else if (poolp->mReferences.empty()) { gPipeline.removePool(poolp); // Don't enable this until we blitz the draw pool for it as well. -- djs if (mSTexturep) { gImageList.deleteImage(mSTexturep); mSTexturep = NULL; } if (mWaterTexturep) { gImageList.deleteImage(mWaterTexturep); mWaterTexturep = NULL; } } else { llerrs << "Terrain pool not empty!" << llendl; } }
void LLSky::init(const LLVector3 &sun_direction) { mVOSkyp = (LLVOSky *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_SKY, gAgent.getRegion()); mVOSkyp->initSunDirection(sun_direction, LLVector3()); gPipeline.addObject((LLViewerObject *)mVOSkyp); mVOStarsp = (LLVOStars *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_STARS, gAgent.getRegion()); gPipeline.addObject((LLViewerObject *)mVOStarsp); mVOGroundp = (LLVOGround*)gObjectList.createObjectViewer(LLViewerObject::LL_VO_GROUND, gAgent.getRegion()); LLVOGround *groundp = mVOGroundp; gPipeline.addObject((LLViewerObject *)groundp); gSky.setFogRatio(gSavedSettings.getF32("RenderFogRatio")); //////////////////////////// // // Legacy code, ignore // // // Get the parameters. mSunDefaultPosition = gSavedSettings.getVector3("SkySunDefaultPosition"); if (gSavedSettings.getBOOL("SkyOverrideSimSunPosition") || mOverrideSimSunPosition) { setSunDirection(mSunDefaultPosition, LLVector3(0.f, 0.f, 0.f)); } else { setSunDirection(sun_direction, LLVector3(0.f, 0.f, 0.f)); } mUpdatedThisFrame = TRUE; }
BOOL LLSurfacePatch::updateTexture() { if (mSTexUpdate) // Update texture as needed { F32 meters_per_grid = getSurface()->getMetersPerGrid(); F32 grids_per_patch_edge = (F32)getSurface()->getGridsPerPatchEdge(); if ((!getNeighborPatch(EAST) || getNeighborPatch(EAST)->getHasReceivedData()) && (!getNeighborPatch(WEST) || getNeighborPatch(WEST)->getHasReceivedData()) && (!getNeighborPatch(SOUTH) || getNeighborPatch(SOUTH)->getHasReceivedData()) && (!getNeighborPatch(NORTH) || getNeighborPatch(NORTH)->getHasReceivedData())) { LLViewerRegion *regionp = getSurface()->getRegion(); LLVector3d origin_region = getOriginGlobal() - getSurface()->getOriginGlobal(); // Have to figure out a better way to deal with these edge conditions... LLVLComposition* comp = regionp->getComposition(); if (!mHeightsGenerated) { F32 patch_size = meters_per_grid*(grids_per_patch_edge+1); if (comp->generateHeights((F32)origin_region[VX], (F32)origin_region[VY], patch_size, patch_size)) { mHeightsGenerated = TRUE; } else { return FALSE; } } if (comp->generateComposition()) { if (mVObjp) { mVObjp->dirtyGeom(); gPipeline.markGLRebuild(mVObjp); return TRUE; } } } return FALSE; } else { return TRUE; } }
LLDrawable* LLVOTree::createDrawable(LLPipeline *pipeline) { pipeline->allocDrawable(this); mDrawable->setLit(FALSE); mDrawable->setRenderType(LLPipeline::RENDER_TYPE_TREE); LLDrawPoolTree *poolp = (LLDrawPoolTree*) gPipeline.getPool(LLDrawPool::POOL_TREE, mTreeImagep); // Just a placeholder for an actual object... LLFace *facep = mDrawable->addFace(poolp, mTreeImagep); facep->setSize(1, 3); updateRadius(); return mDrawable; }
void LLSky::updateSky() { if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY)) { return; } if (mVOSkyp) { mVOSkyp->updateSky(); } if (mVOStarsp) { //if (mVOStarsp->mDrawable) //{ // gPipeline.markRebuild(mVOStarsp->mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); //} } }
void LLSurface::rebuildWater() { BOOL renderwater = gSavedSettings.getBOOL("RenderWater") && LLWorld::getInstance()->getAllowRenderWater(); BOOL prev_renderwater = !mWaterObjp.isNull(); if(prev_renderwater && !renderwater) { gObjectList.killObject(mWaterObjp); } if (!prev_renderwater && renderwater) { createWaterTexture(); mWaterObjp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, mRegionp); gPipeline.createObject(mWaterObjp); LLVector3d water_pos_global = from_region_handle(mRegionp->getHandle()); water_pos_global += LLVector3d(mRegionp->getWidth()/2, mRegionp->getWidth()/2, DEFAULT_WATER_HEIGHT); mWaterObjp->setPositionGlobal(water_pos_global); } }
BOOL LLSurface::idleUpdate(F32 max_update_time) { LLMemType mt_ius(LLMemType::MTYPE_IDLE_UPDATE_SURFACE); if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TERRAIN)) { return FALSE; } // Perform idle time update of non-critical stuff. // In this case, texture and normal updates. LLTimer update_timer; BOOL did_update = FALSE; // If the Z height data has changed, we need to rebuild our // property line vertex arrays. if (mDirtyPatchList.size() > 0) { getRegion()->dirtyHeights(); } // Always call updateNormals() / updateVerticalStats() // every frame to avoid artifacts for(std::set<LLSurfacePatch *>::iterator iter = mDirtyPatchList.begin(); iter != mDirtyPatchList.end(); ) { std::set<LLSurfacePatch *>::iterator curiter = iter++; LLSurfacePatch *patchp = *curiter; patchp->updateNormals(); patchp->updateVerticalStats(); if (max_update_time == 0.f || update_timer.getElapsedTimeF32() < max_update_time) { if (patchp->updateTexture()) { did_update = TRUE; patchp->clearDirty(); mDirtyPatchList.erase(curiter); } } } return did_update; }
BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { const U16 FRAMES_PER_WIND_UPDATE = 20; // How many frames between wind update per tree const F32 TREE_WIND_SENSITIVITY = 0.005f; const F32 TREE_TRUNK_STIFFNESS = 0.1f; if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TREE))) { return TRUE; } F32 mass_inv; // For all tree objects, update the trunk bending with the current wind // Walk sprite list in order away from viewer if (!(mFrameCount % FRAMES_PER_WIND_UPDATE)) { // If needed, Get latest wind for this tree mWind = mRegionp->mWind.getVelocity(getPositionRegion()); } mFrameCount++; mass_inv = 1.f/(5.f + mDepth*mBranches*0.2f); mTrunkVel += (mWind * mass_inv * TREE_WIND_SENSITIVITY); // Pull in direction of wind mTrunkVel -= (mTrunkBend * mass_inv * TREE_TRUNK_STIFFNESS); // Restoring force in direction of trunk mTrunkBend += mTrunkVel; mTrunkVel *= 0.99f; // Add damping if (mTrunkBend.magVec() > 1.f) { mTrunkBend.normVec(); } if (mTrunkVel.magVec() > 1.f) { mTrunkVel.normVec(); } return TRUE; }
void LLSurface::initTextures() { /////////////////////// // // Main surface texture // createSTexture(); /////////////////////// // // Water texture // if (gSavedSettings.getBOOL("RenderWater") && LLWorld::getInstance()->getAllowRenderWater()) { createWaterTexture(); mWaterObjp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, mRegionp); gPipeline.createObject(mWaterObjp); LLVector3d water_pos_global = from_region_handle(mRegionp->getHandle()); water_pos_global += LLVector3d(mRegionp->getWidth()/2, mRegionp->getWidth()/2, DEFAULT_WATER_HEIGHT); mWaterObjp->setPositionGlobal(water_pos_global); } }
void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port) { if (gNoRender) { return; } if (objectp->isDead()) { llwarns << "Trying to find orphans for dead obj " << objectp->mID << ":" << objectp->getPCodeString() << llendl; return; } // See if we are a parent of an orphan. // Note: This code is fairly inefficient but it should happen very rarely. // It can be sped up if this is somehow a performance issue... if (0 == mOrphanParents.count()) { // no known orphan parents return; } if (-1 == mOrphanParents.find(getIndex(objectp->mLocalID, ip, port))) { // did not find objectp in OrphanParent list return; } S32 i; U64 parent_info = getIndex(objectp->mLocalID, ip, port); BOOL orphans_found = FALSE; // Iterate through the orphan list, and set parents of matching children. for (i = 0; i < mOrphanChildren.count(); i++) { if (mOrphanChildren[i].mParentInfo != parent_info) { continue; } LLViewerObject *childp = findObject(mOrphanChildren[i].mChildInfo); if (childp) { if (childp == objectp) { llwarns << objectp->mID << " has self as parent, skipping!" << llendl; continue; } #ifdef ORPHAN_SPAM llinfos << "Reunited parent " << objectp->mID << " with child " << childp->mID << llendl; llinfos << "Glob: " << objectp->getPositionGlobal() << llendl; llinfos << "Agent: " << objectp->getPositionAgent() << llendl; addDebugBeacon(objectp->getPositionAgent(),""); #endif gPipeline.markMoved(objectp->mDrawable); objectp->setChanged(LLXform::MOVED | LLXform::SILHOUETTE); // Flag the object as no longer orphaned childp->mOrphaned = FALSE; if (childp->mDrawable.notNull()) { // Make the drawable visible again and set the drawable parent childp->mDrawable->setState(LLDrawable::CLEAR_INVISIBLE); childp->setDrawableParent(objectp->mDrawable); // LLViewerObjectList::findOrphans() } // Make certain particles, icon and HUD aren't hidden childp->hideExtraDisplayItems( FALSE ); objectp->addChild(childp); orphans_found = TRUE; } else { llinfos << "Missing orphan child, removing from list" << llendl; mOrphanChildren.remove(i); i--; } } // Remove orphan parent and children from lists now that they've been found mOrphanParents.remove(mOrphanParents.find(parent_info)); i = 0; while (i < mOrphanChildren.count()) { if (mOrphanChildren[i].mParentInfo == parent_info) { mOrphanChildren.remove(i); mNumOrphans--; } else { i++; } } if (orphans_found && objectp->isSelected()) { LLSelectNode* nodep = gSelectMgr->getSelection()->findNode(objectp); if (nodep && !nodep->mIndividualSelection) { // rebuild selection with orphans gSelectMgr->deselectObjectAndFamily(objectp); gSelectMgr->selectObjectAndFamily(objectp); } } }
U32 LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, BOOL pick_parcel_wall, BOOL keep_pick_list) { gRenderForSelect = TRUE; // LLTimer pick_timer; if (!keep_pick_list) { LLViewerObject *objectp; S32 i; // Reset all of the GL names to zero. for (i = 0; i < mObjects.count(); i++) { objectp = mObjects[i]; objectp->mGLName = 0; } mSelectPickList.clear(); std::vector<LLDrawable*> pick_drawables; for (i = 0; i < LLPipeline::NUM_PARTITIONS-1; i++) { LLSpatialPartition* part = gPipeline.getSpatialPartition(i); if (part) { part->cull(camera, &pick_drawables, TRUE); } } for (std::vector<LLDrawable*>::iterator iter = pick_drawables.begin(); iter != pick_drawables.end(); iter++) { LLDrawable* drawablep = *iter; if( !drawablep ) continue; LLViewerObject* last_objectp = NULL; for (S32 face_num = 0; face_num < drawablep->getNumFaces(); face_num++) { LLViewerObject* objectp = drawablep->getFace(face_num)->getViewerObject(); if (objectp && objectp != last_objectp) { mSelectPickList.insert(objectp); last_objectp = objectp; } } } LLHUDText::addPickable(mSelectPickList); for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); iter != LLCharacter::sInstances.end(); ++iter) { objectp = (LLVOAvatar*) *iter; if (!objectp->isDead()) { if (objectp->mDrawable.notNull() && objectp->mDrawable->isVisible()) { mSelectPickList.insert(objectp); } } } // add all hud objects to pick list LLVOAvatar* avatarp = gAgent.getAvatarObject(); if (avatarp) { LLViewerJointAttachment* attachmentp; for (attachmentp = avatarp->mAttachmentPoints.getFirstData(); attachmentp; attachmentp = avatarp->mAttachmentPoints.getNextData()) { if (attachmentp->getIsHUDAttachment()) { LLViewerObject* objectp = attachmentp->getObject(); if (objectp) { mSelectPickList.insert(objectp); for (U32 i = 0; i < objectp->mChildList.size(); i++) { LLViewerObject* childp = objectp->mChildList[i]; if (childp) { mSelectPickList.insert(childp); } } } } } } S32 num_pickables = (S32)mSelectPickList.size() + LLHUDIcon::getNumInstances(); if (num_pickables != 0) { S32 step = (0x000fffff - GL_NAME_INDEX_OFFSET) / num_pickables; std::set<LLViewerObject*>::iterator pick_it; i = 0; for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end();) { LLViewerObject* objp = (*pick_it); if (!objp || objp->isDead() || !objp->mbCanSelect) { mSelectPickList.erase(pick_it++); continue; } objp->mGLName = (i * step) + GL_NAME_INDEX_OFFSET; i++; ++pick_it; } LLHUDIcon::generatePickIDs(i * step, step); // At this point, we should only have live drawables/viewer objects gPipeline.renderForSelect(mSelectPickList); } } // // Render pass for selected objects // gViewerWindow->renderSelections( TRUE, pick_parcel_wall, FALSE ); // render pickable ui elements, like names, etc. LLHUDObject::renderAllForSelect(); gRenderForSelect = FALSE; //llinfos << "Rendered " << count << " for select" << llendl; //llinfos << "Took " << pick_timer.getElapsedTimeF32()*1000.f << "ms to pick" << llendl; return 0; }
void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp, void** user_data, U32 i, const EObjectUpdateType update_type, LLDataPacker* dpp, BOOL just_created) { LLMessageSystem* msg = gMessageSystem; // ignore returned flags objectp->processUpdateMessage(msg, user_data, i, update_type, dpp); if (objectp->isDead()) { // The update failed return; } updateActive(objectp); if (just_created) { gPipeline.addObject(objectp); } // Also sets the approx. pixel area objectp->setPixelAreaAndAngle(gAgent); // RN: this must be called after we have a drawable // (from gPipeline.addObject) // so that the drawable parent is set properly findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort()); LLVector3 pScale=objectp->getScale(); if(objectp->permYouOwner()) { if(objectp->permModify() && objectp->permCopy() && objectp->permTransfer()) { if (gImportTracker.getState() != ImportTracker::IDLE && objectp) { if((gImportTracker.getState() == ImportTracker::WAND && just_created && objectp->mCreateSelected) || (pScale.mV[VX] == 0.52345f && pScale.mV[VY] == 0.52346f && pScale.mV[VZ] == 0.52347f && gImportTracker.getState() == ImportTracker::BUILDING)) gImportTracker.get_update(objectp->mLocalID, just_created, objectp->mCreateSelected); } } } // If we're just wandering around, don't create new objects selected. if (just_created && update_type != OUT_TERSE_IMPROVED && objectp->mCreateSelected) { if(JCExportTracker::getInstance()->getStatus() == JCExportTracker::EXPORTING && JCExportTracker::getInstance()->expected_surrogate_pos.count(objectp->getPosition()) > 0) { //the surrogate prim has been created, notify JCExportTracker JCExportTracker::getInstance()->queued_surrogates.push_back(objectp); JCExportTracker::getInstance()->surrogate_roots.push_back(objectp); } else if ( LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance() ) { //llinfos << "DEBUG selecting " << objectp->mID << " " // << objectp->mLocalID << llendl; LLSelectMgr::getInstance()->selectObjectAndFamily(objectp); dialog_refresh_all(); } objectp->mCreateSelected = false; gViewerWindow->getWindow()->decBusyCount(); gViewerWindow->getWindow()->setCursor( UI_CURSOR_ARROW ); } }
//----------------------------------------------------------------------------- // removeObject() //----------------------------------------------------------------------------- void LLViewerJointAttachment::removeObject(LLViewerObject *object) { attachedobjs_vec_t::iterator iter; for (iter = mAttachedObjects.begin(); iter != mAttachedObjects.end(); ++iter) { LLViewerObject *attached_object = (*iter); if (attached_object == object) { break; } } if (iter == mAttachedObjects.end()) { llwarns << "Could not find object to detach" << llendl; return; } // force object visibile setAttachmentVisibility(TRUE); mAttachedObjects.erase(iter); if (object->mDrawable.notNull()) { //if object is active, make it static if(object->mDrawable->isActive()) { object->mDrawable->makeStatic(FALSE) ; } LLVector3 cur_position = object->getRenderPosition(); LLQuaternion cur_rotation = object->getRenderRotation(); object->mDrawable->mXform.setPosition(cur_position); object->mDrawable->mXform.setRotation(cur_rotation); gPipeline.markMoved(object->mDrawable, TRUE); gPipeline.markTextured(object->mDrawable); // face may need to change draw pool to/from POOL_HUD object->mDrawable->clearState(LLDrawable::USE_BACKLIGHT); if (mIsHUDAttachment) { for (S32 face_num = 0; face_num < object->mDrawable->getNumFaces(); face_num++) { object->mDrawable->getFace(face_num)->clearState(LLFace::HUD_RENDER); } } } LLViewerObject::const_child_list_t& child_list = object->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); iter != child_list.end(); ++iter) { LLViewerObject* childp = *iter; if (childp && childp->mDrawable.notNull()) { childp->mDrawable->clearState(LLDrawable::USE_BACKLIGHT); gPipeline.markTextured(childp->mDrawable); // face may need to change draw pool to/from POOL_HUD if (mIsHUDAttachment) { for (S32 face_num = 0; face_num < childp->mDrawable->getNumFaces(); face_num++) { childp->mDrawable->getFace(face_num)->clearState(LLFace::HUD_RENDER); } } } } if (mIsHUDAttachment) { if (object->mText.notNull()) { object->mText->setOnHUDAttachment(FALSE); } LLViewerObject::const_child_list_t& child_list = object->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); iter != child_list.end(); ++iter) { LLViewerObject* childp = *iter; if (childp->mText.notNull()) { childp->mText->setOnHUDAttachment(FALSE); } } } if (mAttachedObjects.size() == 0) { mUpdateXform = FALSE; } object->setAttachmentItemID(LLUUID::null); }
U32 LLVOTree::drawBranchPipeline(LLMatrix4& matrix, U16* indicesp, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 scale, F32 twist, F32 droop, F32 branches, F32 alpha) { U32 ret = 0; // // Draws a tree by recursing, drawing branches and then a 'leaf' texture. // If stop_level = -1, simply draws the whole tree as a billboarded texture // static F32 constant_twist; static F32 width = 0; //F32 length = ((scale == 1.f)? mTrunkLength:mBranchLength); //F32 aspect = ((scale == 1.f)? mTrunkAspect:mBranchAspect); F32 length = ((trunk_depth || (scale == 1.f))? mTrunkLength:mBranchLength); F32 aspect = ((trunk_depth || (scale == 1.f))? mTrunkAspect:mBranchAspect); constant_twist = 360.f/branches; if (!LLPipeline::sReflectionRender && stop_level >= 0) { // // Draw the tree using recursion // if (depth > stop_level) { { llassert(sLODIndexCount[trunk_LOD] > 0); width = scale * length * aspect; LLMatrix4 scale_mat; scale_mat.mMatrix[0][0] = width; scale_mat.mMatrix[1][1] = width; scale_mat.mMatrix[2][2] = scale*length; scale_mat *= matrix; glLoadMatrixf((F32*) scale_mat.mMatrix); glDrawElements(GL_TRIANGLES, sLODIndexCount[trunk_LOD], GL_UNSIGNED_SHORT, indicesp + sLODIndexOffset[trunk_LOD]); gPipeline.addTrianglesDrawn(LEAF_INDICES/3); stop_glerror(); ret += sLODIndexCount[trunk_LOD]; } // Recurse to create more branches for (S32 i=0; i < (S32)branches; i++) { LLMatrix4 trans_mat; trans_mat.setTranslation(0,0,scale*length); trans_mat *= matrix; LLQuaternion rot = LLQuaternion(20.f*DEG_TO_RAD, LLVector4(0.f, 0.f, 1.f)) * LLQuaternion(droop*DEG_TO_RAD, LLVector4(0.f, 1.f, 0.f)) * LLQuaternion(((constant_twist + ((i%2==0)?twist:-twist))*i)*DEG_TO_RAD, LLVector4(0.f, 0.f, 1.f)); LLMatrix4 rot_mat(rot); rot_mat *= trans_mat; ret += drawBranchPipeline(rot_mat, indicesp, trunk_LOD, stop_level, depth - 1, 0, scale*mScaleStep, twist, droop, branches, alpha); } // Recurse to continue trunk if (trunk_depth) { LLMatrix4 trans_mat; trans_mat.setTranslation(0,0,scale*length); trans_mat *= matrix; LLMatrix4 rot_mat(70.5f*DEG_TO_RAD, LLVector4(0,0,1)); rot_mat *= trans_mat; // rotate a bit around Z when ascending ret += drawBranchPipeline(rot_mat, indicesp, trunk_LOD, stop_level, depth, trunk_depth-1, scale*mScaleStep, twist, droop, branches, alpha); } } else { // // Draw leaves as two 90 deg crossed quads with leaf textures // { LLMatrix4 scale_mat; scale_mat.mMatrix[0][0] = scale_mat.mMatrix[1][1] = scale_mat.mMatrix[2][2] = scale*mLeafScale; scale_mat *= matrix; glLoadMatrixf((F32*) scale_mat.mMatrix); glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_SHORT, indicesp); gPipeline.addTrianglesDrawn(LEAF_INDICES/3); stop_glerror(); ret += LEAF_INDICES; } } } else { // // Draw the tree as a single billboard texture // LLMatrix4 scale_mat; scale_mat.mMatrix[0][0] = scale_mat.mMatrix[1][1] = scale_mat.mMatrix[2][2] = mBillboardScale*mBillboardRatio; scale_mat *= matrix; glMatrixMode(GL_TEXTURE); glTranslatef(0.0, -0.5, 0.0); glMatrixMode(GL_MODELVIEW); glLoadMatrixf((F32*) scale_mat.mMatrix); glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_SHORT, indicesp); gPipeline.addTrianglesDrawn(LEAF_INDICES/3); stop_glerror(); ret += LEAF_INDICES; glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); } return ret; }
U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, EObjectUpdateType update_type, LLDataPacker *dp) { // Do base class updates... U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); if ( (getVelocity().lengthSquared() > 0.f) ||(getAcceleration().lengthSquared() > 0.f) ||(getAngularVelocity().lengthSquared() > 0.f)) { llinfos << "ACK! Moving tree!" << llendl; setVelocity(LLVector3::zero); setAcceleration(LLVector3::zero); setAngularVelocity(LLVector3::zero); } if (update_type == OUT_TERSE_IMPROVED) { // Nothing else needs to be done for the terse message. return retval; } // // Load Instance-Specific data // if (mData) { mSpecies = ((U8 *)mData)[0]; } if (!sSpeciesTable.count(mSpecies)) { if (sSpeciesTable.size()) { SpeciesMap::const_iterator it = sSpeciesTable.begin(); mSpecies = (*it).first; } } // // Load Species-Specific data // mTreeImagep = gImageList.getImage(sSpeciesTable[mSpecies]->mTextureID); if (mTreeImagep) { gGL.getTexUnit(0)->bind(mTreeImagep.get()); } mBranchLength = sSpeciesTable[mSpecies]->mBranchLength; mTrunkLength = sSpeciesTable[mSpecies]->mTrunkLength; mLeafScale = sSpeciesTable[mSpecies]->mLeafScale; mDroop = sSpeciesTable[mSpecies]->mDroop; mTwist = sSpeciesTable[mSpecies]->mTwist; mBranches = sSpeciesTable[mSpecies]->mBranches; mDepth = sSpeciesTable[mSpecies]->mDepth; mScaleStep = sSpeciesTable[mSpecies]->mScaleStep; mTrunkDepth = sSpeciesTable[mSpecies]->mTrunkDepth; mBillboardScale = sSpeciesTable[mSpecies]->mBillboardScale; mBillboardRatio = sSpeciesTable[mSpecies]->mBillboardRatio; mTrunkAspect = sSpeciesTable[mSpecies]->mTrunkAspect; mBranchAspect = sSpeciesTable[mSpecies]->mBranchAspect; // position change not caused by us, etc. make sure to rebuild. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL); return retval; }
BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { const U16 FRAMES_PER_WIND_UPDATE = 20; // How many frames between wind update per tree const F32 TREE_WIND_SENSITIVITY = 0.005f; const F32 TREE_TRUNK_STIFFNESS = 0.1f; if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TREE))) { return TRUE; } //it's cheaper to check if wind is enabled first if (gLLWindEnabled && gSavedSettings.getBOOL("RenderAnimateTrees")) { F32 mass_inv; // For all tree objects, update the trunk bending with the current wind // Walk sprite list in order away from viewer if (!(mFrameCount % FRAMES_PER_WIND_UPDATE)) { // If needed, Get latest wind for this tree mWind = mRegionp->mWind.getVelocity(getPositionRegion()); } mFrameCount++; mass_inv = 1.f/(5.f + mDepth*mBranches*0.2f); mTrunkVel += (mWind * mass_inv * TREE_WIND_SENSITIVITY); // Pull in direction of wind mTrunkVel -= (mTrunkBend * mass_inv * TREE_TRUNK_STIFFNESS); // Restoring force in direction of trunk mTrunkBend += mTrunkVel; mTrunkVel *= 0.99f; // Add damping if (mTrunkBend.length() > 1.f) { mTrunkBend.normalize(); } if (mTrunkVel.length() > 1.f) { mTrunkVel.normalize(); } } S32 trunk_LOD = 0; F32 app_angle = getAppAngle()*LLVOTree::sTreeFactor; for (S32 j = 0; j < 4; j++) { if (app_angle > LLVOTree::sLODAngles[j]) { trunk_LOD = j; break; } } if (!gLLWindEnabled || !gSavedSettings.getBOOL("RenderAnimateTrees")) { if (mReferenceBuffer.isNull()) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); } else if (trunk_LOD != mTrunkLOD) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, FALSE); } else { // we're not animating but we may *still* need to // regenerate the mesh if we moved, since position // and rotation are baked into the mesh. // *TODO: I don't know what's so special about trees // that they don't get REBUILD_POSITION automatically // at a higher level. const LLVector3 &this_position = getPositionAgent(); if (this_position != mLastPosition) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION); mLastPosition = this_position; } else { const LLQuaternion &this_rotation = getRotation(); if (this_rotation != mLastRotation) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION); mLastRotation = this_rotation; } } } } mTrunkLOD = trunk_LOD; return TRUE; }
//----------------------------------------------------------------------------- // removeObject() //----------------------------------------------------------------------------- void LLViewerJointAttachment::removeObject(LLViewerObject *object) { // force object visibile setAttachmentVisibility(TRUE); if (object->mDrawable.notNull()) { //if object is active, make it static if(object->mDrawable->isActive()) { object->mDrawable->makeStatic(FALSE) ; } LLVector3 cur_position = object->getRenderPosition(); LLQuaternion cur_rotation = object->getRenderRotation(); object->mDrawable->mXform.setPosition(cur_position); object->mDrawable->mXform.setRotation(cur_rotation); gPipeline.markMoved(object->mDrawable, TRUE); gPipeline.markTextured(object->mDrawable); // face may need to change draw pool to/from POOL_HUD object->mDrawable->clearState(LLDrawable::USE_BACKLIGHT); if (mIsHUDAttachment) { for (S32 face_num = 0; face_num < object->mDrawable->getNumFaces(); face_num++) { object->mDrawable->getFace(face_num)->clearState(LLFace::HUD_RENDER); } } } LLViewerObject::const_child_list_t& child_list = object->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); iter != child_list.end(); iter++) { LLViewerObject* childp = *iter; if (childp && childp->mDrawable.notNull()) { childp->mDrawable->clearState(LLDrawable::USE_BACKLIGHT); gPipeline.markTextured(childp->mDrawable); // face may need to change draw pool to/from POOL_HUD if (mIsHUDAttachment) { for (S32 face_num = 0; face_num < childp->mDrawable->getNumFaces(); face_num++) { childp->mDrawable->getFace(face_num)->clearState(LLFace::HUD_RENDER); } } } } if (mIsHUDAttachment) { if (object->mText.notNull()) { object->mText->setOnHUDAttachment(FALSE); } LLViewerObject::const_child_list_t& child_list = object->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); iter != child_list.end(); iter++) { LLViewerObject* childp = *iter; if (childp->mText.notNull()) { childp->mText->setOnHUDAttachment(FALSE); } } } mAttachedObject = NULL; mUpdateXform = FALSE; mItemID.setNull(); }