Example #1
0
bool less_than_max_mag(const LLVector4a& vec)
{
	LLVector4a MAX_MAG;
	MAX_MAG.splat(1024.f*1024.f);

	LLVector4a val;
	val.setAbs(vec);

	S32 lt = val.lessThan(MAX_MAG).getGatheredBits() & 0x7;
	
	return lt == 0x7;
}
//-----------------------------------------------------------------------------
// loadBinary()
//-----------------------------------------------------------------------------
BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh)
{
	S32 numVertices;
	S32 numRead;

	numRead = fread(&numVertices, sizeof(S32), 1, fp);
	llendianswizzle(&numVertices, sizeof(S32), 1);
	if (numRead != 1)
	{
		LL_WARNS() << "Can't read number of morph target vertices" << LL_ENDL;
		return FALSE;
	}

	//-------------------------------------------------------------------------
	// free any existing data
	//-------------------------------------------------------------------------
	freeData();

	//-------------------------------------------------------------------------
	// allocate vertices
	//-------------------------------------------------------------------------
	
	U32 size = sizeof(LLVector4a)*numVertices;
	
	mCoords = static_cast<LLVector4a*>(ll_aligned_malloc_16(size));
	mNormals = static_cast<LLVector4a*>(ll_aligned_malloc_16(size));
	mBinormals = static_cast<LLVector4a*>(ll_aligned_malloc_16(size));
	
	mTexCoords = new LLVector2[numVertices];
	// Actually, we are allocating more space than we need for the skiplist
	mVertexIndices = new U32[numVertices];
	mNumIndices = 0;
	mTotalDistortion = 0.f;
	mMaxDistortion = 0.f;
	mAvgDistortion.clear();
	mMesh = mesh;

	//-------------------------------------------------------------------------
	// read vertices
	//-------------------------------------------------------------------------
	for(S32 v = 0; v < numVertices; v++)
	{
		numRead = fread(&mVertexIndices[v], sizeof(U32), 1, fp);
		llendianswizzle(&mVertexIndices[v], sizeof(U32), 1);
		if (numRead != 1)
		{
			LL_WARNS() << "Can't read morph target vertex number" << LL_ENDL;
			return FALSE;
		}

		if (mVertexIndices[v] > 10000)
		{
			LL_ERRS() << "Bad morph index: " << mVertexIndices[v] << LL_ENDL;
		}


		numRead = fread(&mCoords[v], sizeof(F32), 3, fp);
		llendianswizzle(&mCoords[v], sizeof(F32), 3);
		if (numRead != 3)
		{
			LL_WARNS() << "Can't read morph target vertex coordinates" << LL_ENDL;
			return FALSE;
		}

		F32 magnitude = mCoords[v].getLength3().getF32();
		
		mTotalDistortion += magnitude;
		LLVector4a t;
		t.setAbs(mCoords[v]);
		mAvgDistortion.add(t);
		
		if (magnitude > mMaxDistortion)
		{
			mMaxDistortion = magnitude;
		}

		numRead = fread(&mNormals[v], sizeof(F32), 3, fp);
		llendianswizzle(&mNormals[v], sizeof(F32), 3);
		if (numRead != 3)
		{
			LL_WARNS() << "Can't read morph target normal" << LL_ENDL;
			return FALSE;
		}

		numRead = fread(&mBinormals[v], sizeof(F32), 3, fp);
		llendianswizzle(&mBinormals[v], sizeof(F32), 3);
		if (numRead != 3)
		{
			LL_WARNS() << "Can't read morph target binormal" << LL_ENDL;
			return FALSE;
		}


		numRead = fread(&mTexCoords[v].mV, sizeof(F32), 2, fp);
		llendianswizzle(&mTexCoords[v].mV, sizeof(F32), 2);
		if (numRead != 2)
		{
			LL_WARNS() << "Can't read morph target uv" << LL_ENDL;
			return FALSE;
		}

		mNumIndices++;
	}

	mAvgDistortion.mul(1.f/(F32)mNumIndices);
	mAvgDistortion.normalize3fast();

	return TRUE;
}
void LLSpatialBridge::updateSpatialExtents()
{
	LLSpatialGroup* root = (LLSpatialGroup*) mOctree->getListener(0);
	
	{
		LLFastTimer ftm(FTM_CULL_REBOUND);
		root->rebound();
	}
	
	LLVector4a offset;
	LLVector4a size = root->mBounds[1];
		
	//VECTORIZE THIS
	LLMatrix4a mat;
	mat.loadu(mDrawable->getXform()->getWorldMatrix());

	LLVector4a t;
	t.splat(0.f);

	LLVector4a center;
	mat.affineTransform(t, center);
	
	mat.rotate(root->mBounds[0], offset);
	center.add(offset);
	
	LLVector4a v[4];

	//get 4 corners of bounding box
	mat.rotate(size,v[0]);

	LLVector4a scale;
	
	scale.set(-1.f, -1.f, 1.f);
	scale.mul(size);
	mat.rotate(scale, v[1]);
	
	scale.set(1.f, -1.f, -1.f);
	scale.mul(size);
	mat.rotate(scale, v[2]);
	
	scale.set(-1.f, 1.f, -1.f);
	scale.mul(size);
	mat.rotate(scale, v[3]);

	
	LLVector4a& newMin = mExtents[0];
	LLVector4a& newMax = mExtents[1];
	
	newMin = newMax = center;
	
	for (U32 i = 0; i < 4; i++)
	{
		LLVector4a delta;
		delta.setAbs(v[i]);
		LLVector4a min;
		min.setSub(center, delta);
		LLVector4a max;
		max.setAdd(center, delta);

		newMin.setMin(newMin, min);
		newMax.setMax(newMax, max);
	}
	
	LLVector4a diagonal;
	diagonal.setSub(newMax, newMin);
	mRadius = diagonal.getLength3().getF32() * 0.5f;
	
	mPositionGroup.setAdd(newMin,newMax);
	mPositionGroup.mul(0.5f);
	updateBinRadius();
}
//-----------------------------------------------------------------------------
// setMorphFromMesh()
//-----------------------------------------------------------------------------
BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph)
{
	if (!morph)
		return FALSE;

	LLVector4a *morph_coords     = morph->getWritableCoords();
	LLVector4a *morph_normals    = morph->getWritableNormals();
	LLVector4a *morph_binormals  = morph->getWritableBinormals();
	LLVector2 *morph_tex_coords = morph->getWritableTexCoords();

	// We now have the morph loaded as a mesh.  We have to subtract the
	// base mesh to get the delta morph.

	LLPolyMesh delta(mMesh, NULL);
	U32 nverts = delta.getNumVertices();

	LLVector4a *delta_coords     = delta.getWritableCoords();
	LLVector4a *delta_normals    = delta.getWritableNormals();
	LLVector4a *delta_binormals  = delta.getWritableBinormals();
	LLVector2 *delta_tex_coords = delta.getWritableTexCoords();

	U32 num_significant = 0;
	U32 vert_index;
	for( vert_index = 0; vert_index < nverts; vert_index++)
	{
		delta_coords[vert_index].setSub(	morph_coords[vert_index], delta_coords[vert_index]);
		delta_normals[vert_index].setSub(	morph_normals[vert_index], delta_normals[vert_index]);
		delta_binormals[vert_index].setSub(	morph_binormals[vert_index], delta_binormals[vert_index]);
		delta_tex_coords[vert_index] =		morph_tex_coords[vert_index] - delta_tex_coords[vert_index];

		// For the normals and binormals, we really want the deltas
		// to be perpendicular to the mesh (bi)normals in the plane
		// that contains both the mesh and morph (bi)normals, such
		// that the morph (bi)normals form the hypotenuses of right
		// triangles. Right now, we just compute the difference vector.

		if (delta_coords[vert_index].getLength3().getF32()		> SIGNIFICANT_DELTA
		||  delta_normals[vert_index].getLength3().getF32()		> SIGNIFICANT_DELTA
		||  delta_binormals[vert_index].getLength3().getF32()	> SIGNIFICANT_DELTA
		||  delta_tex_coords[vert_index].length()				> SIGNIFICANT_DELTA)
		{
			num_significant++;
		}
	}

	//-------------------------------------------------------------------------
	// compute new morph
	//-------------------------------------------------------------------------

	// If the morph matches the base mesh, we store one vertex to prevent
	// zero length vectors.

	U32 nindices = num_significant;
	if (num_significant == 0)
		nindices = 1;

	LLVector4a* new_coords     = new LLVector4a[nindices];
	LLVector4a* new_normals    = new LLVector4a[nindices];
	LLVector4a* new_binormals  = new LLVector4a[nindices];
	LLVector2* new_tex_coords = new LLVector2[nindices];
	U32* new_vertex_indices   = new U32[nindices];

    // We'll set the distortion directly
	mTotalDistortion = 0.f;
	mMaxDistortion   = 0.f;
	mAvgDistortion.clear();

	U32 morph_index = 0;
	for( vert_index = 0; vert_index < nverts; vert_index++)
	{
		if (delta_coords[vert_index].getLength3().getF32()		> SIGNIFICANT_DELTA
		||  delta_normals[vert_index].getLength3().getF32()		> SIGNIFICANT_DELTA
		||  delta_binormals[vert_index].getLength3().getF32()	> SIGNIFICANT_DELTA
		||  delta_tex_coords[vert_index].length()				> SIGNIFICANT_DELTA
		||  num_significant == 0)
		{
			new_vertex_indices[morph_index] = vert_index;

			new_coords[morph_index]     = delta_coords[vert_index];
			new_normals[morph_index]    = delta_normals[vert_index];
			new_binormals[morph_index]  = delta_binormals[vert_index];
			new_tex_coords[morph_index] = delta_tex_coords[vert_index];

			F32 magnitude = new_coords[morph_index].getLength3().getF32();

			mTotalDistortion += magnitude;
			LLVector4a t;
			t.setAbs(new_coords[morph_index]);
			mAvgDistortion.add(t);

			if (magnitude > mMaxDistortion)
			{
				mMaxDistortion = magnitude;
			}

			morph_index++;
			num_significant = 1;
		}
	}

	mAvgDistortion.mul(1.f/(F32)nindices);
	mAvgDistortion.normalize3();

	//-------------------------------------------------------------------------
	// compute the change in the morph
	//-------------------------------------------------------------------------

	// Because meshes are set by continually updating morph weights
	// there is no easy way to reapply the morphs, so we just compute
	// the change in this morph and apply that appropriately weighted.

	for( morph_index = 0; morph_index < mNumIndices; morph_index++)
	{
		vert_index = mVertexIndices[morph_index];

		delta_coords[vert_index].sub(	mCoords[morph_index]);
		delta_normals[vert_index].sub(	mNormals[morph_index]);
		delta_binormals[vert_index].sub(mBinormals[morph_index]);
		delta_tex_coords[vert_index] -= mTexCoords[morph_index];
	}

	//-------------------------------------------------------------------------
	// Update all avatars
	//-------------------------------------------------------------------------

	std::vector< LLCharacter* >::iterator avatar_it;
	for(avatar_it = LLCharacter::sInstances.begin(); avatar_it != LLCharacter::sInstances.end(); ++avatar_it)
	{
		LLVOAvatar* avatarp = (LLVOAvatar*)*avatar_it;

		LLPolyMorphTarget* param = (LLPolyMorphTarget*) avatarp->getVisualParam(mName.c_str());
		if (!param)
		{
			continue;
		}

		F32 weight = param->getLastWeight();
		if (weight == 0.0f)
		{
			continue;
		}

		LLPolyMesh* mesh = avatarp->getMesh(mMesh);
		if (!mesh)
		{
			continue;
		}

		// If we have a vertex mask, just remove it.  It will be recreated.
		/*if (param->undoMask(TRUE))
		{
			continue;
		}*/

		LLVector4a *mesh_coords           = mesh->getWritableCoords();
		LLVector4a *mesh_normals          = mesh->getWritableNormals();
		LLVector4a *mesh_binormals        = mesh->getWritableBinormals();
		LLVector2 *mesh_tex_coords        = mesh->getWritableTexCoords();
		LLVector4a *mesh_scaled_normals   = mesh->getScaledNormals();
		LLVector4a *mesh_scaled_binormals = mesh->getScaledBinormals();

		for( vert_index = 0; vert_index < nverts; vert_index++)
		{
			delta_coords[vert_index].mul(weight);
			mesh_coords[vert_index].add(delta_coords[vert_index]);

			mesh_tex_coords[vert_index]       += delta_tex_coords[vert_index] * weight;

			delta_normals[vert_index].mul(weight * NORMAL_SOFTEN_FACTOR);
			mesh_scaled_normals[vert_index].add(delta_normals[vert_index]);
			
			LLVector4a normalized_normal       = mesh_scaled_normals[vert_index];
			normalized_normal.normalize3();
			mesh_normals[vert_index]           = normalized_normal;

			delta_binormals[vert_index].mul(weight * NORMAL_SOFTEN_FACTOR);
			mesh_scaled_binormals[vert_index].add(delta_binormals[vert_index]);

			LLVector4a tangent;
			tangent.setCross3(mesh_scaled_binormals[vert_index], normalized_normal);
			LLVector4a normalized_binormal;
			normalized_binormal.setCross3(normalized_normal, tangent);
			normalized_binormal.normalize3();
			mesh_binormals[vert_index]         = normalized_binormal;
		}

		avatarp->dirtyMesh();
	}

	//-------------------------------------------------------------------------
	// reallocate vertices
	//-------------------------------------------------------------------------
	delete [] mVertexIndices;
	delete [] mCoords;
	delete [] mNormals;
	delete [] mBinormals;
	delete [] mTexCoords;

	mVertexIndices = new_vertex_indices;
	mCoords        = new_coords;
	mNormals       = new_normals;
	mBinormals     = new_binormals;
	mTexCoords     = new_tex_coords;
	mNumIndices    = nindices;

	return TRUE;
}
Example #5
0
BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
								const LLMatrix4& mat_vert_in, const LLMatrix3& mat_normal_in, BOOL global_volume)
{
	LLMemType mt1(LLMemType::MTYPE_DRAWABLE);

	//get bounding box
	if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION
#if MESH_ENABLED
		| LLDrawable::REBUILD_RIGGED
#endif //MESH_ENABLED
		))
	{
		//VECTORIZE THIS
		LLMatrix4a mat_vert;
		mat_vert.loadu(mat_vert_in);

		LLMatrix4a mat_normal;
		mat_normal.loadu(mat_normal_in);

		//if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME))
		//{ //vertex buffer no longer valid
		//	mVertexBuffer = NULL;
		//	mLastVertexBuffer = NULL;
		//}

		//VECTORIZE THIS
		LLVector4a min,max;
	
		if (f >= volume.getNumVolumeFaces())
		{
			llwarns << "Generating bounding box for invalid face index!" << llendl;
			f = 0;
		}

		const LLVolumeFace &face = volume.getVolumeFace(f);
		min = face.mExtents[0];
		max = face.mExtents[1];
		
		llassert(less_than_max_mag(min));
		llassert(less_than_max_mag(max));

		//min, max are in volume space, convert to drawable render space
		LLVector4a center;
		LLVector4a t;
		t.setAdd(min, max);
		t.mul(0.5f);
		mat_vert.affineTransform(t, center);
		LLVector4a size;
		size.setSub(max, min);
		size.mul(0.5f);

		llassert(less_than_max_mag(min));
		llassert(less_than_max_mag(max));

		if (!global_volume)
		{
			//VECTORIZE THIS
			LLVector4a scale;
			scale.load3(mDrawablep->getVObj()->getScale().mV);
			size.mul(scale);
		}

		mat_normal.mMatrix[0].normalize3fast();
		mat_normal.mMatrix[1].normalize3fast();
		mat_normal.mMatrix[2].normalize3fast();
		
		LLVector4a v[4];

		//get 4 corners of bounding box
		mat_normal.rotate(size,v[0]);

		//VECTORIZE THIS
		LLVector4a scale;
		
		scale.set(-1.f, -1.f, 1.f);
		scale.mul(size);
		mat_normal.rotate(scale, v[1]);
		
		scale.set(1.f, -1.f, -1.f);
		scale.mul(size);
		mat_normal.rotate(scale, v[2]);
		
		scale.set(-1.f, 1.f, -1.f);
		scale.mul(size);
		mat_normal.rotate(scale, v[3]);

		LLVector4a& newMin = mExtents[0];
		LLVector4a& newMax = mExtents[1];
		
		newMin = newMax = center;
		
		llassert(less_than_max_mag(center));
		
		for (U32 i = 0; i < 4; i++)
		{
			LLVector4a delta;
			delta.setAbs(v[i]);
			LLVector4a min;
			min.setSub(center, delta);
			LLVector4a max;
			max.setAdd(center, delta);

			newMin.setMin(newMin,min);
			newMax.setMax(newMax,max);

			llassert(less_than_max_mag(newMin));
			llassert(less_than_max_mag(newMax));
		}

		if (!mDrawablep->isActive())
		{
			LLVector4a offset;
			offset.load3(mDrawablep->getRegion()->getOriginAgent().mV);
			newMin.add(offset);
			newMax.add(offset);
			
			llassert(less_than_max_mag(newMin));
			llassert(less_than_max_mag(newMax));
		}

		t.setAdd(newMin, newMax);
		t.mul(0.5f);

		llassert(less_than_max_mag(t));
		
		//VECTORIZE THIS
		mCenterLocal.set(t.getF32ptr());
		
		llassert(less_than_max_mag(newMin));
		llassert(less_than_max_mag(newMax));

		t.setSub(newMax,newMin);
		mBoundingSphereRadius = t.getLength3().getF32()*0.5f;

		updateCenterAgent();
	}

	return TRUE;
}