From f62b8591a29481ce882b1e50246f848475d3fb6a Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Fri, 5 Jan 2024 19:45:58 +0100 Subject: DRTVWR-489 MacOS Release build fix (vertex_count and index_count aren't used) --- indra/newview/llvotree.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra/newview/llvotree.cpp') diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 36e6da802b..575b1dbe7e 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -865,6 +865,10 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable) mReferenceBuffer->unmapBuffer(); llassert(vertex_count == max_vertices); llassert(index_count == max_indices); +#ifndef SHOW_ASSERT + (void)vertex_count; + (void)index_count; +#endif } //generate tree mesh -- cgit v1.2.3 From 088f2f4f6545ebc2ee01945938a40ae5c87ad27a Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sat, 17 Feb 2024 00:51:13 +0100 Subject: More BOOL to bool replacements primarily in llappearance and llxml --- indra/newview/llvotree.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'indra/newview/llvotree.cpp') diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 575b1dbe7e..cf7206d2da 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -135,10 +135,7 @@ void LLVOTree::initClass() LLUUID id; S32 S32_val; - BOOL success = TRUE; - - - + bool success{ true }; S32 species; static LLStdStringHandle species_id_string = LLXmlTree::addAttributeString("species_id"); if (!tree_def->getFastAttributeS32(species_id_string, species)) @@ -250,7 +247,7 @@ void LLVOTree::initClass() } } - BOOL have_all_trees = TRUE; + bool have_all_trees {true}; std::string err; for (S32 i=0;i Date: Wed, 21 Feb 2024 21:05:14 +0100 Subject: Convert remaining BOOL to bool --- indra/newview/llvotree.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'indra/newview/llvotree.cpp') diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index cf7206d2da..caee731ea3 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -319,7 +319,7 @@ U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys, // Load Species-Specific data // static const S32 MAX_TREE_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL = 32 ; //frames. - mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); mTreeImagep->setMaxVirtualSizeResetInterval(MAX_TREE_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); //allow to wait for at most 16 frames to reset virtual size. mBranchLength = sSpeciesTable[mSpecies]->mBranchLength; @@ -470,7 +470,7 @@ void LLVOTree::updateTextures() LLDrawable* LLVOTree::createDrawable(LLPipeline *pipeline) { pipeline->allocDrawable(this); - mDrawable->setLit(FALSE); + mDrawable->setLit(false); mDrawable->setRenderType(LLPipeline::RENDER_TYPE_TREE); @@ -490,7 +490,7 @@ LLDrawable* LLVOTree::createDrawable(LLPipeline *pipeline) const S32 LEAF_INDICES = 24; const S32 LEAF_VERTICES = 16; -BOOL LLVOTree::updateGeometry(LLDrawable *drawable) +bool LLVOTree::updateGeometry(LLDrawable *drawable) { LL_PROFILE_ZONE_SCOPED; @@ -502,7 +502,7 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable) { facep->setVertexBuffer(NULL); } - return TRUE ; + return true ; } if (mDrawable->getFace(0) && @@ -519,7 +519,7 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable) S32 lod; LLFace *face = drawable->getFace(0); - if (!face) return TRUE; + if (!face) return true; face->mCenterAgent = getPositionAgent(); face->mCenterLocal = face->mCenterAgent; @@ -542,7 +542,7 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable) << max_vertices << " vertices and " << max_indices << " indices" << LL_ENDL; mReferenceBuffer = NULL; //unref - return TRUE; + return true; } LLStrider vertices; @@ -871,7 +871,7 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable) //generate tree mesh updateMesh(); - return TRUE; + return true; } void LLVOTree::updateMesh() @@ -1171,14 +1171,14 @@ void LLVOTree::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) mDrawable->setPositionGroup(pos); } -BOOL LLVOTree::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32 *face_hitp, +bool LLVOTree::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, bool pick_transparent, bool pick_rigged, bool pick_unselectable, S32 *face_hitp, LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) { if (!lineSegmentBoundingBox(start, end)) { - return FALSE; + return false; } const LLVector4a* exta = mDrawable->getSpatialExtents(); @@ -1215,10 +1215,10 @@ BOOL LLVOTree::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& e { normal->load3(norm.mV); } - return TRUE; + return true; } - return FALSE; + return false; } U32 LLVOTree::getPartitionType() const @@ -1227,7 +1227,7 @@ U32 LLVOTree::getPartitionType() const } LLTreePartition::LLTreePartition(LLViewerRegion* regionp) -: LLSpatialPartition(0, FALSE, regionp) +: LLSpatialPartition(0, false, regionp) { mDrawableType = LLPipeline::RENDER_TYPE_TREE; mPartitionType = LLViewerRegion::PARTITION_TREE; -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/newview/llvotree.cpp | 2474 ++++++++++++++++++++++---------------------- 1 file changed, 1237 insertions(+), 1237 deletions(-) (limited to 'indra/newview/llvotree.cpp') diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 4822b0b7ee..a981c60ef2 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -1,1237 +1,1237 @@ -/** - * @file llvotree.cpp - * @brief LLVOTree class implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llvotree.h" - -#include "lldrawpooltree.h" - -#include "llviewercontrol.h" -#include "lldir.h" -#include "llprimitive.h" -#include "lltree_common.h" -#include "llxmltree.h" -#include "material_codes.h" -#include "object_flags.h" - -#include "llagentcamera.h" -#include "lldrawable.h" -#include "llface.h" -#include "llviewercamera.h" -#include "llviewertexturelist.h" -#include "llviewerobjectlist.h" -#include "llviewerregion.h" -#include "llvolumemgr.h" -#include "llvovolume.h" -#include "llworld.h" -#include "noise.h" -#include "pipeline.h" -#include "llspatialpartition.h" -#include "llnotificationsutil.h" -#include "raytrace.h" -#include "llglslshader.h" - -extern LLPipeline gPipeline; - -const S32 MAX_SLICES = 32; -const F32 LEAF_LEFT = 0.52f; -const F32 LEAF_RIGHT = 0.98f; -const F32 LEAF_TOP = 1.0f; -const F32 LEAF_BOTTOM = 0.52f; -const F32 LEAF_WIDTH = 1.f; - -const S32 LLVOTree::sMAX_NUM_TREE_LOD_LEVELS = 4 ; - -S32 LLVOTree::sLODVertexOffset[sMAX_NUM_TREE_LOD_LEVELS]; -S32 LLVOTree::sLODVertexCount[sMAX_NUM_TREE_LOD_LEVELS]; -S32 LLVOTree::sLODIndexOffset[sMAX_NUM_TREE_LOD_LEVELS]; -S32 LLVOTree::sLODIndexCount[sMAX_NUM_TREE_LOD_LEVELS]; -S32 LLVOTree::sLODSlices[sMAX_NUM_TREE_LOD_LEVELS] = {10, 5, 4, 3}; -F32 LLVOTree::sLODAngles[sMAX_NUM_TREE_LOD_LEVELS] = {30.f, 20.f, 15.f, F_ALMOST_ZERO}; - -F32 LLVOTree::sTreeFactor = 1.f; - -LLVOTree::SpeciesMap LLVOTree::sSpeciesTable; -S32 LLVOTree::sMaxTreeSpecies = 0; - -// Tree variables and functions - -LLVOTree::LLVOTree(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp): - LLViewerObject(id, pcode, regionp) -{ - mSpecies = 0; - mFrameCount = 0; - mWind = mRegionp->mWind.getVelocity(getPositionRegion()); - mTrunkLOD = 0; - - // if assert triggers, idleUpdate() needs to be revised and adjusted to new LOD levels - llassert(sMAX_NUM_TREE_LOD_LEVELS == LLVolumeLODGroup::NUM_LODS); -} - - -LLVOTree::~LLVOTree() -{ - if (mData) - { - delete[] mData; - mData = NULL; - } -} - -//static -bool LLVOTree::isTreeRenderingStopped() -{ - return LLVOTree::sTreeFactor < LLVOTree::sLODAngles[sMAX_NUM_TREE_LOD_LEVELS - 1] ; -} - -// static -void LLVOTree::initClass() -{ - std::string xml_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"trees.xml"); - - LLXmlTree tree_def_tree; - - if (!tree_def_tree.parseFile(xml_filename)) - { - LL_ERRS() << "Failed to parse tree file." << LL_ENDL; - } - - LLXmlTreeNode* rootp = tree_def_tree.getRoot(); - - for (LLXmlTreeNode* tree_def = rootp->getFirstChild(); - tree_def; - tree_def = rootp->getNextChild()) - { - if (!tree_def->hasName("tree")) - { - LL_WARNS() << "Invalid tree definition node " << tree_def->getName() << LL_ENDL; - continue; - } - F32 F32_val; - LLUUID id; - S32 S32_val; - - bool success{ true }; - S32 species; - static LLStdStringHandle species_id_string = LLXmlTree::addAttributeString("species_id"); - if (!tree_def->getFastAttributeS32(species_id_string, species)) - { - LL_WARNS() << "No species id defined" << LL_ENDL; - continue; - } - - if (species < 0) - { - LL_WARNS() << "Invalid species id " << species << LL_ENDL; - continue; - } - - if (sSpeciesTable.count(species)) - { - LL_WARNS() << "Tree species " << species << " already defined! Duplicate discarded." << LL_ENDL; - continue; - } - - TreeSpeciesData* newTree = new TreeSpeciesData(); - - static LLStdStringHandle texture_id_string = LLXmlTree::addAttributeString("texture_id"); - success &= tree_def->getFastAttributeUUID(texture_id_string, id); - newTree->mTextureID = id; - - static LLStdStringHandle droop_string = LLXmlTree::addAttributeString("droop"); - success &= tree_def->getFastAttributeF32(droop_string, F32_val); - newTree->mDroop = F32_val; - - static LLStdStringHandle twist_string = LLXmlTree::addAttributeString("twist"); - success &= tree_def->getFastAttributeF32(twist_string, F32_val); - newTree->mTwist = F32_val; - - static LLStdStringHandle branches_string = LLXmlTree::addAttributeString("branches"); - success &= tree_def->getFastAttributeF32(branches_string, F32_val); - newTree->mBranches = F32_val; - - static LLStdStringHandle depth_string = LLXmlTree::addAttributeString("depth"); - success &= tree_def->getFastAttributeS32(depth_string, S32_val); - newTree->mDepth = S32_val; - - static LLStdStringHandle scale_step_string = LLXmlTree::addAttributeString("scale_step"); - success &= tree_def->getFastAttributeF32(scale_step_string, F32_val); - newTree->mScaleStep = F32_val; - - static LLStdStringHandle trunk_depth_string = LLXmlTree::addAttributeString("trunk_depth"); - success &= tree_def->getFastAttributeS32(trunk_depth_string, S32_val); - newTree->mTrunkDepth = S32_val; - - static LLStdStringHandle branch_length_string = LLXmlTree::addAttributeString("branch_length"); - success &= tree_def->getFastAttributeF32(branch_length_string, F32_val); - newTree->mBranchLength = F32_val; - - static LLStdStringHandle trunk_length_string = LLXmlTree::addAttributeString("trunk_length"); - success &= tree_def->getFastAttributeF32(trunk_length_string, F32_val); - newTree->mTrunkLength = F32_val; - - static LLStdStringHandle leaf_scale_string = LLXmlTree::addAttributeString("leaf_scale"); - success &= tree_def->getFastAttributeF32(leaf_scale_string, F32_val); - newTree->mLeafScale = F32_val; - - static LLStdStringHandle billboard_scale_string = LLXmlTree::addAttributeString("billboard_scale"); - success &= tree_def->getFastAttributeF32(billboard_scale_string, F32_val); - newTree->mBillboardScale = F32_val; - - static LLStdStringHandle billboard_ratio_string = LLXmlTree::addAttributeString("billboard_ratio"); - success &= tree_def->getFastAttributeF32(billboard_ratio_string, F32_val); - newTree->mBillboardRatio = F32_val; - - static LLStdStringHandle trunk_aspect_string = LLXmlTree::addAttributeString("trunk_aspect"); - success &= tree_def->getFastAttributeF32(trunk_aspect_string, F32_val); - newTree->mTrunkAspect = F32_val; - - static LLStdStringHandle branch_aspect_string = LLXmlTree::addAttributeString("branch_aspect"); - success &= tree_def->getFastAttributeF32(branch_aspect_string, F32_val); - newTree->mBranchAspect = F32_val; - - static LLStdStringHandle leaf_rotate_string = LLXmlTree::addAttributeString("leaf_rotate"); - success &= tree_def->getFastAttributeF32(leaf_rotate_string, F32_val); - newTree->mRandomLeafRotate = F32_val; - - static LLStdStringHandle noise_mag_string = LLXmlTree::addAttributeString("noise_mag"); - success &= tree_def->getFastAttributeF32(noise_mag_string, F32_val); - newTree->mNoiseMag = F32_val; - - static LLStdStringHandle noise_scale_string = LLXmlTree::addAttributeString("noise_scale"); - success &= tree_def->getFastAttributeF32(noise_scale_string, F32_val); - newTree->mNoiseScale = F32_val; - - static LLStdStringHandle taper_string = LLXmlTree::addAttributeString("taper"); - success &= tree_def->getFastAttributeF32(taper_string, F32_val); - newTree->mTaper = F32_val; - - static LLStdStringHandle repeat_z_string = LLXmlTree::addAttributeString("repeat_z"); - success &= tree_def->getFastAttributeF32(repeat_z_string, F32_val); - newTree->mRepeatTrunkZ = F32_val; - - sSpeciesTable[species] = newTree; - - if (species >= sMaxTreeSpecies) sMaxTreeSpecies = species + 1; - - if (!success) - { - std::string name; - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - tree_def->getFastAttributeString(name_string, name); - LL_WARNS() << "Incomplete definition of tree " << name << LL_ENDL; - } - } - - bool have_all_trees {true}; - std::string err; - - for (S32 i=0;i 0.f) - ||(getAcceleration().lengthSquared() > 0.f) - ||(getAngularVelocity().lengthSquared() > 0.f)) - { - LL_INFOS() << "ACK! Moving tree!" << LL_ENDL; - 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 - // - static const S32 MAX_TREE_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL = 32 ; //frames. - mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - mTreeImagep->setMaxVirtualSizeResetInterval(MAX_TREE_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); //allow to wait for at most 16 frames to reset virtual size. - - 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; -} - -void LLVOTree::idleUpdate(LLAgent &agent, const F64 &time) -{ - if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TREE))) - { - return; - } - - S32 trunk_LOD = sMAX_NUM_TREE_LOD_LEVELS ; // disabled - F32 app_angle = getAppAngle()*LLVOTree::sTreeFactor; - F32 distance = mDrawable->mDistanceWRTCamera * LLVOVolume::sDistanceFactor * (F_PI / 3.f); - F32 diameter = getScale().length(); // trees have very broken scale, but length rougtly outlines proper diameter - F32 sz = mBillboardScale * mBillboardRatio * diameter; - - for (S32 j = 0; j < sMAX_NUM_TREE_LOD_LEVELS; j++) - { - if (app_angle > LLVOTree::sLODAngles[j]) - { - trunk_LOD = j; - break; - } - } - - F32 tan_angle = (LLVOTree::sTreeFactor * 64 * sz) / distance; - S32 cur_detail = LLVolumeLODGroup::getDetailFromTan(ll_round(tan_angle, 0.01f)); // larger value, better quality - - // for trunk_LOD lower value means better quality, but both trunk_LOD and cur_detail have 4 levels - trunk_LOD = llmax(trunk_LOD, LLVolumeLODGroup::NUM_LODS - cur_detail - 1); - trunk_LOD = llmin(trunk_LOD, sMAX_NUM_TREE_LOD_LEVELS); - - if (mReferenceBuffer.isNull()) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL); - } - else if (trunk_LOD != mTrunkLOD) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL); - } - 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 = getPositionRegion(); - 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; -} - -void LLVOTree::render(LLAgent &agent) -{ -} - - -void LLVOTree::setPixelAreaAndAngle(LLAgent &agent) -{ - LLVector3 center = getPositionAgent();//center of tree. - LLVector3 viewer_pos_agent = gAgentCamera.getCameraPositionAgent(); - LLVector3 lookAt = center - viewer_pos_agent; - F32 dist = lookAt.normVec() ; - F32 cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ; - F32 radius = getScale().length()*0.5f; - F32 range = dist - radius; - - if (range < F_ALMOST_ZERO || isHUDAttachment()) // range == zero - { - mAppAngle = 180.f; - } - else - { - mAppAngle = (F32) atan2( getMaxScale(), range) * RAD_TO_DEG; - } - - F32 max_scale = mBillboardScale * getMaxScale(); - F32 area = max_scale * (max_scale*mBillboardRatio); - // Compute pixels per meter at the given range - F32 pixels_per_meter = LLViewerCamera::getInstance()->getViewHeightInPixels() / (tan(LLViewerCamera::getInstance()->getView()) * dist); - mPixelArea = pixels_per_meter * pixels_per_meter * area ; - - F32 importance = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist) ; - mPixelArea = LLFace::adjustPixelArea(importance, mPixelArea) ; - if (mPixelArea > LLViewerCamera::getInstance()->getScreenPixelArea()) - { - mAppAngle = 180.f; - } - -#if 0 - // mAppAngle is a bit of voodoo; - // use the one calculated LLViewerObject::setPixelAreaAndAngle above - // to avoid LOD miscalculations - mAppAngle = (F32) atan2( max_scale, range) * RAD_TO_DEG; -#endif -} - -void LLVOTree::updateTextures() -{ - if (mTreeImagep) - { - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) - { - setDebugText(llformat("%4.0f", (F32) sqrt(mPixelArea))); - } - mTreeImagep->addTextureStats(mPixelArea); - } - -} - - -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; -} - - -// Yes, I know this is bad. I'll clean this up soon. - djs 04/02/02 -const S32 LEAF_INDICES = 24; -const S32 LEAF_VERTICES = 16; - -bool LLVOTree::updateGeometry(LLDrawable *drawable) -{ - LL_PROFILE_ZONE_SCOPED; - - if(mTrunkLOD >= sMAX_NUM_TREE_LOD_LEVELS) //do not display the tree. - { - mReferenceBuffer = NULL ; - LLFace * facep = drawable->getFace(0); - if (facep) - { - facep->setVertexBuffer(NULL); - } - return true ; - } - - if (mDrawable->getFace(0) && - (mReferenceBuffer.isNull() || !mDrawable->getFace(0)->getVertexBuffer())) - { - const F32 SRR3 = 0.577350269f; // sqrt(1/3) - const F32 SRR2 = 0.707106781f; // sqrt(1/2) - U32 i, j; - - U32 slices = MAX_SLICES; - - S32 max_indices = LEAF_INDICES; - S32 max_vertices = LEAF_VERTICES; - S32 lod; - - LLFace *face = drawable->getFace(0); - if (!face) return true; - - face->mCenterAgent = getPositionAgent(); - face->mCenterLocal = face->mCenterAgent; - - for (lod = 0; lod < sMAX_NUM_TREE_LOD_LEVELS; lod++) - { - slices = sLODSlices[lod]; - sLODVertexOffset[lod] = max_vertices; - sLODVertexCount[lod] = slices*slices; - sLODIndexOffset[lod] = max_indices; - sLODIndexCount[lod] = (slices-1)*(slices-1)*6; - max_indices += sLODIndexCount[lod]; - max_vertices += sLODVertexCount[lod]; - } - - mReferenceBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); - if (!mReferenceBuffer->allocateBuffer(max_vertices, max_indices)) - { - LL_WARNS() << "Failed to allocate Vertex Buffer on update to " - << max_vertices << " vertices and " - << max_indices << " indices" << LL_ENDL; - mReferenceBuffer = NULL; //unref - return true; - } - - LLStrider vertices; - LLStrider normals; - LLStrider colors; - LLStrider tex_coords; - LLStrider indicesp; - - mReferenceBuffer->getVertexStrider(vertices); - mReferenceBuffer->getNormalStrider(normals); - mReferenceBuffer->getTexCoord0Strider(tex_coords); - mReferenceBuffer->getColorStrider(colors); - mReferenceBuffer->getIndexStrider(indicesp); - - S32 vertex_count = 0; - S32 index_count = 0; - - // First leaf - *(normals++) = LLVector3(-SRR2, -SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); - *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f); - *(colors++) = LLColor4U::white; - vertex_count++; - - *(normals++) = LLVector3(SRR3, -SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); - *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f); - *(colors++) = LLColor4U::white; - vertex_count++; - - *(normals++) = LLVector3(-SRR3, -SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); - *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f); - *(colors++) = LLColor4U::white; - vertex_count++; - - *(normals++) = LLVector3(SRR2, -SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); - *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f); - *(colors++) = LLColor4U::white; - vertex_count++; - - *(indicesp++) = 0; - index_count++; - *(indicesp++) = 1; - index_count++; - *(indicesp++) = 2; - index_count++; - - *(indicesp++) = 0; - index_count++; - *(indicesp++) = 3; - index_count++; - *(indicesp++) = 1; - index_count++; - - // Same leaf, inverse winding/normals - *(normals++) = LLVector3(-SRR2, SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); - *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f); - *(colors++) = LLColor4U::white; - vertex_count++; - - *(normals++) = LLVector3(SRR3, SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); - *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f); - *(colors++) = LLColor4U::white; - vertex_count++; - - *(normals++) = LLVector3(-SRR3, SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); - *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f); - *(colors++) = LLColor4U::white; - vertex_count++; - - *(normals++) = LLVector3(SRR2, SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); - *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f); - *(colors++) = LLColor4U::white; - vertex_count++; - - *(indicesp++) = 4; - index_count++; - *(indicesp++) = 6; - index_count++; - *(indicesp++) = 5; - index_count++; - - *(indicesp++) = 4; - index_count++; - *(indicesp++) = 5; - index_count++; - *(indicesp++) = 7; - index_count++; - - - // next leaf - *(normals++) = LLVector3(SRR2, -SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); - *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f); - *(colors++) = LLColor4U::white; - vertex_count++; - - *(normals++) = LLVector3(SRR3, SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); - *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f); - *(colors++) = LLColor4U::white; - vertex_count++; - - *(normals++) = LLVector3(SRR3, -SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); - *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f); - *(colors++) = LLColor4U::white; - vertex_count++; - - *(normals++) = LLVector3(SRR2, SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); - *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f); - *(colors++) = LLColor4U::white; - vertex_count++; - - *(indicesp++) = 8; - index_count++; - *(indicesp++) = 9; - index_count++; - *(indicesp++) = 10; - index_count++; - - *(indicesp++) = 8; - index_count++; - *(indicesp++) = 11; - index_count++; - *(indicesp++) = 9; - index_count++; - - - // other side of same leaf - *(normals++) = LLVector3(-SRR2, -SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); - *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f); - *(colors++) = LLColor4U::white; - vertex_count++; - - *(normals++) = LLVector3(-SRR3, SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); - *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f); - *(colors++) = LLColor4U::white; - vertex_count++; - - *(normals++) = LLVector3(-SRR3, -SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); - *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f); - *(colors++) = LLColor4U::white; - vertex_count++; - - *(normals++) = LLVector3(-SRR2, SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); - *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f); - *(colors++) = LLColor4U::white; - vertex_count++; - - *(indicesp++) = 12; - index_count++; - *(indicesp++) = 14; - index_count++; - *(indicesp++) = 13; - index_count++; - - *(indicesp++) = 12; - index_count++; - *(indicesp++) = 13; - index_count++; - *(indicesp++) = 15; - index_count++; - - // Generate geometry for the cylinders - - // Different LOD's - - // Generate the vertices - // Generate the indices - - for (lod = 0; lod < sMAX_NUM_TREE_LOD_LEVELS; lod++) - { - slices = sLODSlices[lod]; - F32 base_radius = 0.65f; - F32 top_radius = base_radius * sSpeciesTable[mSpecies]->mTaper; - //LL_INFOS() << "Species " << ((U32) mSpecies) << ", taper = " << sSpeciesTable[mSpecies].mTaper << LL_ENDL; - //LL_INFOS() << "Droop " << mDroop << ", branchlength: " << mBranchLength << LL_ENDL; - F32 angle = 0; - F32 angle_inc = 360.f/(slices-1); - F32 z = 0.f; - F32 z_inc = 1.f; - if (slices > 3) - { - z_inc = 1.f/(slices - 3); - } - F32 radius = base_radius; - - F32 x1,y1; - F32 noise_scale = sSpeciesTable[mSpecies]->mNoiseMag; - LLVector3 nvec; - - const F32 cap_nudge = 0.1f; // Height to 'peak' the caps on top/bottom of branch - - const S32 fractal_depth = 5; - F32 nvec_scale = 1.f * sSpeciesTable[mSpecies]->mNoiseScale; - F32 nvec_scalez = 4.f * sSpeciesTable[mSpecies]->mNoiseScale; - - F32 tex_z_repeat = sSpeciesTable[mSpecies]->mRepeatTrunkZ; - - F32 start_radius; - F32 nangle = 0; - F32 height = 1.f; - F32 r0; - - for (i = 0; i < slices; i++) - { - if (i == 0) - { - z = - cap_nudge; - r0 = 0.0; - } - else if (i == (slices - 1)) - { - z = 1.f + cap_nudge;//((i - 2) * z_inc) + cap_nudge; - r0 = 0.0; - } - else - { - z = (i - 1) * z_inc; - r0 = base_radius + (top_radius - base_radius)*z; - } - - for (j = 0; j < slices; j++) - { - if (slices - 1 == j) - { - angle = 0.f; - } - else - { - angle = j*angle_inc; - } - - nangle = angle; - - x1 = cos(angle * DEG_TO_RAD); - y1 = sin(angle * DEG_TO_RAD); - LLVector2 tc; - // This isn't totally accurate. Should compute based on slope as well. - start_radius = r0 * (1.f + 1.2f*fabs(z - 0.66f*height)/height); - nvec.set( cos(nangle * DEG_TO_RAD)*start_radius*nvec_scale, - sin(nangle * DEG_TO_RAD)*start_radius*nvec_scale, - z*nvec_scalez); - // First and last slice at 0 radius (to bring in top/bottom of structure) - radius = start_radius + turbulence3((F32*)&nvec.mV, (F32)fractal_depth)*noise_scale; - - if (slices - 1 == j) - { - // Not 0.5 for slight slop factor to avoid edges on leaves - tc = LLVector2(0.490f, (1.f - z/2.f)*tex_z_repeat); - } - else - { - tc = LLVector2((angle/360.f)*0.5f, (1.f - z/2.f)*tex_z_repeat); - } - - *(vertices++) = LLVector3(x1*radius, y1*radius, z); - *(normals++) = LLVector3(x1, y1, 0.f); - *(tex_coords++) = tc; - *(colors++) = LLColor4U::white; - vertex_count++; - } - } - - for (i = 0; i < (slices - 1); i++) - { - for (j = 0; j < (slices - 1); j++) - { - S32 x1_offset = j+1; - if ((j+1) == slices) - { - x1_offset = 0; - } - // Generate the matching quads - *(indicesp) = j + (i*slices) + sLODVertexOffset[lod]; - llassert(*(indicesp) < (U32)max_vertices); - indicesp++; - index_count++; - *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod]; - llassert(*(indicesp) < (U32)max_vertices); - indicesp++; - index_count++; - *(indicesp) = j + ((i+1)*slices) + sLODVertexOffset[lod]; - llassert(*(indicesp) < (U32)max_vertices); - indicesp++; - index_count++; - - *(indicesp) = j + (i*slices) + sLODVertexOffset[lod]; - llassert(*(indicesp) < (U32)max_vertices); - indicesp++; - index_count++; - *(indicesp) = x1_offset + (i*slices) + sLODVertexOffset[lod]; - llassert(*(indicesp) < (U32)max_vertices); - indicesp++; - index_count++; - *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod]; - llassert(*(indicesp) < (U32)max_vertices); - indicesp++; - index_count++; - } - } - slices /= 2; - } - - mReferenceBuffer->unmapBuffer(); - llassert(vertex_count == max_vertices); - llassert(index_count == max_indices); -#ifndef SHOW_ASSERT - (void)vertex_count; - (void)index_count; -#endif - } - - //generate tree mesh - updateMesh(); - - return true; -} - -void LLVOTree::updateMesh() -{ - LLMatrix4 matrix; - - // Translate to tree base HACK - adjustment in Z plants tree underground - const LLVector3 &pos_region = getPositionRegion(); - //gGL.translatef(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); - LLMatrix4 trans_mat; - trans_mat.setTranslation(pos_region.mV[VX], pos_region.mV[VY], pos_region.mV[VZ] - 0.1f); - trans_mat *= matrix; - - // Rotate to tree position and bend for current trunk/wind - // Note that trunk stiffness controls the amount of bend at the trunk as - // opposed to the crown of the tree - // - const F32 TRUNK_STIFF = 22.f; - - LLQuaternion rot = - LLQuaternion(mTrunkBend.magVec()*TRUNK_STIFF*DEG_TO_RAD, LLVector4(mTrunkBend.mV[VX], mTrunkBend.mV[VY], 0)) * - LLQuaternion(90.f*DEG_TO_RAD, LLVector4(0,0,1)) * - getRotation(); - - LLMatrix4 rot_mat(rot); - rot_mat *= trans_mat; - - F32 radius = getScale().magVec()*0.05f; - LLMatrix4 scale_mat; - scale_mat.mMatrix[0][0] = - scale_mat.mMatrix[1][1] = - scale_mat.mMatrix[2][2] = radius; - - scale_mat *= rot_mat; - -// const F32 THRESH_ANGLE_FOR_BILLBOARD = 15.f; -// const F32 BLEND_RANGE_FOR_BILLBOARD = 3.f; - - F32 droop = mDroop + 25.f*(1.f - mTrunkBend.magVec()); - - S32 stop_depth = 0; - F32 alpha = 1.0; - - U32 vert_count = 0; - U32 index_count = 0; - - calcNumVerts(vert_count, index_count, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, mBranches); - - LLFace* facep = mDrawable->getFace(0); - if (!facep) return; - LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); - if (!buff->allocateBuffer(vert_count, index_count)) - { - LL_WARNS() << "Failed to allocate Vertex Buffer on mesh update to " - << vert_count << " vertices and " - << index_count << " indices" << LL_ENDL; - buff->allocateBuffer(1, 3); - memset((U8*)buff->getMappedData(), 0, buff->getSize()); - memset((U8*)buff->getMappedIndices(), 0, buff->getIndicesSize()); - facep->setSize(1, 3); - facep->setVertexBuffer(buff); - mReferenceBuffer->unmapBuffer(); - buff->unmapBuffer(); - return; - } - - facep->setVertexBuffer(buff); - - LLStrider vertices; - LLStrider normals; - LLStrider tex_coords; - LLStrider colors; - LLStrider indices; - U16 idx_offset = 0; - - buff->getVertexStrider(vertices); - buff->getNormalStrider(normals); - buff->getTexCoord0Strider(tex_coords); - buff->getColorStrider(colors); - buff->getIndexStrider(indices); - - genBranchPipeline(vertices, normals, tex_coords, colors, indices, idx_offset, scale_mat, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, 1.0, mTwist, droop, mBranches, alpha); - - mReferenceBuffer->unmapBuffer(); - buff->unmapBuffer(); -} - -void LLVOTree::appendMesh(LLStrider& vertices, - LLStrider& normals, - LLStrider& tex_coords, - LLStrider& colors, - LLStrider& indices, - U16& cur_idx, - LLMatrix4& matrix, - LLMatrix4& norm_mat, - S32 vert_start, - S32 vert_count, - S32 index_count, - S32 index_offset) -{ - LLStrider v; - LLStrider n; - LLStrider t; - LLStrider c; - LLStrider idx; - - mReferenceBuffer->getVertexStrider(v); - mReferenceBuffer->getNormalStrider(n); - mReferenceBuffer->getTexCoord0Strider(t); - mReferenceBuffer->getColorStrider(c); - mReferenceBuffer->getIndexStrider(idx); - - //copy/transform vertices into mesh - check - for (S32 i = 0; i < vert_count; i++) - { - U16 index = vert_start + i; - *vertices++ = v[index] * matrix; - LLVector3 norm = n[index] * norm_mat; - norm.normalize(); - *normals++ = norm; - *tex_coords++ = t[index]; - *colors++ = c[index]; - } - - //copy offset indices into mesh - check - for (S32 i = 0; i < index_count; i++) - { - U16 index = index_offset + i; - *indices++ = idx[index]-vert_start+cur_idx; - } - - //increment index offset - check - cur_idx += vert_count; -} - - -void LLVOTree::genBranchPipeline(LLStrider& vertices, - LLStrider& normals, - LLStrider& tex_coords, - LLStrider& colors, - LLStrider& indices, - U16& index_offset, - LLMatrix4& matrix, - S32 trunk_LOD, - S32 stop_level, - U16 depth, - U16 trunk_depth, - F32 scale, - F32 twist, - F32 droop, - F32 branches, - F32 alpha) -{ - // - // Generates a tree mesh by recursing, generating branches and then a 'leaf' texture. - - static F32 constant_twist; - static F32 width = 0; - - F32 length = ((trunk_depth || (scale == 1.f))? mTrunkLength:mBranchLength); - F32 aspect = ((trunk_depth || (scale == 1.f))? mTrunkAspect:mBranchAspect); - - constant_twist = 360.f/branches; - - if (stop_level >= 0) - { - 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; - - glh::matrix4f norm((F32*) scale_mat.mMatrix); - LLMatrix4 norm_mat = LLMatrix4(norm.inverse().transpose().m); - - norm_mat.invert(); - appendMesh(vertices, normals, tex_coords, colors, indices, index_offset, scale_mat, norm_mat, - sLODVertexOffset[trunk_LOD], sLODVertexCount[trunk_LOD], sLODIndexCount[trunk_LOD], sLODIndexOffset[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; - - genBranchPipeline(vertices, normals, tex_coords, colors, indices, index_offset, rot_mat, 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 - genBranchPipeline(vertices, normals, tex_coords, colors, indices, index_offset, rot_mat, trunk_LOD, stop_level, depth, trunk_depth-1, scale*mScaleStep, twist, droop, branches, alpha); - } - } - else - { - // - // Append 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; - - glh::matrix4f norm((F32*) scale_mat.mMatrix); - LLMatrix4 norm_mat = LLMatrix4(norm.inverse().transpose().m); - - appendMesh(vertices, normals, tex_coords, colors, indices, index_offset, scale_mat, norm_mat, 0, LEAF_VERTICES, LEAF_INDICES, 0); - } - } - } -} - - - -void LLVOTree::calcNumVerts(U32& vert_count, U32& index_count, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 branches) -{ - if (stop_level >= 0) - { - if (depth > stop_level) - { - index_count += sLODIndexCount[trunk_LOD]; - vert_count += sLODVertexCount[trunk_LOD]; - - // Recurse to create more branches - for (S32 i=0; i < (S32)branches; i++) - { - calcNumVerts(vert_count, index_count, trunk_LOD, stop_level, depth - 1, 0, branches); - } - - // Recurse to continue trunk - if (trunk_depth) - { - calcNumVerts(vert_count, index_count, trunk_LOD, stop_level, depth, trunk_depth-1, branches); - } - } - else - { - index_count += LEAF_INDICES; - vert_count += LEAF_VERTICES; - } - } - else - { - index_count += LEAF_INDICES; - vert_count += LEAF_VERTICES; - } -} - -void LLVOTree::updateRadius() -{ - if (mDrawable.isNull()) - { - return; - } - - mDrawable->setRadius(32.0f); -} - -void LLVOTree::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) -{ - F32 radius = getScale().length()*0.05f; - LLVector3 center = getRenderPosition(); - - F32 sz = mBillboardScale*mBillboardRatio*radius*0.5f; - LLVector3 size(sz,sz,sz); - - center += LLVector3(0, 0, size.mV[2]) * getRotation(); - - newMin.load3((center-size).mV); - newMax.load3((center+size).mV); - LLVector4a pos; - pos.load3(center.mV); - mDrawable->setPositionGroup(pos); -} - -bool LLVOTree::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, bool pick_transparent, bool pick_rigged, bool pick_unselectable, S32 *face_hitp, - LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) - -{ - - if (!lineSegmentBoundingBox(start, end)) - { - return false; - } - - const LLVector4a* exta = mDrawable->getSpatialExtents(); - - //VECTORIZE THIS - LLVector3 ext[2]; - ext[0].set(exta[0].getF32ptr()); - ext[1].set(exta[1].getF32ptr()); - - LLVector3 center = (ext[1]+ext[0])*0.5f; - LLVector3 size = (ext[1]-ext[0]); - - LLQuaternion quat = getRotation(); - - center -= LLVector3(0,0,size.magVec() * 0.25f)*quat; - - size.scaleVec(LLVector3(0.25f, 0.25f, 1.f)); - size.mV[0] = llmin(size.mV[0], 1.f); - size.mV[1] = llmin(size.mV[1], 1.f); - - LLVector3 pos, norm; - - LLVector3 start3(start.getF32ptr()); - LLVector3 end3(end.getF32ptr()); - - if (linesegment_tetrahedron(start3, end3, center, size, quat, pos, norm)) - { - if (intersection) - { - intersection->load3(pos.mV); - } - - if (normal) - { - normal->load3(norm.mV); - } - return true; - } - - return false; -} - -U32 LLVOTree::getPartitionType() const -{ - return LLViewerRegion::PARTITION_TREE; -} - -LLTreePartition::LLTreePartition(LLViewerRegion* regionp) -: LLSpatialPartition(0, false, regionp) -{ - mDrawableType = LLPipeline::RENDER_TYPE_TREE; - mPartitionType = LLViewerRegion::PARTITION_TREE; - mSlopRatio = 0.f; - mLODPeriod = 1; -} - +/** + * @file llvotree.cpp + * @brief LLVOTree class implementation + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llvotree.h" + +#include "lldrawpooltree.h" + +#include "llviewercontrol.h" +#include "lldir.h" +#include "llprimitive.h" +#include "lltree_common.h" +#include "llxmltree.h" +#include "material_codes.h" +#include "object_flags.h" + +#include "llagentcamera.h" +#include "lldrawable.h" +#include "llface.h" +#include "llviewercamera.h" +#include "llviewertexturelist.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "llvolumemgr.h" +#include "llvovolume.h" +#include "llworld.h" +#include "noise.h" +#include "pipeline.h" +#include "llspatialpartition.h" +#include "llnotificationsutil.h" +#include "raytrace.h" +#include "llglslshader.h" + +extern LLPipeline gPipeline; + +const S32 MAX_SLICES = 32; +const F32 LEAF_LEFT = 0.52f; +const F32 LEAF_RIGHT = 0.98f; +const F32 LEAF_TOP = 1.0f; +const F32 LEAF_BOTTOM = 0.52f; +const F32 LEAF_WIDTH = 1.f; + +const S32 LLVOTree::sMAX_NUM_TREE_LOD_LEVELS = 4 ; + +S32 LLVOTree::sLODVertexOffset[sMAX_NUM_TREE_LOD_LEVELS]; +S32 LLVOTree::sLODVertexCount[sMAX_NUM_TREE_LOD_LEVELS]; +S32 LLVOTree::sLODIndexOffset[sMAX_NUM_TREE_LOD_LEVELS]; +S32 LLVOTree::sLODIndexCount[sMAX_NUM_TREE_LOD_LEVELS]; +S32 LLVOTree::sLODSlices[sMAX_NUM_TREE_LOD_LEVELS] = {10, 5, 4, 3}; +F32 LLVOTree::sLODAngles[sMAX_NUM_TREE_LOD_LEVELS] = {30.f, 20.f, 15.f, F_ALMOST_ZERO}; + +F32 LLVOTree::sTreeFactor = 1.f; + +LLVOTree::SpeciesMap LLVOTree::sSpeciesTable; +S32 LLVOTree::sMaxTreeSpecies = 0; + +// Tree variables and functions + +LLVOTree::LLVOTree(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp): + LLViewerObject(id, pcode, regionp) +{ + mSpecies = 0; + mFrameCount = 0; + mWind = mRegionp->mWind.getVelocity(getPositionRegion()); + mTrunkLOD = 0; + + // if assert triggers, idleUpdate() needs to be revised and adjusted to new LOD levels + llassert(sMAX_NUM_TREE_LOD_LEVELS == LLVolumeLODGroup::NUM_LODS); +} + + +LLVOTree::~LLVOTree() +{ + if (mData) + { + delete[] mData; + mData = NULL; + } +} + +//static +bool LLVOTree::isTreeRenderingStopped() +{ + return LLVOTree::sTreeFactor < LLVOTree::sLODAngles[sMAX_NUM_TREE_LOD_LEVELS - 1] ; +} + +// static +void LLVOTree::initClass() +{ + std::string xml_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"trees.xml"); + + LLXmlTree tree_def_tree; + + if (!tree_def_tree.parseFile(xml_filename)) + { + LL_ERRS() << "Failed to parse tree file." << LL_ENDL; + } + + LLXmlTreeNode* rootp = tree_def_tree.getRoot(); + + for (LLXmlTreeNode* tree_def = rootp->getFirstChild(); + tree_def; + tree_def = rootp->getNextChild()) + { + if (!tree_def->hasName("tree")) + { + LL_WARNS() << "Invalid tree definition node " << tree_def->getName() << LL_ENDL; + continue; + } + F32 F32_val; + LLUUID id; + S32 S32_val; + + bool success{ true }; + S32 species; + static LLStdStringHandle species_id_string = LLXmlTree::addAttributeString("species_id"); + if (!tree_def->getFastAttributeS32(species_id_string, species)) + { + LL_WARNS() << "No species id defined" << LL_ENDL; + continue; + } + + if (species < 0) + { + LL_WARNS() << "Invalid species id " << species << LL_ENDL; + continue; + } + + if (sSpeciesTable.count(species)) + { + LL_WARNS() << "Tree species " << species << " already defined! Duplicate discarded." << LL_ENDL; + continue; + } + + TreeSpeciesData* newTree = new TreeSpeciesData(); + + static LLStdStringHandle texture_id_string = LLXmlTree::addAttributeString("texture_id"); + success &= tree_def->getFastAttributeUUID(texture_id_string, id); + newTree->mTextureID = id; + + static LLStdStringHandle droop_string = LLXmlTree::addAttributeString("droop"); + success &= tree_def->getFastAttributeF32(droop_string, F32_val); + newTree->mDroop = F32_val; + + static LLStdStringHandle twist_string = LLXmlTree::addAttributeString("twist"); + success &= tree_def->getFastAttributeF32(twist_string, F32_val); + newTree->mTwist = F32_val; + + static LLStdStringHandle branches_string = LLXmlTree::addAttributeString("branches"); + success &= tree_def->getFastAttributeF32(branches_string, F32_val); + newTree->mBranches = F32_val; + + static LLStdStringHandle depth_string = LLXmlTree::addAttributeString("depth"); + success &= tree_def->getFastAttributeS32(depth_string, S32_val); + newTree->mDepth = S32_val; + + static LLStdStringHandle scale_step_string = LLXmlTree::addAttributeString("scale_step"); + success &= tree_def->getFastAttributeF32(scale_step_string, F32_val); + newTree->mScaleStep = F32_val; + + static LLStdStringHandle trunk_depth_string = LLXmlTree::addAttributeString("trunk_depth"); + success &= tree_def->getFastAttributeS32(trunk_depth_string, S32_val); + newTree->mTrunkDepth = S32_val; + + static LLStdStringHandle branch_length_string = LLXmlTree::addAttributeString("branch_length"); + success &= tree_def->getFastAttributeF32(branch_length_string, F32_val); + newTree->mBranchLength = F32_val; + + static LLStdStringHandle trunk_length_string = LLXmlTree::addAttributeString("trunk_length"); + success &= tree_def->getFastAttributeF32(trunk_length_string, F32_val); + newTree->mTrunkLength = F32_val; + + static LLStdStringHandle leaf_scale_string = LLXmlTree::addAttributeString("leaf_scale"); + success &= tree_def->getFastAttributeF32(leaf_scale_string, F32_val); + newTree->mLeafScale = F32_val; + + static LLStdStringHandle billboard_scale_string = LLXmlTree::addAttributeString("billboard_scale"); + success &= tree_def->getFastAttributeF32(billboard_scale_string, F32_val); + newTree->mBillboardScale = F32_val; + + static LLStdStringHandle billboard_ratio_string = LLXmlTree::addAttributeString("billboard_ratio"); + success &= tree_def->getFastAttributeF32(billboard_ratio_string, F32_val); + newTree->mBillboardRatio = F32_val; + + static LLStdStringHandle trunk_aspect_string = LLXmlTree::addAttributeString("trunk_aspect"); + success &= tree_def->getFastAttributeF32(trunk_aspect_string, F32_val); + newTree->mTrunkAspect = F32_val; + + static LLStdStringHandle branch_aspect_string = LLXmlTree::addAttributeString("branch_aspect"); + success &= tree_def->getFastAttributeF32(branch_aspect_string, F32_val); + newTree->mBranchAspect = F32_val; + + static LLStdStringHandle leaf_rotate_string = LLXmlTree::addAttributeString("leaf_rotate"); + success &= tree_def->getFastAttributeF32(leaf_rotate_string, F32_val); + newTree->mRandomLeafRotate = F32_val; + + static LLStdStringHandle noise_mag_string = LLXmlTree::addAttributeString("noise_mag"); + success &= tree_def->getFastAttributeF32(noise_mag_string, F32_val); + newTree->mNoiseMag = F32_val; + + static LLStdStringHandle noise_scale_string = LLXmlTree::addAttributeString("noise_scale"); + success &= tree_def->getFastAttributeF32(noise_scale_string, F32_val); + newTree->mNoiseScale = F32_val; + + static LLStdStringHandle taper_string = LLXmlTree::addAttributeString("taper"); + success &= tree_def->getFastAttributeF32(taper_string, F32_val); + newTree->mTaper = F32_val; + + static LLStdStringHandle repeat_z_string = LLXmlTree::addAttributeString("repeat_z"); + success &= tree_def->getFastAttributeF32(repeat_z_string, F32_val); + newTree->mRepeatTrunkZ = F32_val; + + sSpeciesTable[species] = newTree; + + if (species >= sMaxTreeSpecies) sMaxTreeSpecies = species + 1; + + if (!success) + { + std::string name; + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + tree_def->getFastAttributeString(name_string, name); + LL_WARNS() << "Incomplete definition of tree " << name << LL_ENDL; + } + } + + bool have_all_trees {true}; + std::string err; + + for (S32 i=0;i 0.f) + ||(getAcceleration().lengthSquared() > 0.f) + ||(getAngularVelocity().lengthSquared() > 0.f)) + { + LL_INFOS() << "ACK! Moving tree!" << LL_ENDL; + 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 + // + static const S32 MAX_TREE_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL = 32 ; //frames. + mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mTreeImagep->setMaxVirtualSizeResetInterval(MAX_TREE_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); //allow to wait for at most 16 frames to reset virtual size. + + 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; +} + +void LLVOTree::idleUpdate(LLAgent &agent, const F64 &time) +{ + if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TREE))) + { + return; + } + + S32 trunk_LOD = sMAX_NUM_TREE_LOD_LEVELS ; // disabled + F32 app_angle = getAppAngle()*LLVOTree::sTreeFactor; + F32 distance = mDrawable->mDistanceWRTCamera * LLVOVolume::sDistanceFactor * (F_PI / 3.f); + F32 diameter = getScale().length(); // trees have very broken scale, but length rougtly outlines proper diameter + F32 sz = mBillboardScale * mBillboardRatio * diameter; + + for (S32 j = 0; j < sMAX_NUM_TREE_LOD_LEVELS; j++) + { + if (app_angle > LLVOTree::sLODAngles[j]) + { + trunk_LOD = j; + break; + } + } + + F32 tan_angle = (LLVOTree::sTreeFactor * 64 * sz) / distance; + S32 cur_detail = LLVolumeLODGroup::getDetailFromTan(ll_round(tan_angle, 0.01f)); // larger value, better quality + + // for trunk_LOD lower value means better quality, but both trunk_LOD and cur_detail have 4 levels + trunk_LOD = llmax(trunk_LOD, LLVolumeLODGroup::NUM_LODS - cur_detail - 1); + trunk_LOD = llmin(trunk_LOD, sMAX_NUM_TREE_LOD_LEVELS); + + if (mReferenceBuffer.isNull()) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL); + } + else if (trunk_LOD != mTrunkLOD) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL); + } + 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 = getPositionRegion(); + 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; +} + +void LLVOTree::render(LLAgent &agent) +{ +} + + +void LLVOTree::setPixelAreaAndAngle(LLAgent &agent) +{ + LLVector3 center = getPositionAgent();//center of tree. + LLVector3 viewer_pos_agent = gAgentCamera.getCameraPositionAgent(); + LLVector3 lookAt = center - viewer_pos_agent; + F32 dist = lookAt.normVec() ; + F32 cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ; + F32 radius = getScale().length()*0.5f; + F32 range = dist - radius; + + if (range < F_ALMOST_ZERO || isHUDAttachment()) // range == zero + { + mAppAngle = 180.f; + } + else + { + mAppAngle = (F32) atan2( getMaxScale(), range) * RAD_TO_DEG; + } + + F32 max_scale = mBillboardScale * getMaxScale(); + F32 area = max_scale * (max_scale*mBillboardRatio); + // Compute pixels per meter at the given range + F32 pixels_per_meter = LLViewerCamera::getInstance()->getViewHeightInPixels() / (tan(LLViewerCamera::getInstance()->getView()) * dist); + mPixelArea = pixels_per_meter * pixels_per_meter * area ; + + F32 importance = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist) ; + mPixelArea = LLFace::adjustPixelArea(importance, mPixelArea) ; + if (mPixelArea > LLViewerCamera::getInstance()->getScreenPixelArea()) + { + mAppAngle = 180.f; + } + +#if 0 + // mAppAngle is a bit of voodoo; + // use the one calculated LLViewerObject::setPixelAreaAndAngle above + // to avoid LOD miscalculations + mAppAngle = (F32) atan2( max_scale, range) * RAD_TO_DEG; +#endif +} + +void LLVOTree::updateTextures() +{ + if (mTreeImagep) + { + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) + { + setDebugText(llformat("%4.0f", (F32) sqrt(mPixelArea))); + } + mTreeImagep->addTextureStats(mPixelArea); + } + +} + + +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; +} + + +// Yes, I know this is bad. I'll clean this up soon. - djs 04/02/02 +const S32 LEAF_INDICES = 24; +const S32 LEAF_VERTICES = 16; + +bool LLVOTree::updateGeometry(LLDrawable *drawable) +{ + LL_PROFILE_ZONE_SCOPED; + + if(mTrunkLOD >= sMAX_NUM_TREE_LOD_LEVELS) //do not display the tree. + { + mReferenceBuffer = NULL ; + LLFace * facep = drawable->getFace(0); + if (facep) + { + facep->setVertexBuffer(NULL); + } + return true ; + } + + if (mDrawable->getFace(0) && + (mReferenceBuffer.isNull() || !mDrawable->getFace(0)->getVertexBuffer())) + { + const F32 SRR3 = 0.577350269f; // sqrt(1/3) + const F32 SRR2 = 0.707106781f; // sqrt(1/2) + U32 i, j; + + U32 slices = MAX_SLICES; + + S32 max_indices = LEAF_INDICES; + S32 max_vertices = LEAF_VERTICES; + S32 lod; + + LLFace *face = drawable->getFace(0); + if (!face) return true; + + face->mCenterAgent = getPositionAgent(); + face->mCenterLocal = face->mCenterAgent; + + for (lod = 0; lod < sMAX_NUM_TREE_LOD_LEVELS; lod++) + { + slices = sLODSlices[lod]; + sLODVertexOffset[lod] = max_vertices; + sLODVertexCount[lod] = slices*slices; + sLODIndexOffset[lod] = max_indices; + sLODIndexCount[lod] = (slices-1)*(slices-1)*6; + max_indices += sLODIndexCount[lod]; + max_vertices += sLODVertexCount[lod]; + } + + mReferenceBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); + if (!mReferenceBuffer->allocateBuffer(max_vertices, max_indices)) + { + LL_WARNS() << "Failed to allocate Vertex Buffer on update to " + << max_vertices << " vertices and " + << max_indices << " indices" << LL_ENDL; + mReferenceBuffer = NULL; //unref + return true; + } + + LLStrider vertices; + LLStrider normals; + LLStrider colors; + LLStrider tex_coords; + LLStrider indicesp; + + mReferenceBuffer->getVertexStrider(vertices); + mReferenceBuffer->getNormalStrider(normals); + mReferenceBuffer->getTexCoord0Strider(tex_coords); + mReferenceBuffer->getColorStrider(colors); + mReferenceBuffer->getIndexStrider(indicesp); + + S32 vertex_count = 0; + S32 index_count = 0; + + // First leaf + *(normals++) = LLVector3(-SRR2, -SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); + *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f); + *(colors++) = LLColor4U::white; + vertex_count++; + + *(normals++) = LLVector3(SRR3, -SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); + *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f); + *(colors++) = LLColor4U::white; + vertex_count++; + + *(normals++) = LLVector3(-SRR3, -SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); + *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f); + *(colors++) = LLColor4U::white; + vertex_count++; + + *(normals++) = LLVector3(SRR2, -SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); + *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f); + *(colors++) = LLColor4U::white; + vertex_count++; + + *(indicesp++) = 0; + index_count++; + *(indicesp++) = 1; + index_count++; + *(indicesp++) = 2; + index_count++; + + *(indicesp++) = 0; + index_count++; + *(indicesp++) = 3; + index_count++; + *(indicesp++) = 1; + index_count++; + + // Same leaf, inverse winding/normals + *(normals++) = LLVector3(-SRR2, SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); + *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f); + *(colors++) = LLColor4U::white; + vertex_count++; + + *(normals++) = LLVector3(SRR3, SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); + *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f); + *(colors++) = LLColor4U::white; + vertex_count++; + + *(normals++) = LLVector3(-SRR3, SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); + *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f); + *(colors++) = LLColor4U::white; + vertex_count++; + + *(normals++) = LLVector3(SRR2, SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); + *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f); + *(colors++) = LLColor4U::white; + vertex_count++; + + *(indicesp++) = 4; + index_count++; + *(indicesp++) = 6; + index_count++; + *(indicesp++) = 5; + index_count++; + + *(indicesp++) = 4; + index_count++; + *(indicesp++) = 5; + index_count++; + *(indicesp++) = 7; + index_count++; + + + // next leaf + *(normals++) = LLVector3(SRR2, -SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); + *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f); + *(colors++) = LLColor4U::white; + vertex_count++; + + *(normals++) = LLVector3(SRR3, SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); + *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f); + *(colors++) = LLColor4U::white; + vertex_count++; + + *(normals++) = LLVector3(SRR3, -SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); + *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f); + *(colors++) = LLColor4U::white; + vertex_count++; + + *(normals++) = LLVector3(SRR2, SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); + *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f); + *(colors++) = LLColor4U::white; + vertex_count++; + + *(indicesp++) = 8; + index_count++; + *(indicesp++) = 9; + index_count++; + *(indicesp++) = 10; + index_count++; + + *(indicesp++) = 8; + index_count++; + *(indicesp++) = 11; + index_count++; + *(indicesp++) = 9; + index_count++; + + + // other side of same leaf + *(normals++) = LLVector3(-SRR2, -SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); + *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f); + *(colors++) = LLColor4U::white; + vertex_count++; + + *(normals++) = LLVector3(-SRR3, SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); + *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f); + *(colors++) = LLColor4U::white; + vertex_count++; + + *(normals++) = LLVector3(-SRR3, -SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); + *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f); + *(colors++) = LLColor4U::white; + vertex_count++; + + *(normals++) = LLVector3(-SRR2, SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); + *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f); + *(colors++) = LLColor4U::white; + vertex_count++; + + *(indicesp++) = 12; + index_count++; + *(indicesp++) = 14; + index_count++; + *(indicesp++) = 13; + index_count++; + + *(indicesp++) = 12; + index_count++; + *(indicesp++) = 13; + index_count++; + *(indicesp++) = 15; + index_count++; + + // Generate geometry for the cylinders + + // Different LOD's + + // Generate the vertices + // Generate the indices + + for (lod = 0; lod < sMAX_NUM_TREE_LOD_LEVELS; lod++) + { + slices = sLODSlices[lod]; + F32 base_radius = 0.65f; + F32 top_radius = base_radius * sSpeciesTable[mSpecies]->mTaper; + //LL_INFOS() << "Species " << ((U32) mSpecies) << ", taper = " << sSpeciesTable[mSpecies].mTaper << LL_ENDL; + //LL_INFOS() << "Droop " << mDroop << ", branchlength: " << mBranchLength << LL_ENDL; + F32 angle = 0; + F32 angle_inc = 360.f/(slices-1); + F32 z = 0.f; + F32 z_inc = 1.f; + if (slices > 3) + { + z_inc = 1.f/(slices - 3); + } + F32 radius = base_radius; + + F32 x1,y1; + F32 noise_scale = sSpeciesTable[mSpecies]->mNoiseMag; + LLVector3 nvec; + + const F32 cap_nudge = 0.1f; // Height to 'peak' the caps on top/bottom of branch + + const S32 fractal_depth = 5; + F32 nvec_scale = 1.f * sSpeciesTable[mSpecies]->mNoiseScale; + F32 nvec_scalez = 4.f * sSpeciesTable[mSpecies]->mNoiseScale; + + F32 tex_z_repeat = sSpeciesTable[mSpecies]->mRepeatTrunkZ; + + F32 start_radius; + F32 nangle = 0; + F32 height = 1.f; + F32 r0; + + for (i = 0; i < slices; i++) + { + if (i == 0) + { + z = - cap_nudge; + r0 = 0.0; + } + else if (i == (slices - 1)) + { + z = 1.f + cap_nudge;//((i - 2) * z_inc) + cap_nudge; + r0 = 0.0; + } + else + { + z = (i - 1) * z_inc; + r0 = base_radius + (top_radius - base_radius)*z; + } + + for (j = 0; j < slices; j++) + { + if (slices - 1 == j) + { + angle = 0.f; + } + else + { + angle = j*angle_inc; + } + + nangle = angle; + + x1 = cos(angle * DEG_TO_RAD); + y1 = sin(angle * DEG_TO_RAD); + LLVector2 tc; + // This isn't totally accurate. Should compute based on slope as well. + start_radius = r0 * (1.f + 1.2f*fabs(z - 0.66f*height)/height); + nvec.set( cos(nangle * DEG_TO_RAD)*start_radius*nvec_scale, + sin(nangle * DEG_TO_RAD)*start_radius*nvec_scale, + z*nvec_scalez); + // First and last slice at 0 radius (to bring in top/bottom of structure) + radius = start_radius + turbulence3((F32*)&nvec.mV, (F32)fractal_depth)*noise_scale; + + if (slices - 1 == j) + { + // Not 0.5 for slight slop factor to avoid edges on leaves + tc = LLVector2(0.490f, (1.f - z/2.f)*tex_z_repeat); + } + else + { + tc = LLVector2((angle/360.f)*0.5f, (1.f - z/2.f)*tex_z_repeat); + } + + *(vertices++) = LLVector3(x1*radius, y1*radius, z); + *(normals++) = LLVector3(x1, y1, 0.f); + *(tex_coords++) = tc; + *(colors++) = LLColor4U::white; + vertex_count++; + } + } + + for (i = 0; i < (slices - 1); i++) + { + for (j = 0; j < (slices - 1); j++) + { + S32 x1_offset = j+1; + if ((j+1) == slices) + { + x1_offset = 0; + } + // Generate the matching quads + *(indicesp) = j + (i*slices) + sLODVertexOffset[lod]; + llassert(*(indicesp) < (U32)max_vertices); + indicesp++; + index_count++; + *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod]; + llassert(*(indicesp) < (U32)max_vertices); + indicesp++; + index_count++; + *(indicesp) = j + ((i+1)*slices) + sLODVertexOffset[lod]; + llassert(*(indicesp) < (U32)max_vertices); + indicesp++; + index_count++; + + *(indicesp) = j + (i*slices) + sLODVertexOffset[lod]; + llassert(*(indicesp) < (U32)max_vertices); + indicesp++; + index_count++; + *(indicesp) = x1_offset + (i*slices) + sLODVertexOffset[lod]; + llassert(*(indicesp) < (U32)max_vertices); + indicesp++; + index_count++; + *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod]; + llassert(*(indicesp) < (U32)max_vertices); + indicesp++; + index_count++; + } + } + slices /= 2; + } + + mReferenceBuffer->unmapBuffer(); + llassert(vertex_count == max_vertices); + llassert(index_count == max_indices); +#ifndef SHOW_ASSERT + (void)vertex_count; + (void)index_count; +#endif + } + + //generate tree mesh + updateMesh(); + + return true; +} + +void LLVOTree::updateMesh() +{ + LLMatrix4 matrix; + + // Translate to tree base HACK - adjustment in Z plants tree underground + const LLVector3 &pos_region = getPositionRegion(); + //gGL.translatef(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); + LLMatrix4 trans_mat; + trans_mat.setTranslation(pos_region.mV[VX], pos_region.mV[VY], pos_region.mV[VZ] - 0.1f); + trans_mat *= matrix; + + // Rotate to tree position and bend for current trunk/wind + // Note that trunk stiffness controls the amount of bend at the trunk as + // opposed to the crown of the tree + // + const F32 TRUNK_STIFF = 22.f; + + LLQuaternion rot = + LLQuaternion(mTrunkBend.magVec()*TRUNK_STIFF*DEG_TO_RAD, LLVector4(mTrunkBend.mV[VX], mTrunkBend.mV[VY], 0)) * + LLQuaternion(90.f*DEG_TO_RAD, LLVector4(0,0,1)) * + getRotation(); + + LLMatrix4 rot_mat(rot); + rot_mat *= trans_mat; + + F32 radius = getScale().magVec()*0.05f; + LLMatrix4 scale_mat; + scale_mat.mMatrix[0][0] = + scale_mat.mMatrix[1][1] = + scale_mat.mMatrix[2][2] = radius; + + scale_mat *= rot_mat; + +// const F32 THRESH_ANGLE_FOR_BILLBOARD = 15.f; +// const F32 BLEND_RANGE_FOR_BILLBOARD = 3.f; + + F32 droop = mDroop + 25.f*(1.f - mTrunkBend.magVec()); + + S32 stop_depth = 0; + F32 alpha = 1.0; + + U32 vert_count = 0; + U32 index_count = 0; + + calcNumVerts(vert_count, index_count, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, mBranches); + + LLFace* facep = mDrawable->getFace(0); + if (!facep) return; + LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); + if (!buff->allocateBuffer(vert_count, index_count)) + { + LL_WARNS() << "Failed to allocate Vertex Buffer on mesh update to " + << vert_count << " vertices and " + << index_count << " indices" << LL_ENDL; + buff->allocateBuffer(1, 3); + memset((U8*)buff->getMappedData(), 0, buff->getSize()); + memset((U8*)buff->getMappedIndices(), 0, buff->getIndicesSize()); + facep->setSize(1, 3); + facep->setVertexBuffer(buff); + mReferenceBuffer->unmapBuffer(); + buff->unmapBuffer(); + return; + } + + facep->setVertexBuffer(buff); + + LLStrider vertices; + LLStrider normals; + LLStrider tex_coords; + LLStrider colors; + LLStrider indices; + U16 idx_offset = 0; + + buff->getVertexStrider(vertices); + buff->getNormalStrider(normals); + buff->getTexCoord0Strider(tex_coords); + buff->getColorStrider(colors); + buff->getIndexStrider(indices); + + genBranchPipeline(vertices, normals, tex_coords, colors, indices, idx_offset, scale_mat, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, 1.0, mTwist, droop, mBranches, alpha); + + mReferenceBuffer->unmapBuffer(); + buff->unmapBuffer(); +} + +void LLVOTree::appendMesh(LLStrider& vertices, + LLStrider& normals, + LLStrider& tex_coords, + LLStrider& colors, + LLStrider& indices, + U16& cur_idx, + LLMatrix4& matrix, + LLMatrix4& norm_mat, + S32 vert_start, + S32 vert_count, + S32 index_count, + S32 index_offset) +{ + LLStrider v; + LLStrider n; + LLStrider t; + LLStrider c; + LLStrider idx; + + mReferenceBuffer->getVertexStrider(v); + mReferenceBuffer->getNormalStrider(n); + mReferenceBuffer->getTexCoord0Strider(t); + mReferenceBuffer->getColorStrider(c); + mReferenceBuffer->getIndexStrider(idx); + + //copy/transform vertices into mesh - check + for (S32 i = 0; i < vert_count; i++) + { + U16 index = vert_start + i; + *vertices++ = v[index] * matrix; + LLVector3 norm = n[index] * norm_mat; + norm.normalize(); + *normals++ = norm; + *tex_coords++ = t[index]; + *colors++ = c[index]; + } + + //copy offset indices into mesh - check + for (S32 i = 0; i < index_count; i++) + { + U16 index = index_offset + i; + *indices++ = idx[index]-vert_start+cur_idx; + } + + //increment index offset - check + cur_idx += vert_count; +} + + +void LLVOTree::genBranchPipeline(LLStrider& vertices, + LLStrider& normals, + LLStrider& tex_coords, + LLStrider& colors, + LLStrider& indices, + U16& index_offset, + LLMatrix4& matrix, + S32 trunk_LOD, + S32 stop_level, + U16 depth, + U16 trunk_depth, + F32 scale, + F32 twist, + F32 droop, + F32 branches, + F32 alpha) +{ + // + // Generates a tree mesh by recursing, generating branches and then a 'leaf' texture. + + static F32 constant_twist; + static F32 width = 0; + + F32 length = ((trunk_depth || (scale == 1.f))? mTrunkLength:mBranchLength); + F32 aspect = ((trunk_depth || (scale == 1.f))? mTrunkAspect:mBranchAspect); + + constant_twist = 360.f/branches; + + if (stop_level >= 0) + { + 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; + + glh::matrix4f norm((F32*) scale_mat.mMatrix); + LLMatrix4 norm_mat = LLMatrix4(norm.inverse().transpose().m); + + norm_mat.invert(); + appendMesh(vertices, normals, tex_coords, colors, indices, index_offset, scale_mat, norm_mat, + sLODVertexOffset[trunk_LOD], sLODVertexCount[trunk_LOD], sLODIndexCount[trunk_LOD], sLODIndexOffset[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; + + genBranchPipeline(vertices, normals, tex_coords, colors, indices, index_offset, rot_mat, 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 + genBranchPipeline(vertices, normals, tex_coords, colors, indices, index_offset, rot_mat, trunk_LOD, stop_level, depth, trunk_depth-1, scale*mScaleStep, twist, droop, branches, alpha); + } + } + else + { + // + // Append 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; + + glh::matrix4f norm((F32*) scale_mat.mMatrix); + LLMatrix4 norm_mat = LLMatrix4(norm.inverse().transpose().m); + + appendMesh(vertices, normals, tex_coords, colors, indices, index_offset, scale_mat, norm_mat, 0, LEAF_VERTICES, LEAF_INDICES, 0); + } + } + } +} + + + +void LLVOTree::calcNumVerts(U32& vert_count, U32& index_count, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 branches) +{ + if (stop_level >= 0) + { + if (depth > stop_level) + { + index_count += sLODIndexCount[trunk_LOD]; + vert_count += sLODVertexCount[trunk_LOD]; + + // Recurse to create more branches + for (S32 i=0; i < (S32)branches; i++) + { + calcNumVerts(vert_count, index_count, trunk_LOD, stop_level, depth - 1, 0, branches); + } + + // Recurse to continue trunk + if (trunk_depth) + { + calcNumVerts(vert_count, index_count, trunk_LOD, stop_level, depth, trunk_depth-1, branches); + } + } + else + { + index_count += LEAF_INDICES; + vert_count += LEAF_VERTICES; + } + } + else + { + index_count += LEAF_INDICES; + vert_count += LEAF_VERTICES; + } +} + +void LLVOTree::updateRadius() +{ + if (mDrawable.isNull()) + { + return; + } + + mDrawable->setRadius(32.0f); +} + +void LLVOTree::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) +{ + F32 radius = getScale().length()*0.05f; + LLVector3 center = getRenderPosition(); + + F32 sz = mBillboardScale*mBillboardRatio*radius*0.5f; + LLVector3 size(sz,sz,sz); + + center += LLVector3(0, 0, size.mV[2]) * getRotation(); + + newMin.load3((center-size).mV); + newMax.load3((center+size).mV); + LLVector4a pos; + pos.load3(center.mV); + mDrawable->setPositionGroup(pos); +} + +bool LLVOTree::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, bool pick_transparent, bool pick_rigged, bool pick_unselectable, S32 *face_hitp, + LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) + +{ + + if (!lineSegmentBoundingBox(start, end)) + { + return false; + } + + const LLVector4a* exta = mDrawable->getSpatialExtents(); + + //VECTORIZE THIS + LLVector3 ext[2]; + ext[0].set(exta[0].getF32ptr()); + ext[1].set(exta[1].getF32ptr()); + + LLVector3 center = (ext[1]+ext[0])*0.5f; + LLVector3 size = (ext[1]-ext[0]); + + LLQuaternion quat = getRotation(); + + center -= LLVector3(0,0,size.magVec() * 0.25f)*quat; + + size.scaleVec(LLVector3(0.25f, 0.25f, 1.f)); + size.mV[0] = llmin(size.mV[0], 1.f); + size.mV[1] = llmin(size.mV[1], 1.f); + + LLVector3 pos, norm; + + LLVector3 start3(start.getF32ptr()); + LLVector3 end3(end.getF32ptr()); + + if (linesegment_tetrahedron(start3, end3, center, size, quat, pos, norm)) + { + if (intersection) + { + intersection->load3(pos.mV); + } + + if (normal) + { + normal->load3(norm.mV); + } + return true; + } + + return false; +} + +U32 LLVOTree::getPartitionType() const +{ + return LLViewerRegion::PARTITION_TREE; +} + +LLTreePartition::LLTreePartition(LLViewerRegion* regionp) +: LLSpatialPartition(0, false, regionp) +{ + mDrawableType = LLPipeline::RENDER_TYPE_TREE; + mPartitionType = LLViewerRegion::PARTITION_TREE; + mSlopRatio = 0.f; + mLODPeriod = 1; +} + -- cgit v1.2.3