예제 #1
0
void LLVOTextBubble::getGeometry(S32 idx,
								LLStrider<LLVector3>& verticesp,
								LLStrider<LLVector3>& normalsp, 
								LLStrider<LLVector2>& texcoordsp,
								LLStrider<LLColor4U>& colorsp, 
								LLStrider<U16>& indicesp) 
{
	if (idx == 0 || idx == 2)
	{
		return;
	}

	const LLVolumeFace& face = getVolume()->getVolumeFace(idx);
	
	LLVector3 pos = getPositionAgent();
	LLColor4U color = LLColor4U(getTE(idx)->getColor());
	U32 offset = mDrawable->getFace(idx)->getGeomIndex();
	
	for (U32 i = 0; i < face.mVertices.size(); i++)
	{
		*verticesp++ = face.mVertices[i].mPosition.scaledVec(getScale()) + pos;
		*normalsp++ = face.mVertices[i].mNormal;
		*texcoordsp++ = face.mVertices[i].mTexCoord;
		*colorsp++ = color;
	}
	
	for (U32 i = 0; i < face.mIndices.size(); i++)
	{
		*indicesp++ = face.mIndices[i] + offset;
	}
}
예제 #2
0
void LLVOTree::setPixelAreaAndAngle(LLAgent &agent)
{
    // First calculate values as for any other object (for mAppAngle)
    LLViewerObject::setPixelAreaAndAngle(agent);

    // Re-calculate mPixelArea accurately

    // This should be the camera's center, as soon as we move to all region-local.
    LLVector3 relative_position = getPositionAgent() - agent.getCameraPositionAgent();
    F32 range = relative_position.length();				// ugh, square root

    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()) * range);

    mPixelArea = (pixels_per_meter) * (pixels_per_meter) * area;
