12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076 |
- /**
- * @file llvograss.cpp
- * @brief Not a blade, but a clump of grass
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "llviewerprecompiledheaders.h"
- #include "llvograss.h"
- #include "imageids.h"
- #include "lldir.h"
- #include "llfasttimer.h"
- #include "llnotifications.h"
- #include "llxmltree.h"
- #include "llagent.h"
- #include "lldrawable.h"
- #include "lldrawpoolalpha.h"
- #include "llface.h"
- #include "llpipeline.h"
- #include "llselectmgr.h"
- #include "llsky.h"
- #include "llspatialpartition.h"
- #include "llsurface.h"
- #include "llsurfacepatch.h"
- #include "llviewercamera.h"
- #include "llviewercontrol.h"
- #include "llviewerregion.h"
- #include "llviewertexturelist.h"
- #include "llvotree.h"
- #include "llvosky.h"
- #include "llworld.h"
- constexpr S32 GRASS_MAX_BLADES = 32;
- constexpr F32 GRASS_BLADE_BASE = 0.25f; // Width of grass at base
- constexpr F32 GRASS_BLADE_HEIGHT = 0.5f; // In meters
- constexpr F32 GRASS_DISTRIBUTION_SD = 0.15f; // Empirically defined
- F32 exp_x[GRASS_MAX_BLADES];
- F32 exp_y[GRASS_MAX_BLADES];
- F32 rot_x[GRASS_MAX_BLADES];
- F32 rot_y[GRASS_MAX_BLADES];
- F32 dz_x [GRASS_MAX_BLADES];
- F32 dz_y [GRASS_MAX_BLADES];
- // Factor to modulate wind movement by to randomize appearance
- F32 w_mod[GRASS_MAX_BLADES];
- LLVOGrass::data_map_t LLVOGrass::sSpeciesTable;
- LLVOGrass::species_list_t LLVOGrass::sSpeciesNames;
- S32 LLVOGrass::sMaxGrassSpecies = 0;
- ///////////////////////////////////////////////////////////////////////////////
- // LLVOGrass class
- ///////////////////////////////////////////////////////////////////////////////
- LLVOGrass::LLVOGrass(const LLUUID& id, LLViewerRegion* regionp)
- : LLAlphaObject(id, LL_PCODE_LEGACY_GRASS, regionp),
- mPatch(NULL),
- mLastPatchUpdateTime(0),
- mNumBlades(GRASS_MAX_BLADES)
- {
- mCanSelect = true;
- setNumTEs(1);
- setTEColor(0, LLColor4(1.f, 1.f, 1.f, 1.f));
- }
- void LLVOGrass::updateSpecies()
- {
- mSpecies = mAttachmentState;
- if (!sSpeciesTable.count(mSpecies))
- {
- llinfos << "Unknown grass type, substituting grass type." << llendl;
- data_map_t::const_iterator it = sSpeciesTable.begin();
- mSpecies = it->first;
- }
- setTEImage(0,
- LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID,
- FTT_DEFAULT,
- true,
- LLGLTexture::BOOST_NONE,
- LLViewerTexture::LOD_TEXTURE));
- }
- void LLVOGrass::initClass()
- {
- std::string xml_filename = gDirUtil.getFullPath(LL_PATH_APP_SETTINGS,
- "grass.xml");
- LLXmlTree grass_def_grass;
- if (!grass_def_grass.parseFile(xml_filename))
- {
- llerrs << "Failed to parse grass file." << llendl;
- return;
- }
- LLXmlTreeNode* rootp = grass_def_grass.getRoot();
- if (!rootp)
- {
- llerrs << "Failed to parse grass file." << llendl;
- return;
- }
- LLUUID id;
- F32 f32_val;
- for (LLXmlTreeNode* grass_def = rootp->getFirstChild(); grass_def;
- grass_def = rootp->getNextChild())
- {
- if (!grass_def->hasName("grass"))
- {
- llwarns << "Invalid grass definition node " << grass_def->getName()
- << llendl;
- continue;
- }
- bool success = true;
- S32 species;
- static LLStdStringHandle species_id_string =
- LLXmlTree::addAttributeString("species_id");
- if (!grass_def->getFastAttributeS32(species_id_string, species))
- {
- llwarns << "No species id defined" << llendl;
- continue;
- }
- if (species < 0)
- {
- llwarns << "Invalid species id " << species << llendl;
- continue;
- }
- GrassSpeciesData* new_grass = new GrassSpeciesData();
- static LLStdStringHandle texture_id_string =
- LLXmlTree::addAttributeString("texture_id");
- grass_def->getFastAttributeUUID(texture_id_string, id);
- new_grass->mTextureID = id;
- if (new_grass->mTextureID.isNull())
- {
- static LLStdStringHandle texture_name_string =
- LLXmlTree::addAttributeString("texture_name");
- std::string tex_name;
- success &= grass_def->getFastAttributeString(texture_name_string,
- tex_name);
- LLViewerTexture* grass_image =
- LLViewerTextureManager::getFetchedTextureFromFile(tex_name);
- new_grass->mTextureID = grass_image->getID();
- }
- static LLStdStringHandle blade_sizex_string =
- LLXmlTree::addAttributeString("blade_size_x");
- success &= grass_def->getFastAttributeF32(blade_sizex_string, f32_val);
- new_grass->mBladeSizeX = f32_val;
- static LLStdStringHandle blade_sizey_string =
- LLXmlTree::addAttributeString("blade_size_y");
- success &= grass_def->getFastAttributeF32(blade_sizey_string, f32_val);
- new_grass->mBladeSizeY = f32_val;
- if (sSpeciesTable.count(species))
- {
- llinfos << "Grass species " << species
- << " already defined ! Duplicate discarded." << llendl;
- delete new_grass;
- continue;
- }
- else
- {
- sSpeciesTable[species] = new_grass;
- }
- if (species >= sMaxGrassSpecies)
- {
- sMaxGrassSpecies = species + 1;
- }
- std::string name;
- static LLStdStringHandle name_string =
- LLXmlTree::addAttributeString("name");
- success &= grass_def->getFastAttributeString(name_string, name);
- sSpeciesNames[name] = species;
- if (!success)
- {
- llwarns << "Incomplete definition of grass " << name << llendl;
- }
- }
- bool have_all_grass = true;
- std::string err;
- for (S32 i = 0; i < sMaxGrassSpecies; ++i)
- {
- if (!sSpeciesTable.count(i))
- {
- err.append(llformat(" %d", i));
- have_all_grass = false;
- }
- }
- if (!have_all_grass)
- {
- LLSD args;
- args["SPECIES"] = err;
- gNotifications.add("ErrorUndefinedGrasses", args);
- }
- // Create nifty list of exponential distribution 0-1
- F32 x = 0.f;
- F32 y = 0.f;
- F32 rot;
- for (S32 i = 0; i < GRASS_MAX_BLADES; ++i)
- {
- #if 0 // Set to 1 for X blading
- if (i % 2 == 0)
- {
- F32 u = sqrtf(-2.f * logf(ll_frand()));
- F32 v = 2.f * F_PI * ll_frand();
- x = u * sinf(v) * GRASS_DISTRIBUTION_SD;
- y = u * cosf(v) * GRASS_DISTRIBUTION_SD;
- rot = ll_frand(F_PI);
- }
- else
- {
- rot += (F_PI * 0.4f + ll_frand(0.2f * F_PI));
- }
- #else
- F32 u = sqrtf(-2.f * logf(ll_frand()));
- F32 v = 2.f * F_PI * ll_frand();
- x = u * sinf(v) * GRASS_DISTRIBUTION_SD;
- y = u * cosf(v) * GRASS_DISTRIBUTION_SD;
- rot = ll_frand(F_PI);
- #endif
- exp_x[i] = x;
- exp_y[i] = y;
- rot_x[i] = sinf(rot);
- rot_y[i] = cosf(rot);
- dz_x[i] = ll_frand(GRASS_BLADE_BASE * 0.25f);
- dz_y[i] = ll_frand(GRASS_BLADE_BASE * 0.25f);
- // Degree to which blade is moved by wind
- w_mod[i] = 0.5f + ll_frand();
- }
- }
- void LLVOGrass::cleanupClass()
- {
- for_each(sSpeciesTable.begin(), sSpeciesTable.end(),
- DeletePairedPointer());
- sSpeciesTable.clear();
- }
- U32 LLVOGrass::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);
- updateSpecies();
- if (getVelocity().lengthSquared() > 0.f ||
- getAcceleration().lengthSquared() > 0.f ||
- getAngularVelocity().lengthSquared() > 0.f)
- {
- llinfos << "ACK ! Moving grass !" << llendl;
- setVelocity(LLVector3::zero);
- setAcceleration(LLVector3::zero);
- setAngularVelocity(LLVector3::zero);
- }
- if (mDrawable)
- {
- gPipeline.markRebuild(mDrawable);
- }
- return retval;
- }
- void LLVOGrass::idleUpdate(F64 time)
- {
- if (mDead || !gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_GRASS) ||
- !mDrawable) // So that drones work.
- {
- return;
- }
- if (LLVOTree::isTreeRenderingStopped()) // Stop rendering grass
- {
- if (mNumBlades)
- {
- mNumBlades = 0;
- gPipeline.markRebuild(mDrawable);
- }
- return;
- }
- if (!mNumBlades) // Restart grass rendering
- {
- mNumBlades = GRASS_MAX_BLADES;
- gPipeline.markRebuild(mDrawable);
- return;
- }
- if (mPatch && mLastPatchUpdateTime != mPatch->getLastUpdateTime())
- {
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME);
- }
- }
- void LLVOGrass::setPixelAreaAndAngle()
- {
- // This should be the camera's center, as soon as we move to all
- // region-local.
- LLVector3 relative_position = getPositionAgent() -
- gAgent.getCameraPositionAgent();
- F32 range = relative_position.length();
- F32 max_scale = getMaxScale();
- mAppAngle = atan2f(max_scale, range) * RAD_TO_DEG;
- // Compute pixels per meter at the given range
- F32 pixels_per_meter = gViewerCamera.getViewHeightInPixels() /
- (tanf(gViewerCamera.getView()) * range);
- // Assume grass texture is a 5 meter by 5 meter sprite at the grass
- // object's center
- mPixelArea = pixels_per_meter * pixels_per_meter * 25.f;
- }
- // *TODO: could speed this up by caching the relative_position and range
- // calculations
- void LLVOGrass::updateTextures()
- {
- if (getTEImage(0))
- {
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
- {
- setDebugText(llformat("%4.0f", sqrtf(mPixelArea)));
- }
- getTEImage(0)->addTextureStats(mPixelArea);
- }
- }
- bool LLVOGrass::updateLOD()
- {
- if (mDrawable->getNumFaces() <= 0)
- {
- return false;
- }
- if (LLVOTree::isTreeRenderingStopped())
- {
- if (mNumBlades)
- {
- mNumBlades = 0;
- gPipeline.markRebuild(mDrawable);
- }
- return true;
- }
- if (!mNumBlades)
- {
- mNumBlades = GRASS_MAX_BLADES;
- }
- LLFace* face = mDrawable->getFace(0);
- if (!face)
- {
- return false;
- }
- F32 tan_angle = mScale.mV[0] * mScale.mV[1] /
- mDrawable->mDistanceWRTCamera;
- S32 num_blades = llmin(GRASS_MAX_BLADES, lltrunc(tan_angle * 5.f));
- num_blades = llmax(1, num_blades);
- if (num_blades >= (mNumBlades << 1))
- {
- while (mNumBlades < num_blades)
- {
- mNumBlades <<= 1;
- }
- face->setSize(mNumBlades * 8, mNumBlades * 12);
- gPipeline.markRebuild(mDrawable);
- }
- else if (num_blades <= (mNumBlades >> 1))
- {
- while (mNumBlades > num_blades)
- {
- mNumBlades >>= 1;
- }
- face->setSize(mNumBlades * 8, mNumBlades * 12);
- gPipeline.markRebuild(mDrawable);
- return true;
- }
- return false;
- }
- LLDrawable* LLVOGrass::createDrawable()
- {
- gPipeline.allocDrawable(this);
- mDrawable->setRenderType(LLPipeline::RENDER_TYPE_GRASS);
- return mDrawable;
- }
- bool LLVOGrass::updateGeometry(LLDrawable* drawable)
- {
- LL_FAST_TIMER(FTM_UPDATE_GRASS);
- dirtySpatialGroup();
- if (!mNumBlades) // Stop rendering grass
- {
- if (mDrawable->getNumFaces() > 0)
- {
- LLFace* facep = mDrawable->getFace(0);
- if (facep)
- {
- facep->setSize(0, 0);
- }
- }
- }
- else
- {
- plantBlades();
- }
- return true;
- }
- void LLVOGrass::plantBlades()
- {
- // It is possible that the species of a grass is not defined. This is bad,
- // but not the end of the world.
- if (!sSpeciesTable.count(mSpecies))
- {
- llinfos << "Unknown grass species " << mSpecies << llendl;
- return;
- }
- if (mDrawable->getNumFaces() < 1)
- {
- mDrawable->setNumFaces(1, NULL, getTEImage(0));
- }
- LLFace* face = mDrawable->getFace(0);
- if (!face)
- {
- return;
- }
- face->setDiffuseMap(getTEImage(0));
- face->setState(LLFace::GLOBAL);
- face->setSize(mNumBlades * 8, mNumBlades * 12);
- face->setVertexBuffer(NULL);
- face->setTEOffset(0);
- face->mCenterLocal = mPosition + mRegionp->getOriginAgent();
- mDepth = (face->mCenterLocal - gViewerCamera.getOrigin()) *
- gViewerCamera.getAtAxis();
- mDrawable->setPosition(face->mCenterLocal);
- mDrawable->movePartition();
- }
- void LLVOGrass::getGeometry(S32 idx,
- LLStrider<LLVector4a>& verticesp,
- LLStrider<LLVector3>& normalsp,
- LLStrider<LLVector2>& texcoordsp,
- LLStrider<LLColor4U>& colorsp,
- LLStrider<LLColor4U>& emissivep,
- LLStrider<U16>& indicesp)
- {
- if (!mNumBlades) // stop rendering grass
- {
- return;
- }
- mPatch = mRegionp->getLand().resolvePatchRegion(getPositionRegion());
- if (mPatch)
- {
- mLastPatchUpdateTime = mPatch->getLastUpdateTime();
- }
- LLVector3 position;
- // Create random blades of grass with gaussian distribution
- F32 x, y, xf, yf, dzx, dzy;
- LLColor4U color(255, 255, 255, 255);
- LLFace* face = mDrawable->getFace(idx);
- if (!face)
- {
- return;
- }
- F32 width = sSpeciesTable[mSpecies]->mBladeSizeX;
- F32 height = sSpeciesTable[mSpecies]->mBladeSizeY;
- U32 index_offset = face->getGeomIndex();
- LLVector3 origin_agent = mRegionp->getOriginAgent();
- for (S32 i = 0; i < mNumBlades; ++i)
- {
- x = exp_x[i] * mScale.mV[VX];
- y = exp_y[i] * mScale.mV[VY];
- xf = rot_x[i] * GRASS_BLADE_BASE * width * w_mod[i];
- yf = rot_y[i] * GRASS_BLADE_BASE * width * w_mod[i];
- dzx = dz_x [i];
- dzy = dz_y [i];
- LLVector3 v1, v2, v3;
- F32 blade_height = GRASS_BLADE_HEIGHT * height * w_mod[i];
- *texcoordsp++ = LLVector2(0, 0);
- *texcoordsp++ = LLVector2(0, 0);
- *texcoordsp++ = LLVector2(0, 0.98f);
- *texcoordsp++ = LLVector2(0, 0.98f);
- *texcoordsp++ = LLVector2(1, 0);
- *texcoordsp++ = LLVector2(1, 0);
- *texcoordsp++ = LLVector2(1, 0.98f);
- *texcoordsp++ = LLVector2(1, 0.98f);
- position.mV[0] = mPosition.mV[VX] + x + xf;
- position.mV[1] = mPosition.mV[VY] + y + yf;
- position.mV[2] = mRegionp->getLand().resolveHeightRegion(position);
- v1 = position + origin_agent;
- (*verticesp++).load3(v1.mV);
- (*verticesp++).load3(v1.mV);
- position.mV[0] += dzx;
- position.mV[1] += dzy;
- position.mV[2] += blade_height;
- v2 = position + origin_agent;
- (*verticesp++).load3(v2.mV);
- (*verticesp++).load3(v2.mV);
- position.mV[0] = mPosition.mV[VX] + x - xf;
- position.mV[1] = mPosition.mV[VY] + y - xf;
- position.mV[2] = mRegionp->getLand().resolveHeightRegion(position);
- v3 = position + origin_agent;
- (*verticesp++).load3(v3.mV);
- (*verticesp++).load3(v3.mV);
- LLVector3 normal1 = (v1 - v2) % (v2 - v3);
- normal1.mV[VZ] = 0.75f;
- normal1.normalize();
- LLVector3 normal2 = -normal1;
- normal2.mV[VZ] = -normal2.mV[VZ];
- position.mV[0] += dzx;
- position.mV[1] += dzy;
- position.mV[2] += blade_height;
- v1 = position + origin_agent;
- (*verticesp++).load3(v1.mV);
- (*verticesp++).load3(v1.mV);
- *(normalsp++) = normal1;
- *(normalsp++) = normal2;
- *(normalsp++) = normal1;
- *(normalsp++) = normal2;
- *(normalsp++) = normal1;
- *(normalsp++) = normal2;
- *(normalsp++) = normal1;
- *(normalsp++) = normal2;
- *(colorsp++) = color;
- *(colorsp++) = color;
- *(colorsp++) = color;
- *(colorsp++) = color;
- *(colorsp++) = color;
- *(colorsp++) = color;
- *(colorsp++) = color;
- *(colorsp++) = color;
- *indicesp++ = index_offset;
- *indicesp++ = index_offset + 2;
- *indicesp++ = index_offset + 4;
- *indicesp++ = index_offset + 2;
- *indicesp++ = index_offset + 6;
- *indicesp++ = index_offset + 4;
- *indicesp++ = index_offset + 1;
- *indicesp++ = index_offset + 5;
- *indicesp++ = index_offset + 3;
- *indicesp++ = index_offset + 3;
- *indicesp++ = index_offset + 5;
- *indicesp++ = index_offset + 7;
- index_offset += 8;
- }
- }
- U32 LLVOGrass::getPartitionType() const
- {
- return LLViewerRegion::PARTITION_GRASS;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // LLGrassPartition class (declared in llspatialpartition.h)
- ///////////////////////////////////////////////////////////////////////////////
- LLGrassPartition::LLGrassPartition(LLViewerRegion* regionp)
- : LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK |
- LLVertexBuffer::MAP_TEXTURE_INDEX,
- true, regionp)
- {
- mDrawableType = LLPipeline::RENDER_TYPE_GRASS;
- mPartitionType = LLViewerRegion::PARTITION_GRASS;
- mLODPeriod = 16;
- mDepthMask = true;
- mSlopRatio = 0.1f;
- mRenderPass = LLRenderPass::PASS_GRASS;
- }
- //virtual
- void LLGrassPartition::addGeometryCount(LLSpatialGroup* group,
- U32& vertex_count,
- U32& index_count)
- {
- mFaceList.clear();
- for (LLSpatialGroup::element_iter i = group->getDataBegin();
- i != group->getDataEnd(); ++i)
- {
- LLDrawable* drawablep = (LLDrawable*)(*i)->getDrawable();
- if (!drawablep || drawablep->isDead())
- {
- continue;
- }
- LLViewerObject* vobj = drawablep->getVObj().get();
- if (!vobj) // Paranoia
- {
- llwarns_once << "NULL viewer object for drawable " << std::hex
- << drawablep << std::dec << llendl;
- continue;
- }
- LLAlphaObject* obj = vobj->asAlphaObject();
- if (!obj)
- {
- llwarns_once << "Not an alpha object for drawable " << std::hex
- << drawablep << std::dec << llendl;
- continue;
- }
- obj->mDepth = 0.f;
- U32 count = 0;
- for (S32 j = 0; j < drawablep->getNumFaces(); ++j)
- {
- drawablep->updateFaceSize(j);
- LLFace* facep = drawablep->getFace(j);
- if (!facep || !facep->hasGeometry())
- {
- continue;
- }
- if (facep->getGeomCount() + vertex_count <= 65536)
- {
- ++count;
- facep->mDistance = (facep->mCenterLocal -
- gViewerCamera.getOrigin()) *
- gViewerCamera.getAtAxis();
- obj->mDepth += facep->mDistance;
- mFaceList.push_back(facep);
- vertex_count += facep->getGeomCount();
- index_count += facep->getIndicesCount();
- llassert(facep->getIndicesCount() < 65536);
- }
- else
- {
- facep->clearVertexBuffer();
- }
- }
- obj->mDepth /= count;
- }
- }
- //virtual
- void LLGrassPartition::getGeometry(LLSpatialGroup* group)
- {
- LL_FAST_TIMER(FTM_REBUILD_GRASS_VB);
- std::sort(mFaceList.begin(), mFaceList.end(),
- LLFace::CompareDistanceGreater());
- U32 index_count = 0;
- U32 vertex_count = 0;
- group->clearDrawMap();
- LLVertexBuffer* buffer = group->mVertexBuffer;
- if (!buffer) return; // Paranoia
- LLStrider<U16> indicesp;
- LLStrider<LLVector4a> verticesp;
- LLStrider<LLVector3> normalsp;
- LLStrider<LLVector2> texcoordsp;
- LLStrider<LLColor4U> colorsp;
- if (!buffer->getVertexStrider(verticesp) ||
- !buffer->getNormalStrider(normalsp) ||
- !buffer->getColorStrider(colorsp) ||
- !buffer->getTexCoord0Strider(texcoordsp) ||
- !buffer->getIndexStrider(indicesp))
- {
- return;
- }
- LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass];
- for (U32 i = 0, count = mFaceList.size(); i < count; ++i)
- {
- LLFace* facep = mFaceList[i];
- LLViewerObject* vobj = facep->getViewerObject();
- if (!vobj) // Paranoia
- {
- llwarns_once << "NULL viewer object for face " << std::hex << facep
- << std::dec << llendl;
- continue;
- }
- LLAlphaObject* object = vobj->asAlphaObject();
- if (!object)
- {
- llwarns_once << "Not an alpha object for face " << std::hex
- << facep << std::dec << llendl;
- continue;
- }
- facep->setGeomIndex(vertex_count);
- facep->setIndicesIndex(index_count);
- facep->setVertexBuffer(buffer);
- facep->setPoolType(LLDrawPool::POOL_ALPHA);
- // Dummy parameter (unused by this implementation)
- LLStrider<LLColor4U> emissivep;
- object->getGeometry(facep->getTEOffset(), verticesp, normalsp,
- texcoordsp, colorsp, emissivep, indicesp);
- vertex_count += facep->getGeomCount();
- index_count += facep->getIndicesCount();
- S32 idx = draw_vec.size() - 1;
- bool fullbright = facep->isState(LLFace::FULLBRIGHT);
- F32 vsize = facep->getVirtualSize();
- U16 geomcount = facep->getGeomCount();
- U32 indicescount = facep->getIndicesCount();
- if (idx >= 0 &&
- draw_vec[idx]->mEnd == facep->getGeomIndex() - 1 &&
- draw_vec[idx]->mTexture == facep->getTexture() &&
- (U32)(draw_vec[idx]->mEnd - draw_vec[idx]->mStart + geomcount) <=
- (U32)gGLManager.mGLMaxVertexRange &&
- #if 0
- draw_vec[idx]->mCount + indicescount <=
- (U32)gGLManager.mGLMaxIndexRange &&
- #endif
- draw_vec[idx]->mEnd - draw_vec[idx]->mStart + geomcount < 4096 &&
- draw_vec[idx]->mFullbright == fullbright)
- {
- draw_vec[idx]->mCount += indicescount;
- draw_vec[idx]->mEnd += geomcount;
- draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize);
- }
- else
- {
- U32 start = facep->getGeomIndex();
- U32 end = start + geomcount - 1;
- U32 offset = facep->getIndicesStart();
- LLDrawInfo* info = new LLDrawInfo(start, end, indicescount, offset,
- facep->getTexture(), buffer,
- fullbright);
- const LLVector4a* exts = group->getObjectExtents();
- info->mExtents[0] = exts[0];
- info->mExtents[1] = exts[1];
- info->mVSize = vsize;
- draw_vec.push_back(info);
- // For alpha sorting
- facep->setDrawInfo(info);
- }
- }
- buffer->unmapBuffer();
- mFaceList.clear();
- }
- //virtual
- void LLVOGrass::updateDrawable(bool force_damped)
- {
- // Force an immediate rebuild on any update
- if (mDrawable.notNull())
- {
- mDrawable->updateXform(true);
- gPipeline.markRebuild(mDrawable);
- }
- clearChanged(SHIFTED);
- }
- //virtual
- bool LLVOGrass::lineSegmentIntersect(const LLVector4a& start,
- const LLVector4a& end,
- S32 face,
- bool pick_transparent,
- bool pick_rigged,
- S32* face_hitp,
- LLVector4a* intersection,
- LLVector2* tex_coord,
- LLVector4a* normal,
- LLVector4a* tangent)
- {
- bool ret = false;
- if (!mCanSelect || mDrawable.isNull() || mDrawable->isDead() ||
- !gPipeline.hasRenderType(mDrawable->getRenderType()))
- {
- return false;
- }
- LLVector4a dir;
- dir.setSub(end, start);
- mPatch = mRegionp->getLand().resolvePatchRegion(getPositionRegion());
- LLVector3 position;
- // Create random blades of grass with gaussian distribution
- F32 x,y,xf,yf,dzx,dzy;
- LLColor4U color(255, 255, 255, 255);
- F32 width = sSpeciesTable[mSpecies]->mBladeSizeX;
- F32 height = sSpeciesTable[mSpecies]->mBladeSizeY;
- LLVector2 tc[4];
- LLVector3 v[4];
- F32 closest_t = 1.f;
- LLVector3 origin_agent = mRegionp->getOriginAgent();
- for (S32 i = 0; i < mNumBlades; ++i)
- {
- x = exp_x[i] * mScale.mV[VX];
- y = exp_y[i] * mScale.mV[VY];
- xf = rot_x[i] * GRASS_BLADE_BASE * width * w_mod[i];
- yf = rot_y[i] * GRASS_BLADE_BASE * width * w_mod[i];
- dzx = dz_x [i];
- dzy = dz_y [i];
- LLVector3 v1, v2, v3;
- F32 blade_height = GRASS_BLADE_HEIGHT * height * w_mod[i];
- tc[0] = LLVector2(0, 0);
- tc[1] = LLVector2(0, 0.98f);
- tc[2] = LLVector2(1, 0);
- tc[3] = LLVector2(1, 0.98f);
- position.mV[0] = mPosition.mV[VX] + x + xf;
- position.mV[1] = mPosition.mV[VY] + y + yf;
- position.mV[2] = mRegionp->getLand().resolveHeightRegion(position);
- v[0] = v1 = position + origin_agent;
- position.mV[0] += dzx;
- position.mV[1] += dzy;
- position.mV[2] += blade_height;
- v[1] = v2 = position + origin_agent;
- position.mV[0] = mPosition.mV[VX] + x - xf;
- position.mV[1] = mPosition.mV[VY] + y - xf;
- position.mV[2] = mRegionp->getLand().resolveHeightRegion(position);
- v[2] = v3 = position + origin_agent;
- LLVector3 normal1 = (v1 - v2) % (v2 - v3);
- normal1.normalize();
- position.mV[0] += dzx;
- position.mV[1] += dzy;
- position.mV[2] += blade_height;
- v[3] = v1 = position + origin_agent;
- F32 a, b, t;
- bool hit = false;
- U32 idx0 = 0, idx1 = 0, idx2 = 0;
- LLVector4a v0a, v1a, v2a, v3a;
- v0a.load3(v[0].mV);
- v1a.load3(v[1].mV);
- v2a.load3(v[2].mV);
- v3a.load3(v[3].mV);
- if (LLTriangleRayIntersect(v0a, v1a, v2a, start, dir, a, b, t))
- {
- hit = true;
- idx0 = 0; idx1 = 1; idx2 = 2;
- }
- else if (LLTriangleRayIntersect(v1a, v3a, v2a, start, dir, a, b, t))
- {
- hit = true;
- idx0 = 1; idx1 = 3; idx2 = 2;
- }
- else if (LLTriangleRayIntersect(v2a, v1a, v0a, start, dir, a, b, t))
- {
- normal1 = -normal1;
- hit = true;
- idx0 = 2; idx1 = 1; idx2 = 0;
- }
- else if (LLTriangleRayIntersect(v2a, v3a, v1a, start, dir, a, b, t))
- {
- normal1 = -normal1;
- hit = true;
- idx0 = 2; idx1 = 3; idx2 = 1;
- }
- if (hit)
- {
- if (t >= 0.f && t <= 1.f && t < closest_t)
- {
- LLVector2 hit_tc = ((1.f - a - b) * tc[idx0] + a * tc[idx1] +
- b * tc[idx2]);
- if (pick_transparent || getTEImage(0)->getMask(hit_tc))
- {
- closest_t = t;
- if (intersection != NULL)
- {
- dir.mul(closest_t);
- intersection->setAdd(start, dir);
- }
- if (tex_coord != NULL)
- {
- *tex_coord = hit_tc;
- }
- if (normal != NULL)
- {
- normal->load3(normal1.mV);
- }
- ret = true;
- }
- }
- }
- }
- return ret;
- }
- void LLVOGrass::generateSilhouetteVertices(std::vector<LLVector3>& vertices,
- std::vector<LLVector3>& normals,
- const LLVector3& obj_cam_vec,
- const LLMatrix4& mat,
- const LLMatrix3& norm_mat)
- {
- vertices.clear();
- normals.clear();
- F32 width = sSpeciesTable[mSpecies]->mBladeSizeX;
- F32 height = sSpeciesTable[mSpecies]->mBladeSizeY;
- LLVector3 origin_agent = mRegionp->getOriginAgent();
- for (S32 i = 0; i < mNumBlades; ++i)
- {
- F32 x = exp_x[i] * mScale.mV[VX];
- F32 y = exp_y[i] * mScale.mV[VY];
- F32 xf = rot_x[i] * GRASS_BLADE_BASE * width * w_mod[i];
- F32 yf = rot_y[i] * GRASS_BLADE_BASE * width * w_mod[i];
- F32 dzx = dz_x [i];
- F32 dzy = dz_y [i];
- F32 blade_height = GRASS_BLADE_HEIGHT * height * w_mod[i];
- LLVector3 position1;
- position1.mV[0] = mPosition.mV[VX] + x + xf;
- position1.mV[1] = mPosition.mV[VY] + y + yf;
- position1.mV[2] = mRegionp->getLand().resolveHeightRegion(position1);
- LLVector3 position2 = position1;
- position2.mV[0] += dzx;
- position2.mV[1] += dzy;
- position2.mV[2] += blade_height;
- LLVector3 position3;
- position3.mV[0] = mPosition.mV[VX] + x - xf;
- position3.mV[1] = mPosition.mV[VY] + y - xf;
- position3.mV[2] = mRegionp->getLand().resolveHeightRegion(position3);
- LLVector3 position4 = position3;
- position4.mV[0] += dzx;
- position4.mV[1] += dzy;
- position4.mV[2] += blade_height;
- LLVector3 normal = (position1 - position2) % (position2 - position3);
- normal.normalize();
- vertices.emplace_back(position1 + origin_agent);
- normals.emplace_back(normal);
- vertices.emplace_back(position2 + origin_agent);
- normals.emplace_back(normal);
- vertices.emplace_back(position2 + origin_agent);
- normals.emplace_back(normal);
- vertices.emplace_back(position4 + origin_agent);
- normals.emplace_back(normal);
- vertices.emplace_back(position4 + origin_agent);
- normals.emplace_back(normal);
- vertices.emplace_back(position3 + origin_agent);
- normals.emplace_back(normal);
- vertices.emplace_back(position3 + origin_agent);
- normals.emplace_back(normal);
- vertices.emplace_back(position1 + origin_agent);
- normals.emplace_back(normal);
- }
- }
- void LLVOGrass::generateSilhouette(LLSelectNode* nodep)
- {
- generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals,
- LLVector3::zero, LLMatrix4(), LLMatrix3());
- nodep->mSilhouetteGenerated = true;
- }
|