示例#1
0
//-----------------------------------------------------------------------------
// 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)
	{
		llwarns << "Can't read number of morph target vertices" << llendl;
		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)
		{
			llwarns << "Can't read morph target vertex number" << llendl;
			return FALSE;
		}

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


		numRead = fread(&mCoords[v], sizeof(F32), 3, fp);
		llendianswizzle(&mCoords[v], sizeof(F32), 3);
		if (numRead != 3)
		{
			llwarns << "Can't read morph target vertex coordinates" << llendl;
			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)
		{
			llwarns << "Can't read morph target normal" << llendl;
			return FALSE;
		}

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


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

		mNumIndices++;
	}

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

	return TRUE;
}
示例#2
0
//-----------------------------------------------------------------------------
// 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     = static_cast<LLVector4a*>(ll_aligned_malloc_16(nindices * sizeof(LLVector4a)));
	LLVector4a* new_normals    = static_cast<LLVector4a*>(ll_aligned_malloc_16(nindices * sizeof(LLVector4a)));
	LLVector4a* new_binormals  = static_cast<LLVector4a*>(ll_aligned_malloc_16(nindices * sizeof(LLVector4a)));
	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)
	{
		LLAvatarAppearance* avatarp = (LLAvatarAppearance*)*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
	//-------------------------------------------------------------------------
	freeData();

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

	return TRUE;
}
示例#3
0
void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
{
	llassert(newnverts >= 0);
	llassert(newnindices >= 0);

	mRequestedNumVerts = newnverts;
	mRequestedNumIndices = newnindices;

	LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
	mDynamicSize = TRUE;
	if (mUsage == GL_STATIC_DRAW_ARB)
	{ //always delete/allocate static buffers on resize
		destroyGLBuffer();
		destroyGLIndices();
		allocateBuffer(newnverts, newnindices, TRUE);
		mFinal = FALSE;
	}
	else if (newnverts > mNumVerts || newnindices > mNumIndices ||
			 newnverts < mNumVerts/2 || newnindices < mNumIndices/2)
	{
		sAllocatedBytes -= getSize() + getIndicesSize();
		
		S32 oldsize = getSize();
		S32 old_index_size = getIndicesSize();

		updateNumVerts(newnverts);		
		updateNumIndices(newnindices);
		
		S32 newsize = getSize();
		S32 new_index_size = getIndicesSize();

		sAllocatedBytes += newsize + new_index_size;

		if (newsize)
		{
			if (!mGLBuffer)
			{ //no buffer exists, create a new one
				createGLBuffer();
			}
			else
			{
				//delete old buffer, keep GL buffer for now
				if (!useVBOs())
				{
					volatile U8* old = mMappedData;
					mMappedData =  (U8*) ll_aligned_malloc_16(newsize);
					if (old)
					{	
						memcpy((void*)mMappedData, (void*)old, llmin(newsize, oldsize));
						if ((newsize > oldsize) && !sOmitBlank)
						{
							memset((void*)(mMappedData+oldsize), 0, newsize-oldsize);
						}

						ll_aligned_free_16((void*)old);
					}
					else
					{
						if (!sOmitBlank) memset((void*)mMappedData, 0, newsize);
						mEmpty = TRUE;
					}
				}
				mResized = TRUE;
			}
		}
		else if (mGLBuffer)
		{
			destroyGLBuffer();
		}
		
		if (new_index_size)
		{
			if (!mGLIndices)
			{
				createGLIndices();
			}
			else
			{
				if (!useVBOs())
				{
					//delete old buffer, keep GL buffer for now
					volatile U8* old = mMappedIndexData;
					mMappedIndexData = (U8*) ll_aligned_malloc_16(new_index_size);
					
					if (old)
					{	
						memcpy((void*)mMappedIndexData, (void*)old, llmin(new_index_size, old_index_size));
						if ((new_index_size > old_index_size) && !sOmitBlank)
						{
							memset((void*)(mMappedIndexData+old_index_size), 0, new_index_size - old_index_size);
						}
						ll_aligned_free_16((void*)old);
					}
					else
					{
						if (!sOmitBlank) memset((void*)mMappedIndexData, 0, new_index_size);
						mEmpty = TRUE;
					}
				}
				mResized = TRUE;
			}
		}
		else if (mGLIndices)
		{
			destroyGLIndices();
		}
	}

	if (mResized && useVBOs())
	{
		freeClientBuffer() ;
		setBuffer(0);
	}
}