#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
}
예제 #3
0
void LLVOPartGroup::updateSpatialExtents(LLVector3& newMin, LLVector3& newMax)
{		
	const LLVector3& pos_agent = getPositionAgent();
	newMin = pos_agent - mScale;
	newMax = pos_agent + mScale;
	mDrawable->setPositionGroup(pos_agent);
}
예제 #4
0
void LLVOTextBubble::updateTextures(LLAgent &agent)
{
	// Update the image levels of all textures...
	// First we do some quick checks.
	U32 i;

	// This doesn't take into account whether the object is in front
	// or behind...

	LLVector3 position_local = getPositionAgent() - agent.getCameraPositionAgent();
	F32 dot_product = position_local * agent.getFrameAgent().getAtAxis();
	F32 cos_angle = dot_product / position_local.magVec();

	if (cos_angle > 1.f)
	{
		cos_angle = 1.f;
	}

	for (i = 0; i < getNumTEs(); i++)
	{
		const LLTextureEntry *te = getTE(i);
		F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT);

		LLViewerImage *imagep = getTEImage(i);
		if (imagep)
		{
			imagep->addTextureStats(mPixelArea, texel_area_ratio, cos_angle);
		}
	}
}
BOOL LLVOClouds::updateGeometry(LLDrawable *drawable)
{
	LLFastTimer ftm(LLFastTimer::FTM_UPDATE_CLOUDS);
	if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS)))
	{
		return TRUE;
	}
	
	dirtySpatialGroup();

	LLFace *facep;
	
	S32 num_faces = mCloudGroupp->getNumPuffs();

	if (num_faces > drawable->getNumFaces())
	{
		drawable->setNumFacesFast(num_faces, NULL, getTEImage(0));
	}

	mDepth = (getPositionAgent()-LLViewerCamera::getInstance()->getOrigin())*LLViewerCamera::getInstance()->getAtAxis();

	S32 face_indx = 0;
	for ( ;	face_indx < num_faces; face_indx++)
	{
		facep = drawable->getFace(face_indx);
		if (!facep)
		{
			llwarns << "No facep for index " << face_indx << llendl;
			continue;
		}

		facep->setSize(4, 6);
		
		facep->setTEOffset(face_indx);
		facep->setTexture(getTEImage(0));
		const LLCloudPuff &puff = mCloudGroupp->getPuff(face_indx);
		const LLVector3 puff_pos_agent = gAgent.getPosAgentFromGlobal(puff.getPositionGlobal());
		facep->mCenterLocal = puff_pos_agent;
		/// Update cloud color based on sun color.
		LLColor4 float_color(LLColor3(gSky.getSunDiffuseColor() + gSky.getSunAmbientColor()),puff.getAlpha());
		facep->setFaceColor(float_color);
	}
	for ( ; face_indx < drawable->getNumFaces(); face_indx++)
	{
		facep = drawable->getFace(face_indx);
		if (!facep)
		{
			llwarns << "No facep for index " << face_indx << llendl;
			continue;
		}

		facep->setTEOffset(face_indx);
		facep->setSize(0,0);
	}

	drawable->movePartition();

	return TRUE;
}
예제 #6
0
void LLDrawable::updateDistance(LLCamera& camera, bool force_update)
{
	if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD)
	{
		llwarns << "Attempted to update distance for non-world camera." << llendl;
		return;
	}

	//switch LOD with the spatial group to avoid artifacts
	//LLSpatialGroup* sg = getSpatialGroup();

	LLVector3 pos;

	//if (!sg || sg->changeLOD())
	{
		LLVOVolume* volume = getVOVolume();
		if (volume)
		{
			if (getSpatialGroup())
			{
				pos.set(getPositionGroup().getF32ptr());
			}
			else
			{
				pos = getPositionAgent();
			}
			
			if (isState(LLDrawable::HAS_ALPHA))
			{
				for (S32 i = 0; i < getNumFaces(); i++)
				{
					LLFace* facep = getFace(i);
					if (force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA)
					{
						LLVector4a box;
						box.setSub(facep->mExtents[1], facep->mExtents[0]);
						box.mul(0.25f);
						LLVector3 v = (facep->mCenterLocal-camera.getOrigin());
						const LLVector3& at = camera.getAtAxis();
						for (U32 j = 0; j < 3; j++)
						{
							v.mV[j] -= box[j] * at.mV[j];
						}
						facep->mDistance = v * camera.getAtAxis();
					}
				}
			}	
		}
		else
		{
			pos = LLVector3(getPositionGroup().getF32ptr());
		}

		pos -= camera.getOrigin();	
		mDistanceWRTCamera = llround(pos.magVec(), 0.01f);
		mVObjp->updateLOD();
	}
}
예제 #7
0
BOOL LLVOClouds::updateGeometry(LLDrawable *drawable)
{
	LLFastTimer ftm(LLFastTimer::FTM_UPDATE_CLOUDS);
 	if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS)))
		return TRUE;
	
	LLFace *facep;
	
	S32 num_faces = mCloudGroupp->getNumPuffs();

	if (num_faces > drawable->getNumFaces())
	{
		drawable->setNumFacesFast(num_faces, NULL, getTEImage(0));
	}

	mDepth = (getPositionAgent()-gCamera->getOrigin())*gCamera->getAtAxis();

	S32 face_indx = 0;
	for ( ;	face_indx < num_faces; face_indx++)
	{
		facep = drawable->getFace(face_indx);
		if (!facep)
		{
			llwarns << "No facep for index " << face_indx << llendl;
			continue;
		}

		if (isParticle())
		{
			facep->setSize(1,1);
		}
		else
		{
			facep->setSize(4, 6);
		}
		facep->setTEOffset(face_indx);
		facep->setTexture(getTEImage(0));
		const LLCloudPuff &puff = mCloudGroupp->getPuff(face_indx);
		const LLVector3 puff_pos_agent = gAgent.getPosAgentFromGlobal(puff.getPositionGlobal());
		facep->mCenterLocal = puff_pos_agent;
	}
	for ( ; face_indx < drawable->getNumFaces(); face_indx++)
	{
		facep = drawable->getFace(face_indx);
		if (!facep)
		{
			llwarns << "No facep for index " << face_indx << llendl;
			continue;
		}

		facep->setTEOffset(face_indx);
		facep->setSize(0,0);
	}

	drawable->movePartition();

	return TRUE;
}
예제 #8
0
void LLVOPartGroup::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
{		
	const LLVector3& pos_agent = getPositionAgent();
	newMin.load3( (pos_agent - mScale).mV);
	newMax.load3( (pos_agent + mScale).mV);
	LLVector4a pos;
	pos.load3(pos_agent.mV);
	mDrawable->setPositionGroup(pos);
}
예제 #9
0
BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
{
 	if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TREE)))
	{
		return TRUE;
	}
	
	S32 trunk_LOD = sMAX_NUM_TREE_LOD_LEVELS ;
	F32 app_angle = getAppAngle()*LLVOTree::sTreeFactor;

	for (S32 j = 0; j < sMAX_NUM_TREE_LOD_LEVELS; j++)
	{
		if (app_angle > LLVOTree::sLODAngles[j])
		{
			trunk_LOD = j;
			break;
		}
	} 

	if (mReferenceBuffer.isNull())
	{
		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
	}
	else if (trunk_LOD != mTrunkLOD)
	{
		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, FALSE);
	}
	else
	{
		// we're not animating but we may *still* need to
		// regenerate the mesh if we moved, since position
		// and rotation are baked into the mesh.
		// *TODO: I don't know what's so special about trees
		// that they don't get REBUILD_POSITION automatically
		// at a higher level.
		const LLVector3 &this_position = getPositionAgent();
		if (this_position != mLastPosition)
		{
			gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION);
			mLastPosition = this_position;
		}
		else
		{
			const LLQuaternion &this_rotation = getRotation();
			
			if (this_rotation != mLastRotation)
			{
				gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION);
				mLastRotation = this_rotation;
			}
		}
	}

	mTrunkLOD = trunk_LOD;

	return TRUE;
}
예제 #10
0
void LLVOWater::updateSpatialExtents(LLVector3 &newMin, LLVector3& newMax)
{
	LLVector3 pos = getPositionAgent();
	LLVector3 scale = getScale();

	newMin = pos - scale * 0.5f;
	newMax = pos + scale * 0.5f;

	mDrawable->setPositionGroup((newMin + newMax) * 0.5f);
}
예제 #11
0
void LLVOSurfacePatch::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax)
{
	LLVector3 posAgent = getPositionAgent();
	LLVector3 scale = getScale();
	scale.mV[VZ] = llmax(scale.mV[VZ], 1.f);
	newMin.load3( (posAgent-scale*0.5f).mV); // Changing to 2.f makes the culling a -little- better, but still wrong
	newMax.load3( (posAgent+scale*0.5f).mV);
	LLVector4a pos;
	pos.setAdd(newMin,newMax);
	pos.mul(0.5f);
	mDrawable->setPositionGroup(pos);
}
예제 #12
0
void LLVOWater::updateSpatialExtents(LLVector4a &newMin, LLVector4a& newMax)
{
	LLVector4a pos;
	pos.load3(getPositionAgent().mV);
	LLVector4a scale;
	scale.load3(getScale().mV);
	scale.mul(0.5f);

	newMin.setSub(pos, scale);
	newMax.setAdd(pos, scale);
	
	pos.setAdd(newMin,newMax);
	pos.mul(0.5f);

	mDrawable->setPositionGroup(pos);
}
void LLVOPartGroup::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
{		
	const LLVector3& pos_agent = getPositionAgent();

	LLVector4a scale;
	LLVector4a p;

	p.load3(pos_agent.mV);

	scale.splat(mScale.mV[0]+mViewerPartGroupp->getBoxSide()*0.5f);

	newMin.setSub(p, scale);
	newMax.setAdd(p,scale);

	llassert(newMin.isFinite3());
	llassert(newMax.isFinite3());

	llassert(p.isFinite3());
	mDrawable->setPositionGroup(p);
}
예제 #14
0
BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
{
	//VECTORIZE THIS
	//get area of circle around face
	LLVector4a center;
	center.load3(getPositionAgent().mV);
	LLVector4a size;
	size.setSub(mExtents[1], mExtents[0]);
	size.mul(0.5f);

	LLViewerCamera* camera = LLViewerCamera::getInstance();

	F32 size_squared = size.dot3(size).getF32();
	LLVector4a lookAt;
	LLVector4a t;
	t.load3(camera->getOrigin().mV);
	lookAt.setSub(center, t);
	F32 dist = lookAt.getLength3().getF32();
	dist = llmax(dist-size.getLength3().getF32(), 0.f);
	lookAt.normalize3fast() ;	

	//get area of circle around node
	F32 app_angle = atanf((F32) sqrt(size_squared) / dist);
	radius = app_angle*LLDrawable::sCurPixelAngle;
	mPixelArea = radius*radius * 3.14159f;
	LLVector4a x_axis;
	x_axis.load3(camera->getXAxis().mV);
	cos_angle_to_view_dir = lookAt.dot3(x_axis).getF32();

	if(dist < mBoundingSphereRadius) //camera is very close
	{
		cos_angle_to_view_dir = 1.0f;
		mImportanceToCamera = 1.0f;
	}
	else
	{
		mImportanceToCamera = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist);
	}

	return true;
}
예제 #15
0
void LLVOTree::setPixelAreaAndAngle(LLAgent &agent)
{
	LLVector3 center = getPositionAgent();//center of tree.
	LLVector3 viewer_pos_agent = gAgent.getCameraPositionAgent();
	LLVector3 lookAt = center - viewer_pos_agent;
	F32 dist = lookAt.normVec() ;	
	F32 cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ;	
	
	F32 range = dist - getMinScale()/2;
	if (range < F_ALMOST_ZERO)		// range == zero
	{
		range = 0;
		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
}
예제 #16
0
BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
{
	const U16 FRAMES_PER_WIND_UPDATE = 20;				//  How many frames between wind update per tree
	const F32 TREE_WIND_SENSITIVITY = 0.005f;
	const F32 TREE_TRUNK_STIFFNESS = 0.1f;

 	if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TREE)))
	{
		return TRUE;
	}
	
	//it's cheaper to check if wind is enabled first
	if (gLLWindEnabled && gSavedSettings.getBOOL("RenderAnimateTrees"))
	{
		F32 mass_inv; 

		//  For all tree objects, update the trunk bending with the current wind 
		//  Walk sprite list in order away from viewer 
		if (!(mFrameCount % FRAMES_PER_WIND_UPDATE)) 
		{
			//  If needed, Get latest wind for this tree
			mWind = mRegionp->mWind.getVelocity(getPositionRegion());
		}
		mFrameCount++;

		mass_inv = 1.f/(5.f + mDepth*mBranches*0.2f);
		mTrunkVel += (mWind * mass_inv * TREE_WIND_SENSITIVITY);		//  Pull in direction of wind
		mTrunkVel -= (mTrunkBend * mass_inv * TREE_TRUNK_STIFFNESS);		//  Restoring force in direction of trunk 	
		mTrunkBend += mTrunkVel;
		mTrunkVel *= 0.99f;									//  Add damping

		if (mTrunkBend.length() > 1.f)
		{
			mTrunkBend.normalize();
		}

		if (mTrunkVel.length() > 1.f)
		{
			mTrunkVel.normalize();
		}
	}

	S32 trunk_LOD = 0;
	F32 app_angle = getAppAngle()*LLVOTree::sTreeFactor;

	for (S32 j = 0; j < 4; j++)
	{

		if (app_angle > LLVOTree::sLODAngles[j])
		{
			trunk_LOD = j;
			break;
		}
	} 

	if (!gLLWindEnabled || !gSavedSettings.getBOOL("RenderAnimateTrees"))
	{
		if (mReferenceBuffer.isNull())
		{
			gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
		}
		else if (trunk_LOD != mTrunkLOD)
		{
			gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, FALSE);
		}
		else
		{
			// we're not animating but we may *still* need to
			// regenerate the mesh if we moved, since position
			// and rotation are baked into the mesh.
			// *TODO: I don't know what's so special about trees
			// that they don't get REBUILD_POSITION automatically
			// at a higher level.
			const LLVector3 &this_position = getPositionAgent();
			if (this_position != mLastPosition)
			{
				gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION);
				mLastPosition = this_position;
			}
			else
			{
				const LLQuaternion &this_rotation = getRotation();
				
				if (this_rotation != mLastRotation)
				{
					gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION);
					mLastRotation = this_rotation;
				}
			}
		}
	}

	mTrunkLOD = trunk_LOD;

	return TRUE;
}
예제 #17
0
BOOL LLVOWater::updateGeometry(LLDrawable *drawable)
{
	LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WATER);
	LLFace *face;

	if (drawable->getNumFaces() < 1)
	{
		LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER);
		drawable->addFace(poolp, NULL);
	}
	face = drawable->getFace(0);

