Пример #1
0
void LLVOTree::updateSpatialExtents(LLVector3& newMin, LLVector3& 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.set(center-size);
	newMax.set(center+size);
	mDrawable->setPositionGroup(center);
}
Пример #2
0
LLVector3 LLModel::getTransformedCenter(const LLMatrix4& mat)
{
	LLVector3 ret;

	if (!mVolumeFaces.empty())
	{
		LLMatrix4a m;
		m.loadu(mat);

		LLVector4a minv,maxv;

		LLVector4a t;
		m.affineTransform(mVolumeFaces[0].mPositions[0], t);
		minv = maxv = t;

		for (S32 i = 0; i < (S32)mVolumeFaces.size(); ++i)
		{
			LLVolumeFace& face = mVolumeFaces[i];

			for (U32 j = 0; j < (U32)face.mNumVertices; ++j)
			{
				m.affineTransform(face.mPositions[j],t);
				update_min_max(minv, maxv, t);
			}
		}

		minv.add(maxv);
		minv.mul(0.5f);

		ret.set(minv.getF32ptr());
	}

	return ret;
}
Пример #3
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();
	}
}
Пример #4
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;
}
Пример #5
0
//-----------------------------------------------------------------------------
// solve()
//-----------------------------------------------------------------------------
void LLJointSolverRP3::solve()
{
//	llinfos << llendl;
//	llinfos << "LLJointSolverRP3::solve()" << llendl;

	//-------------------------------------------------------------------------
	// setup joints in their base rotations
	//-------------------------------------------------------------------------
	mJointA->setRotation( mJointABaseRotation );
	mJointB->setRotation( mJointBBaseRotation );

	//-------------------------------------------------------------------------
	// get joint positions in world space
	//-------------------------------------------------------------------------
	LLVector3 aPos = mJointA->getWorldPosition();
	LLVector3 bPos = mJointB->getWorldPosition();
	LLVector3 cPos = mJointC->getWorldPosition();
	LLVector3 gPos = mJointGoal->getWorldPosition();

//	llinfos << "bPosLocal = " << mJointB->getPosition() << llendl;
//	llinfos << "cPosLocal = " << mJointC->getPosition() << llendl;
//	llinfos << "bRotLocal = " << mJointB->getRotation() << llendl;
//	llinfos << "cRotLocal = " << mJointC->getRotation() << llendl;

//	llinfos << "aPos : " << aPos << llendl;
//	llinfos << "bPos : " << bPos << llendl;
//	llinfos << "cPos : " << cPos << llendl;
//	llinfos << "gPos : " << gPos << llendl;

	//-------------------------------------------------------------------------
	// get the poleVector in world space
	//-------------------------------------------------------------------------
	LLVector3 poleVec = mPoleVector;
	if ( mJointA->getParent() )
	{
		LLVector4a pole_veca;
		pole_veca.load3(mPoleVector.mV);
		mJointA->getParent()->getWorldMatrix().rotate(pole_veca,pole_veca);
		poleVec.set(pole_veca.getF32ptr());
	}

	//-------------------------------------------------------------------------
	// compute the following:
	// vector from A to B
	// vector from B to C
	// vector from A to C
	// vector from A to G (goal)
	//-------------------------------------------------------------------------
	LLVector3 abVec = bPos - aPos;
	LLVector3 bcVec = cPos - bPos;
	LLVector3 acVec = cPos - aPos;
	LLVector3 agVec = gPos - aPos;

//	llinfos << "abVec : " << abVec << llendl;
//	llinfos << "bcVec : " << bcVec << llendl;
//	llinfos << "acVec : " << acVec << llendl;
//	llinfos << "agVec : " << agVec << llendl;

	//-------------------------------------------------------------------------
	// compute needed lengths of those vectors
	//-------------------------------------------------------------------------
	F32 abLen = abVec.magVec();
	F32 bcLen = bcVec.magVec();
	F32 agLen = agVec.magVec();

//	llinfos << "abLen : " << abLen << llendl;
//	llinfos << "bcLen : " << bcLen << llendl;
//	llinfos << "agLen : " << agLen << llendl;

	//-------------------------------------------------------------------------
	// compute component vector of (A->B) orthogonal to (A->C)
	//-------------------------------------------------------------------------
	LLVector3 abacCompOrthoVec = abVec - acVec * ((abVec * acVec)/(acVec * acVec));

//	llinfos << "abacCompOrthoVec : " << abacCompOrthoVec << llendl;

	//-------------------------------------------------------------------------
	// compute the normal of the original ABC plane (and store for later)
	//-------------------------------------------------------------------------
	LLVector3 abcNorm;
	if (!mbUseBAxis)
	{
		if( are_parallel(abVec, bcVec, 0.001f) )
		{
			// the current solution is maxed out, so we use the axis that is
			// orthogonal to both poleVec and A->B
			if ( are_parallel(poleVec, abVec, 0.001f) )
			{
				// ACK! the problem is singular
				if ( are_parallel(poleVec, agVec, 0.001f) )
				{
					// the solutions is also singular
					return;
				}
				else
				{
					abcNorm = poleVec % agVec;
				}
			}
			else
			{
				abcNorm = poleVec % abVec;
			}
		}
		else
		{
			abcNorm = abVec % bcVec;
		}
	}
	else
	{
		abcNorm = mBAxis * mJointB->getWorldRotation();
	}

	//-------------------------------------------------------------------------
	// compute rotation of B
	//-------------------------------------------------------------------------
	// angle between A->B and B->C
	F32 abbcAng = angle_between(abVec, bcVec);

	// vector orthogonal to A->B and B->C
	LLVector3 abbcOrthoVec = abVec % bcVec;
	if (abbcOrthoVec.magVecSquared() < 0.001f)
	{
		abbcOrthoVec = poleVec % abVec;
		abacCompOrthoVec = poleVec;
	}
	abbcOrthoVec.normVec();

	F32 agLenSq = agLen * agLen;

	// angle arm for extension
	F32 cosTheta =	(agLenSq - abLen*abLen - bcLen*bcLen) / (2.0f * abLen * bcLen);
	if (cosTheta > 1.0f)
		cosTheta = 1.0f;
	else if (cosTheta < -1.0f)
		cosTheta = -1.0f;

	F32 theta = acos(cosTheta);

	LLQuaternion bRot(theta - abbcAng, abbcOrthoVec);

//	llinfos << "abbcAng      : " << abbcAng << llendl;
//	llinfos << "abbcOrthoVec : " << abbcOrthoVec << llendl;
//	llinfos << "agLenSq      : " << agLenSq << llendl;
//	llinfos << "cosTheta     : " << cosTheta << llendl;
//	llinfos << "theta        : " << theta << llendl;
//	llinfos << "bRot         : " << bRot << llendl;
//	llinfos << "theta abbcAng theta-abbcAng: " << theta*180.0/F_PI << " " << abbcAng*180.0f/F_PI << " " << (theta - abbcAng)*180.0f/F_PI << llendl;

	//-------------------------------------------------------------------------
	// compute rotation that rotates new A->C to A->G
	//-------------------------------------------------------------------------
	// rotate B->C by bRot
	bcVec = bcVec * bRot;

	// update A->C
	acVec = abVec + bcVec;

	LLQuaternion cgRot;
	cgRot.shortestArc( acVec, agVec );

//	llinfos << "bcVec : " << bcVec << llendl;
//	llinfos << "acVec : " << acVec << llendl;
//	llinfos << "cgRot : " << cgRot << llendl;

	// update A->B and B->C with rotation from C to G
	abVec = abVec * cgRot;
	bcVec = bcVec * cgRot;
	abcNorm = abcNorm * cgRot;
	acVec = abVec + bcVec;

	//-------------------------------------------------------------------------
	// compute the normal of the APG plane
	//-------------------------------------------------------------------------
	if (are_parallel(agVec, poleVec, 0.001f))
	{
		// the solution plane is undefined ==> we're done
		return;
	}
	LLVector3 apgNorm = poleVec % agVec;
	apgNorm.normVec();

	if (!mbUseBAxis)
	{
		//---------------------------------------------------------------------
		// compute the normal of the new ABC plane
		// (only necessary if we're NOT using mBAxis)
		//---------------------------------------------------------------------
		if( are_parallel(abVec, bcVec, 0.001f) )
		{
			// G is either too close or too far away
			// we'll use the old ABCnormal 
		}
		else
		{
			abcNorm = abVec % bcVec;
		}
		abcNorm.normVec();
	}

	//-------------------------------------------------------------------------
	// calcuate plane rotation
	//-------------------------------------------------------------------------
	LLQuaternion pRot;
	if ( are_parallel( abcNorm, apgNorm, 0.001f) )
	{
		if (abcNorm * apgNorm < 0.0f)
		{
			// we must be PI radians off ==> rotate by PI around agVec
			pRot.setQuat(F_PI, agVec);
		}
		else
		{
			// we're done
		}
	}
	else
	{
		pRot.shortestArc( abcNorm, apgNorm );
	}

//	llinfos << "abcNorm = " << abcNorm << llendl;
//	llinfos << "apgNorm = " << apgNorm << llendl;
//	llinfos << "pRot = " << pRot << llendl;

	//-------------------------------------------------------------------------
	// compute twist rotation
	//-------------------------------------------------------------------------
	LLQuaternion twistRot( mTwist, agVec );

//	llinfos	<< "twist    : " << mTwist*180.0/F_PI << llendl;
//	llinfos << "agNormVec: " << agNormVec << llendl;
//	llinfos << "twistRot : " << twistRot << llendl;

	//-------------------------------------------------------------------------
	// compute rotation of A
	//-------------------------------------------------------------------------
	LLQuaternion aRot = cgRot * pRot * twistRot;

	//-------------------------------------------------------------------------
	// apply the rotations
	//-------------------------------------------------------------------------
	mJointB->setWorldRotation( mJointB->getWorldRotation() * bRot );
	mJointA->setWorldRotation( mJointA->getWorldRotation() * aRot );
}
// <FS:Ansariel> Extended TP history
void LLTeleportHistoryFlatItem::setLocalPos(const LLVector3& local_pos)
{
	mLocalPos.set(local_pos);
}
Пример #7
0
void LLModel::Decomposition::fromLLSD(LLSD& decomp)
{
	if (decomp.has("HullList") && decomp.has("Positions"))
	{
		// updated for const-correctness. gcc is picky about this type of thing - Nyx
		const LLSD::Binary& hulls = decomp["HullList"].asBinary();
		const LLSD::Binary& position = decomp["Positions"].asBinary();

		U16* p = (U16*) &position[0];

		mHull.resize(hulls.size());

		LLVector3 min;
		LLVector3 max;
		LLVector3 range;

		if (decomp.has("Min"))
		{
			min.setValue(decomp["Min"]);
			max.setValue(decomp["Max"]);
		}
		else
		{
			min.set(-0.5f, -0.5f, -0.5f);
			max.set(0.5f, 0.5f, 0.5f);
		}

		range = max-min;

		for (U32 i = 0; i < hulls.size(); ++i)
		{
			U16 count = (hulls[i] == 0) ? 256 : hulls[i];
			
			std::set<U64> valid;

			//must have at least 4 points
			//llassert(count > 3);

			for (U32 j = 0; j < count; ++j)
			{
				U64 test = (U64) p[0] | ((U64) p[1] << 16) | ((U64) p[2] << 32);
				//point must be unique
				//llassert(valid.find(test) == valid.end());
				valid.insert(test);

				mHull[i].push_back(LLVector3(
					(F32) p[0]/65535.f*range.mV[0]+min.mV[0],
					(F32) p[1]/65535.f*range.mV[1]+min.mV[1],
					(F32) p[2]/65535.f*range.mV[2]+min.mV[2]));
				p += 3;


			}

			//each hull must contain at least 4 unique points
			//llassert(valid.size() > 3);
		}
	}

	if (decomp.has("BoundingVerts"))
	{
		const LLSD::Binary& position = decomp["BoundingVerts"].asBinary();

		U16* p = (U16*) &position[0];

		LLVector3 min;
		LLVector3 max;
		LLVector3 range;

		if (decomp.has("Min"))
		{
			min.setValue(decomp["Min"]);
			max.setValue(decomp["Max"]);
		}
		else
		{
			min.set(-0.5f, -0.5f, -0.5f);
			max.set(0.5f, 0.5f, 0.5f);
		}

		range = max-min;

		size_t count = position.size()/6;
		
		for (U32 j = 0; j < count; ++j)
		{
			mBaseHull.push_back(LLVector3(
				(F32) p[0]/65535.f*range.mV[0]+min.mV[0],
				(F32) p[1]/65535.f*range.mV[1]+min.mV[1],
				(F32) p[2]/65535.f*range.mV[2]+min.mV[2]));
			p += 3;
		}		 
	}
	else
	{
		//empty base hull mesh to indicate decomposition has been loaded
		//but contains no base hull
		mBaseHullMesh.clear();
	}
}
Пример #8
0
BOOL LLFace::getGeometryVolume(const LLVolume& volume,
							   const S32 &f,
								const LLMatrix4& mat_vert_in, const LLMatrix3& mat_norm_in,
								const U16 &index_offset,
								bool force_rebuild)
{
	llassert(verify());
	const LLVolumeFace &vf = volume.getVolumeFace(f);
	S32 num_vertices = (S32)vf.mNumVertices;
	S32 num_indices = (S32) vf.mNumIndices;
	
	if (mVertexBuffer.notNull())
	{
		if (num_indices + (S32) mIndicesIndex > mVertexBuffer->getNumIndices())
		{
			llwarns	<< "Index buffer overflow!" << llendl;
			llwarns << "Indices Count: " << mIndicesCount
					<< " VF Num Indices: " << num_indices
					<< " Indices Index: " << mIndicesIndex
					<< " VB Num Indices: " << mVertexBuffer->getNumIndices() << llendl;
			llwarns	<< "Last Indices Count: " << mLastIndicesCount
					<< " Last Indices Index: " << mLastIndicesIndex
					<< " Face Index: " << f
					<< " Pool Type: " << mPoolType << llendl;
			return FALSE;
		}

		if (num_vertices + mGeomIndex > mVertexBuffer->getNumVerts())
		{
			llwarns << "Vertex buffer overflow!" << llendl;
			return FALSE;
		}
	}

	LLStrider<LLVector3> vertices;
	LLStrider<LLVector2> tex_coords;
	LLStrider<LLVector2> tex_coords2;
	LLStrider<LLVector3> normals;
	LLStrider<LLColor4U> colors;
	LLStrider<LLVector3> binormals;
	LLStrider<U16> indicesp;
#if MESH_ENABLED
	LLStrider<LLVector4> weights;
#endif //MESH_ENABLED

	BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME);
	
	BOOL global_volume = mDrawablep->getVOVolume()->isVolumeGlobal();
	LLVector3 scale;
	if (global_volume)
	{
		scale.setVec(1,1,1);
	}
	else
	{
		scale = mVObjp->getScale();
	}
	
	bool rebuild_pos = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_POSITION);
	bool rebuild_color = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_COLOR);
	bool rebuild_tcoord = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_TCOORD);
	bool rebuild_normal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL);
	bool rebuild_binormal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_BINORMAL);