//	LLVector2 uvs[4];
//	LLVector3 vtx[4];

	LLStrider<LLVector3> verticesp, normalsp;
	LLStrider<LLVector2> texCoordsp;
	LLStrider<U16> indicesp;
	U16 index_offset;

	S32 size = 16;

	S32 num_quads = size*size;	
	face->setSize(4*num_quads, 6*num_quads);

	if (face->mVertexBuffer.isNull())
	{
		face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB);
		face->mVertexBuffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE);
		face->setIndicesIndex(0);
		face->setGeomIndex(0);
	}
	else
	{
		face->mVertexBuffer->resizeBuffer(face->getGeomCount(), face->getIndicesCount());
	}
		
	index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
		
	LLVector3 position_agent;
	position_agent = getPositionAgent();
	face->mCenterAgent = position_agent;
	face->mCenterLocal = position_agent;

	S32 x, y;
	F32 step_x = getScale().mV[0] / size;
	F32 step_y = getScale().mV[1] / size;

	const LLVector3 up(0.f, step_y * 0.5f, 0.f);
	const LLVector3 right(step_x * 0.5f, 0.f, 0.f);
	const LLVector3 normal(0.f, 0.f, 1.f);

	F32 size_inv = 1.f / size;

	for (y = 0; y < size; y++)
	{
		for (x = 0; x < size; x++)
		{
			S32 toffset = index_offset + 4*(y*size + x);
			position_agent = getPositionAgent() - getScale() * 0.5f;
			position_agent.mV[VX] += (x + 0.5f) * step_x;
			position_agent.mV[VY] += (y + 0.5f) * step_y;

			*verticesp++  = position_agent - right + up;
			*verticesp++  = position_agent - right - up;
			*verticesp++  = position_agent + right + up;
			*verticesp++  = position_agent + right - up;

			*texCoordsp++ = LLVector2(x*size_inv, (y+1)*size_inv);
			*texCoordsp++ = LLVector2(x*size_inv, y*size_inv);
			*texCoordsp++ = LLVector2((x+1)*size_inv, (y+1)*size_inv);
			*texCoordsp++ = LLVector2((x+1)*size_inv, y*size_inv);
			
			*normalsp++   = normal;
			*normalsp++   = normal;
			*normalsp++   = normal;
			*normalsp++   = normal;

			*indicesp++ = toffset + 0;
			*indicesp++ = toffset + 1;
			*indicesp++ = toffset + 2;

			*indicesp++ = toffset + 1;
			*indicesp++ = toffset + 3;
			*indicesp++ = toffset + 2;
		}
	}
	
	face->mVertexBuffer->setBuffer(0);

	mDrawable->movePartition();
	LLPipeline::sCompiles++;
	return TRUE;
}
예제 #18
0
BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
{
	LLFastTimer ftm(LLFastTimer::FTM_UPDATE_TREE);

	if (mReferenceBuffer.isNull() || mDrawable->getFace(0)->mVertexBuffer.isNull())
	{
		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);

		face->mCenterAgent = getPositionAgent();
		face->mCenterLocal = face->mCenterAgent;

		for (lod = 0; lod < 4; 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, gSavedSettings.getBOOL("RenderAnimateTrees") ? GL_STATIC_DRAW_ARB : 0);
		mReferenceBuffer->allocateBuffer(max_vertices, max_indices, TRUE);

		LLStrider<LLVector3> vertices;
		LLStrider<LLVector3> normals;
		LLStrider<LLVector2> tex_coords;
		LLStrider<U16> indicesp;

		mReferenceBuffer->getVertexStrider(vertices);
		mReferenceBuffer->getNormalStrider(normals);
		mReferenceBuffer->getTexCoord0Strider(tex_coords);
		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);
		vertex_count++;

		*(normals++) =		LLVector3(SRR3, -SRR3, SRR3);
		*(tex_coords++) =	LLVector2(LEAF_RIGHT, LEAF_TOP);
		*(vertices++) =		LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f);
		vertex_count++;

		*(normals++) =		LLVector3(-SRR3, -SRR3, SRR3);
		*(tex_coords++) =	LLVector2(LEAF_LEFT, LEAF_TOP);
		*(vertices++) =		LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f);
		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);
		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);
		vertex_count++;

		*(normals++) =		LLVector3(SRR3, SRR3, SRR3);
		*(tex_coords++) =	LLVector2(LEAF_RIGHT, LEAF_TOP);
		*(vertices++) =		LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f);
		vertex_count++;

		*(normals++) =		LLVector3(-SRR3, SRR3, SRR3);
		*(tex_coords++) =	LLVector2(LEAF_LEFT, LEAF_TOP);
		*(vertices++) =		LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f);
		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);
		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);
		vertex_count++;

		*(normals++) =		LLVector3(SRR3, SRR3, SRR3);
		*(tex_coords++) =	LLVector2(LEAF_RIGHT, LEAF_TOP);
		*(vertices++) =		LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f);
		vertex_count++;

		*(normals++) =		LLVector3(SRR3, -SRR3, SRR3);
		*(tex_coords++) =	LLVector2(LEAF_LEFT, LEAF_TOP);
		*(vertices++) =		LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f);
		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);
		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);
		vertex_count++;

		*(normals++) =		LLVector3(-SRR3, SRR3, SRR3);
		*(tex_coords++) =	LLVector2(LEAF_RIGHT, LEAF_TOP);
		*(vertices++) =		LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f);
		vertex_count++;

		*(normals++) =		LLVector3(-SRR3, -SRR3, SRR3);
		*(tex_coords++) =	LLVector2(LEAF_LEFT, LEAF_TOP);
		*(vertices++) =		LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f);
		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);
		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 < 4; lod++)
		{
			slices = sLODSlices[lod];
			F32 base_radius = 0.65f;
			F32 top_radius = base_radius * sSpeciesTable[mSpecies]->mTaper;
			//llinfos << "Species " << ((U32) mSpecies) << ", taper = " << sSpeciesTable[mSpecies].mTaper << llendl;
			//llinfos << "Droop " << mDroop << ", branchlength: " << mBranchLength << llendl;
			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;
					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->setBuffer(0);
		llassert(vertex_count == max_vertices);
		llassert(index_count == max_indices);
	}

	if (gLLWindEnabled || gSavedSettings.getBOOL("RenderAnimateTrees"))
	{
		mDrawable->getFace(0)->mVertexBuffer = mReferenceBuffer;
	}
	else
	{
		//generate tree mesh
		updateMesh();
	}
	
	return TRUE;
}
예제 #19
0
BOOL LLVOWater::updateGeometry(LLDrawable *drawable)
{
	LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WATER);
	LLFace *face;

	if (drawable->getNumFaces() < 1)
	{
		LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER);
		drawable->addFace(poolp, NULL);
	}
	face = drawable->getFace(0);

//	LLVector2 uvs[4];
//	LLVector3 vtx[4];

	LLStrider<LLVector3> verticesp, normalsp;
	LLStrider<LLVector2> texCoordsp;
	LLStrider<U16> indicesp;
	U16 index_offset;


	// A quad is 4 vertices and 6 indices (making 2 triangles)
	static const unsigned int vertices_per_quad = 4;
	static const unsigned int indices_per_quad = 6;

	static const LLCachedControl<bool> render_transparent_water("RenderTransparentWater",false);
	const S32 size = (render_transparent_water && !LLGLSLShader::sNoFixedFunction) ? 16 : 1;
	const S32 num_quads = size * size;
	face->setSize(vertices_per_quad * num_quads,
				  indices_per_quad * num_quads);
	
	LLVertexBuffer* buff = face->getVertexBuffer();
	if (!buff)
	{
		buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB);
		buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE);
		face->setIndicesIndex(0);
		face->setGeomIndex(0);
		face->setVertexBuffer(buff);
	}
	else
	{
		buff->resizeBuffer(face->getGeomCount(), face->getIndicesCount());
	}
		
	index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
		
	LLVector3 position_agent;
	position_agent = getPositionAgent();
	face->mCenterAgent = position_agent;
	face->mCenterLocal = position_agent;

	S32 x, y;
	F32 step_x = getScale().mV[0] / size;
	F32 step_y = getScale().mV[1] / size;

	const LLVector3 up(0.f, step_y * 0.5f, 0.f);
	const LLVector3 right(step_x * 0.5f, 0.f, 0.f);
	const LLVector3 normal(0.f, 0.f, 1.f);

	F32 size_inv = 1.f / size;

	for (y = 0; y < size; y++)
	{
		for (x = 0; x < size; x++)
		{
			S32 toffset = index_offset + 4*(y*size + x);
			position_agent = getPositionAgent() - getScale() * 0.5f;
			position_agent.mV[VX] += (x + 0.5f) * step_x;
			position_agent.mV[VY] += (y + 0.5f) * step_y;

			*verticesp++  = position_agent - right + up;
			*verticesp++  = position_agent - right - up;
			*verticesp++  = position_agent + right + up;
			*verticesp++  = position_agent + right - up;

			*texCoordsp++ = LLVector2(x*size_inv, (y+1)*size_inv);
			*texCoordsp++ = LLVector2(x*size_inv, y*size_inv);
			*texCoordsp++ = LLVector2((x+1)*size_inv, (y+1)*size_inv);
			*texCoordsp++ = LLVector2((x+1)*size_inv, y*size_inv);
			
			*normalsp++   = normal;
			*normalsp++   = normal;
			*normalsp++   = normal;
			*normalsp++   = normal;

			*indicesp++ = toffset + 0;
			*indicesp++ = toffset + 1;
			*indicesp++ = toffset + 2;

			*indicesp++ = toffset + 1;
			*indicesp++ = toffset + 3;
			*indicesp++ = toffset + 2;
		}
	}
	
	buff->flush();

	mDrawable->movePartition();
	LLPipeline::sCompiles++;
	return TRUE;
}
예제 #20
0
void LLVOTree::updateMesh()
{
	LLMatrix4 matrix;
	
	// Translate to tree base  HACK - adjustment in Z plants tree underground
	const LLVector3 &pos_agent = getPositionAgent();
	//glTranslatef(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f);
	LLMatrix4 trans_mat;
	trans_mat.setTranslation(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.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);
	facep->mVertexBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
	facep->mVertexBuffer->allocateBuffer(vert_count, index_count, TRUE);
	
	LLStrider<LLVector3> vertices;
	LLStrider<LLVector3> normals;
	LLStrider<LLVector2> tex_coords;
	LLStrider<U16> indices;
	U16 idx_offset = 0;

	facep->mVertexBuffer->getVertexStrider(vertices);
	facep->mVertexBuffer->getNormalStrider(normals);
	facep->mVertexBuffer->getTexCoord0Strider(tex_coords);
	facep->mVertexBuffer->getIndexStrider(indices);

	genBranchPipeline(vertices, normals, tex_coords, indices, idx_offset, scale_mat, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, 1.0, mTwist, droop, mBranches, alpha);
	
	mReferenceBuffer->setBuffer(0);
	facep->mVertexBuffer->setBuffer(0);

}