#if MESH_ENABLED
	bool rebuild_weights = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_WEIGHT4);
#endif //MESH_ENABLED

	const LLTextureEntry *tep = mVObjp->getTE(f);
	if (!tep) rebuild_color = FALSE;	// can't get color when tep is NULL
	U8  bump_code = tep ? tep->getBumpmap() : 0;


	
	BOOL is_static = mDrawablep->isStatic();
	BOOL is_global = is_static;

	LLVector3 center_sum(0.f, 0.f, 0.f);
	
	if (is_global)
	{
		setState(GLOBAL);
	}
	else
	{
		clearState(GLOBAL);
	}

	LLColor4U color = (tep ? LLColor4U(tep->getColor()) : LLColor4U::white);

	if (rebuild_color)	// FALSE if tep == NULL
	{
		if (tep)
		{
			GLfloat alpha[4] =
			{
				0.00f,
				0.25f,
				0.5f,
				0.75f
			};
			
			if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || (LLPipeline::sRenderBump && tep->getShiny())))
			{
				color.mV[3] = U8 (alpha[tep->getShiny()] * 255);
			}
		}
	}

    // INDICES
	if (full_rebuild)
	{
		mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex);
		for (U32 i = 0; i < (U32) num_indices; i++)
		{
			indicesp[i] = vf.mIndices[i] + index_offset;
		}

		//mVertexBuffer->setBuffer(0);
	}
	
	LLMatrix4a mat_normal;
	mat_normal.loadu(mat_norm_in);
	
	//if it's not fullbright and has no normals, bake sunlight based on face normal
	//bool bake_sunlight = !getTextureEntry()->getFullbright() &&
	//  !mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL);

	F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0;

	if (rebuild_tcoord)
	{
		bool do_xform;
			
		if (tep)
		{
			r  = tep->getRotation();
			os = tep->mOffsetS;
			ot = tep->mOffsetT;
			ms = tep->mScaleS;
			mt = tep->mScaleT;
			cos_ang = cos(r);
			sin_ang = sin(r);

			if (cos_ang != 1.f || 
				sin_ang != 0.f ||
				os != 0.f ||
				ot != 0.f ||
				ms != 1.f ||
				mt != 1.f)
			{
				do_xform = true;
			}
			else
			{
				do_xform = false;
			}	
		}
		else
		{
			do_xform = false;
		}
						
		//bump setup
		LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f );
		LLVector4a bump_s_primary_light_ray(0.f, 0.f, 0.f);
		LLVector4a bump_t_primary_light_ray(0.f, 0.f, 0.f);

		LLQuaternion bump_quat;
		if (mDrawablep->isActive())
		{
			bump_quat = LLQuaternion(mDrawablep->getRenderMatrix());
		}
		
		if (bump_code)
		{
			mVObjp->getVolume()->genBinormals(f);
			F32 offset_multiple; 
			switch( bump_code )
			{
				case BE_NO_BUMP:
				offset_multiple = 0.f;
				break;
				case BE_BRIGHTNESS:
				case BE_DARKNESS:
				if( mTexture.notNull() && mTexture->hasGLTexture())
				{
					// Offset by approximately one texel
					S32 cur_discard = mTexture->getDiscardLevel();
					S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() );
					max_size <<= cur_discard;
					const F32 ARTIFICIAL_OFFSET = 2.f;
					offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size;
				}
				else
				{
					offset_multiple = 1.f/256;
				}
				break;

				default:  // Standard bumpmap textures.  Assumed to be 256x256
				offset_multiple = 1.f / 256;
				break;
			}

			F32 s_scale = 1.f;
			F32 t_scale = 1.f;
			if( tep )
			{
				tep->getScale( &s_scale, &t_scale );
			}
			// Use the nudged south when coming from above sun angle, such
			// that emboss mapping always shows up on the upward faces of cubes when 
			// it's noon (since a lot of builders build with the sun forced to noon).
			LLVector3   sun_ray  = gSky.mVOSkyp->mBumpSunDir;
			LLVector3   moon_ray = gSky.getMoonDirection();
			LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray;

			bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV);
			bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV);
		}

		U8 texgen = getTextureEntry()->getTexGen();
		if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT)
		{ //planar texgen needs binormals
			mVObjp->getVolume()->genBinormals(f);
		}

		U8 tex_mode = 0;
	
		if (isState(TEXTURE_ANIM))
		{
			LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp;	
			tex_mode = vobj->mTexAnimMode;

			if (!tex_mode)
			{
				clearState(TEXTURE_ANIM);
			}
			else
			{
				os = ot = 0.f;
				r = 0.f;
				cos_ang = 1.f;
				sin_ang = 0.f;
				ms = mt = 1.f;

				do_xform = false;
			}

			if (getVirtualSize() >= MIN_TEX_ANIM_SIZE)
			{ //don't override texture transform during tc bake
				tex_mode = 0;
			}
		}
	
		LLVector4a scalea;
		scalea.load3(scale.mV);

		bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1);
		bool do_tex_mat = tex_mode && mTextureMatrix;

		if (!do_bump)
		{ //not in atlas or not bump mapped, might be able to do a cheap update
			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex);

			if (texgen != LLTextureEntry::TEX_GEN_PLANAR)
			{
				if (!do_tex_mat)
				{
					if (!do_xform)
					{
						tex_coords.assignArray((U8*) vf.mTexCoords, sizeof(vf.mTexCoords[0]), num_vertices);
					}
					else
					{
						for (S32 i = 0; i < num_vertices; i++)
						{	
							LLVector2 tc(vf.mTexCoords[i]);
							xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
							*tex_coords++ = tc;	
						}
					}
				}
				else
				{ //do tex mat, no texgen, no atlas, no bump
					for (S32 i = 0; i < num_vertices; i++)
					{	
						LLVector2 tc(vf.mTexCoords[i]);
						//LLVector4a& norm = vf.mNormals[i];
						//LLVector4a& center = *(vf.mCenter);

						LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
						tmp = tmp * *mTextureMatrix;
						tc.mV[0] = tmp.mV[0];
						tc.mV[1] = tmp.mV[1];
						*tex_coords++ = tc;	
					}
				}
			}
			else
			{ //no bump, no atlas, tex gen planar
				if (do_tex_mat)
				{
					for (S32 i = 0; i < num_vertices; i++)
					{	
						LLVector2 tc(vf.mTexCoords[i]);
						LLVector4a& norm = vf.mNormals[i];
						LLVector4a& center = *(vf.mCenter);
						LLVector4a vec = vf.mPositions[i];	
						vec.mul(scalea);
						planarProjection(tc, norm, center, vec);
						
						LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
						tmp = tmp * *mTextureMatrix;
						tc.mV[0] = tmp.mV[0];
						tc.mV[1] = tmp.mV[1];
				
						*tex_coords++ = tc;	
					}
				}
				else
				{
					for (S32 i = 0; i < num_vertices; i++)
					{	
						LLVector2 tc(vf.mTexCoords[i]);
						LLVector4a& norm = vf.mNormals[i];
						LLVector4a& center = *(vf.mCenter);
						LLVector4a vec = vf.mPositions[i];	
						vec.mul(scalea);
						planarProjection(tc, norm, center, vec);
						
						xform(tc, cos_ang, sin_ang, os, ot, ms, mt);

						*tex_coords++ = tc;	
					}
				}
			}

			//mVertexBuffer->setBuffer(0);
		}
		else
		{ //either bump mapped or in atlas, just do the whole expensive loop
			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex);

			std::vector<LLVector2> bump_tc;
		
			for (S32 i = 0; i < num_vertices; i++)
			{	
				LLVector2 tc(vf.mTexCoords[i]);
			
				LLVector4a& norm = vf.mNormals[i];
				
				LLVector4a& center = *(vf.mCenter);
		   
				if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
				{
					LLVector4a vec = vf.mPositions[i];
				
					vec.mul(scalea);

					switch (texgen)
					{
						case LLTextureEntry::TEX_GEN_PLANAR:
							planarProjection(tc, norm, center, vec);
							break;
						case LLTextureEntry::TEX_GEN_SPHERICAL:
							sphericalProjection(tc, norm, center, vec);
							break;
						case LLTextureEntry::TEX_GEN_CYLINDRICAL:
							cylindricalProjection(tc, norm, center, vec);
							break;
						default:
							break;
					}		
				}

				if (tex_mode && mTextureMatrix)
				{
					LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
					tmp = tmp * *mTextureMatrix;
					tc.mV[0] = tmp.mV[0];
					tc.mV[1] = tmp.mV[1];
				}
				else
				{
					xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
				}


				*tex_coords++ = tc;
				if (do_bump)
				{
					bump_tc.push_back(tc);
				}
			}

			//mVertexBuffer->setBuffer(0);


			if (do_bump)
			{
				mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex);
		
				for (S32 i = 0; i < num_vertices; i++)
				{
					LLVector4a tangent;
					tangent.setCross3(vf.mBinormals[i], vf.mNormals[i]);

					LLMatrix4a tangent_to_object;
					tangent_to_object.setRows(tangent, vf.mBinormals[i], vf.mNormals[i]);
					LLVector4a t;
					tangent_to_object.rotate(binormal_dir, t);
					LLVector4a binormal;
					mat_normal.rotate(t, binormal);
						
					//VECTORIZE THIS
					if (mDrawablep->isActive())
					{
						LLVector3 t;
						t.set(binormal.getF32ptr());
						t *= bump_quat;
						binormal.load3(t.mV);
					}

					binormal.normalize3fast();
					LLVector2 tc = bump_tc[i];
					tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() );
					
					*tex_coords2++ = tc;
				}

				//mVertexBuffer->setBuffer(0);
			}
		}
	}

	if (rebuild_pos)
	{
		llassert(num_vertices > 0);
		mVertexBuffer->getVertexStrider(vertices, mGeomIndex);
		LLMatrix4a mat_vert;
		mat_vert.loadu(mat_vert_in);
		
		LLVector4a* src = vf.mPositions;
		LLVector4a position;
		for (S32 i = 0; i < num_vertices; i++)
		{
			mat_vert.affineTransform(src[i], position);
			vertices[i].set(position.getF32ptr());
		}
			
			
		//mVertexBuffer->setBuffer(0);
	}
		
	if (rebuild_normal)
	{
		mVertexBuffer->getNormalStrider(normals, mGeomIndex);
		for (S32 i = 0; i < num_vertices; i++)
		{	
			LLVector4a normal;
			mat_normal.rotate(vf.mNormals[i], normal);
			normal.normalize3fast();
			normals[i].set(normal.getF32ptr());
		}

		//mVertexBuffer->setBuffer(0);
	}
		
	if (rebuild_binormal)
	{
		mVertexBuffer->getBinormalStrider(binormals, mGeomIndex);
		for (S32 i = 0; i < num_vertices; i++)
		{	
			LLVector4a binormal;
			mat_normal.rotate(vf.mBinormals[i], binormal);
			binormal.normalize3fast();
			binormals[i].set(binormal.getF32ptr());
		}

		//mVertexBuffer->setBuffer(0);
	}
	
#if MESH_ENABLED
	if (rebuild_weights && vf.mWeights)
	{
		mVertexBuffer->getWeight4Strider(weights, mGeomIndex);
		weights.assignArray((U8*) vf.mWeights, sizeof(vf.mWeights[0]), num_vertices);
		//mVertexBuffer->setBuffer(0);
	}
#endif //MESH_ENABLED

	if (rebuild_color)
	{
		mVertexBuffer->getColorStrider(colors, mGeomIndex);
		for (S32 i = 0; i < num_vertices; i++)
		{
			colors[i] = color;	
		}

		//mVertexBuffer->setBuffer(0);
	}

	if (rebuild_tcoord)
	{
		mTexExtents[0].setVec(0,0);
		mTexExtents[1].setVec(1,1);
		xform(mTexExtents[0], cos_ang, sin_ang, os, ot, ms, mt);
		xform(mTexExtents[1], cos_ang, sin_ang, os, ot, ms, mt);
		
		F32 es = vf.mTexCoordExtents[1].mV[0] - vf.mTexCoordExtents[0].mV[0] ;
		F32 et = vf.mTexCoordExtents[1].mV[1] - vf.mTexCoordExtents[0].mV[1] ;
		mTexExtents[0][0] *= es ;
		mTexExtents[1][0] *= es ;
		mTexExtents[0][1] *= et ;
		mTexExtents[1][1] *= et ;
	}

	mLastVertexBuffer = mVertexBuffer;
	mLastGeomCount = mGeomCount;
	mLastGeomIndex = mGeomIndex;
	mLastIndicesCount = mIndicesCount;
	mLastIndicesIndex = mIndicesIndex;

	return TRUE;
}