Beispiel #1
0
void LLModel::setVolumeFaceData(
	S32 f, 
	LLStrider<LLVector3> pos, 
	LLStrider<LLVector3> norm, 
	LLStrider<LLVector2> tc, 
	LLStrider<U16> ind, 
	U32 num_verts, 
	U32 num_indices)
{
	LLVolumeFace& face = mVolumeFaces[f];

	face.resizeVertices(num_verts);
	face.resizeIndices(num_indices);

	LLVector4a::memcpyNonAliased16((F32*) face.mPositions, (F32*) pos.get(), num_verts*4*sizeof(F32));
	if (norm.get())
	{
		LLVector4a::memcpyNonAliased16((F32*) face.mNormals, (F32*) norm.get(), num_verts*4*sizeof(F32));
	}
	else
	{
		//ll_aligned_free_16(face.mNormals);
		face.mNormals = NULL;
	}

	if (tc.get())
	{
		U32 tex_size = (num_verts*2*sizeof(F32)+0xF)&~0xF;
		LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), tex_size);
	}
	else
	{
		//ll_aligned_free_16(face.mTexCoords);
		face.mTexCoords = NULL;
	}

	U32 size = (num_indices*2+0xF)&~0xF;
	LLVector4a::memcpyNonAliased16((F32*) face.mIndices, (F32*) ind.get(), size);
}
void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind, bool terse_update)
{
	//IF THIS FUNCTION BREAKS, SEE LLPOLYMESH CONSTRUCTOR AND CHECK ALIGNMENT OF INPUT ARRAYS

	mFace = face;

	if (!mFace->getVertexBuffer())
	{
		return;
	}

	LLDrawPool *poolp = mFace->getPool();
	BOOL hardware_skinning = (poolp && poolp->getVertexShaderLevel() > 0) ? TRUE : FALSE;

	if (!hardware_skinning && terse_update)
	{ //no need to do terse updates if we're doing software vertex skinning
	 // since mMesh is being copied into mVertexBuffer every frame
		return;
	}


	LLFastTimer t(FTM_AVATAR_FACE);

	LLStrider<LLVector3> verticesp;
	LLStrider<LLVector3> normalsp;
	LLStrider<LLVector2> tex_coordsp;
	LLStrider<F32>		 vertex_weightsp;
	LLStrider<LLVector4> clothing_weightsp;
	LLStrider<U16> indicesp;

	// Copy data into the faces from the polymesh data.
	if (mMesh && mValid)
	{
		const U32 num_verts = mMesh->getNumVertices();

		if (num_verts)
		{
			face->getVertexBuffer()->getIndexStrider(indicesp);
			face->getGeometryAvatar(verticesp, normalsp, tex_coordsp, vertex_weightsp, clothing_weightsp);
			
			verticesp += mMesh->mFaceVertexOffset;
			normalsp += mMesh->mFaceVertexOffset;
			
			F32* v = (F32*) verticesp.get();
			F32* n = (F32*) normalsp.get();
			
			U32 words = num_verts*4;

			LLVector4a::memcpyNonAliased16(v, (F32*) mMesh->getCoords(), words*sizeof(F32));
			LLVector4a::memcpyNonAliased16(n, (F32*) mMesh->getNormals(), words*sizeof(F32));
						
			
			if (!terse_update)
			{
				vertex_weightsp += mMesh->mFaceVertexOffset;
				clothing_weightsp += mMesh->mFaceVertexOffset;
				tex_coordsp += mMesh->mFaceVertexOffset;
		
				F32* tc = (F32*) tex_coordsp.get();
				F32* vw = (F32*) vertex_weightsp.get();
				F32* cw = (F32*) clothing_weightsp.get();	

				S32 tc_size = (num_verts*2*sizeof(F32)+0xF) & ~0xF;
				LLVector4a::memcpyNonAliased16(tc, (F32*) mMesh->getTexCoords(), tc_size);
				S32 vw_size = (num_verts*sizeof(F32)+0xF) & ~0xF;	
				LLVector4a::memcpyNonAliased16(vw, (F32*) mMesh->getWeights(), vw_size);	
				LLVector4a::memcpyNonAliased16(cw, (F32*) mMesh->getClothingWeights(), num_verts*4*sizeof(F32));	
			}

			const U32 idx_count = mMesh->getNumFaces()*3;

			indicesp += mMesh->mFaceIndexOffset;

			U16* __restrict idx = indicesp.get();
			S32* __restrict src_idx = (S32*) mMesh->getFaces();	

			const S32 offset = (S32) mMesh->mFaceVertexOffset;

			for (S32 i = 0; i < (S32)idx_count; ++i)
			{
				*(idx++) = *(src_idx++)+offset;
			}
		}
	}
}
void LLVOSurfacePatch::updateEastGeometry(LLFace *facep,
										  LLStrider<LLVector3> &verticesp,
										  LLStrider<LLVector3> &normalsp,
										  LLStrider<LLVector2> &texCoords0p,
										  LLStrider<LLVector2> &texCoords1p,
										  LLStrider<U16> &indicesp,
										  U32 &index_offset)
{
	S32 i, x, y;

	S32 num_vertices;

	U32 render_stride = mLastStride;
	S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
	S32 length = patch_size / render_stride;
	S32 half_length = length / 2;

	U32 east_stride = mLastEastStride;

	// Stride lengths are the same
	if (east_stride == render_stride)
	{
		num_vertices = 2 * length + 1;

		facep->mCenterAgent = (mPatchp->getPointAgent(8, 15) + mPatchp->getPointAgent(8, 16))*0.5f;

		// Main patch
		for (i = 0; i < length; i++)
		{
			x = 16 - render_stride;
			y = i * render_stride;

			mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
			verticesp++;
			normalsp++;
			texCoords0p++;
			texCoords1p++;
		}

		// East patch
		for (i = 0; i <= length; i++)
		{
			x = 16;
			y = i * render_stride;
			mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
			verticesp++;
			normalsp++;
			texCoords0p++;
			texCoords1p++;
		}


		for (i = 0; i < length; i++)
		{
			// Generate indices
			*(indicesp++) = index_offset + i;
			*(indicesp++) = index_offset + length + i;
			*(indicesp++) = index_offset + length + i + 1;

			if (i != length - 1)
			{
				*(indicesp++) = index_offset + i;
				*(indicesp++) = index_offset + length + i + 1;
				*(indicesp++) = index_offset + i + 1;
			}
		}
	}
	else if (east_stride > render_stride)
	{
		// East stride is longer (has less vertices)
		num_vertices = length + half_length + 1;

		facep->mCenterAgent = (mPatchp->getPointAgent(7, 15) + mPatchp->getPointAgent(8, 16))*0.5f;

		// Iterate through this patch's points
		for (i = 0; i < length; i++)
		{
			x = 16 - render_stride;
			y = i * render_stride;

			mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
			verticesp++;
			normalsp++;
			texCoords0p++;
			texCoords1p++;
		}
		// Iterate through the east patch's points
		for (i = 0; i <= length; i+=2)
		{
			x = 16;
			y = i * render_stride;

			mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
			verticesp++;
			normalsp++;
			texCoords0p++;
			texCoords1p++;
		}

		for (i = 0; i < length; i++)
		{
			if (!(i % 2))
			{
				*(indicesp++) = index_offset + i;
				*(indicesp++) = index_offset + length + (i/2);
				*(indicesp++) = index_offset + i + 1;

				*(indicesp++) = index_offset + i + 1;
				*(indicesp++) = index_offset + length + (i/2);
				*(indicesp++) = index_offset + length + (i/2) + 1;
			}
			else if (i < (length - 1))
			{
				*(indicesp++) = index_offset + i;
				*(indicesp++) = index_offset + length + (i/2) + 1;
				*(indicesp++) = index_offset + i + 1;
			}
		}
	}
	else
	{
		// East stride is shorter (more vertices)
		length = patch_size / east_stride;
		half_length = length / 2;
		num_vertices = length + length/2 + 1;

		facep->mCenterAgent = (mPatchp->getPointAgent(15, 7) + mPatchp->getPointAgent(16, 8))*0.5f;

		// Iterate through this patch's points
		for (i = 0; i < length; i+=2)
		{
			x = 16 - render_stride;
			y = i * east_stride;

			mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
			verticesp++;
			normalsp++;
			texCoords0p++;
			texCoords1p++;
		}
		// Iterate through the east patch's points
		for (i = 0; i <= length; i++)
		{
			x = 16;
			y = i * east_stride;

			mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
			verticesp++;
			normalsp++;
			texCoords0p++;
			texCoords1p++;
		}

		for (i = 0; i < length; i++)
		{
			if (!(i%2))
			{
				*(indicesp++) = index_offset + half_length + i;
				*(indicesp++) = index_offset + half_length + i + 1;
				*(indicesp++) = index_offset + i/2;
			}
			else if (i < (length - 2))
			{
				*(indicesp++) = index_offset + half_length + i;
				*(indicesp++) = index_offset + i/2 + 1;
				*(indicesp++) = index_offset + i/2;

				*(indicesp++) = index_offset + half_length + i;
				*(indicesp++) = index_offset + half_length + i + 1;
				*(indicesp++) = index_offset + i/2 + 1;
			}
			else
			{
				*(indicesp++) = index_offset + half_length + i;
				*(indicesp++) = index_offset + half_length + i + 1;
				*(indicesp++) = index_offset + i/2;
			}
		}
	}
	index_offset += num_vertices;
}
void LLVOSurfacePatch::updateMainGeometry(LLFace *facep,
										LLStrider<LLVector3> &verticesp,
										LLStrider<LLVector3> &normalsp,
										LLStrider<LLVector2> &texCoords0p,
										LLStrider<LLVector2> &texCoords1p,
										LLStrider<U16> &indicesp,
										U32 &index_offset)
{
	S32 i, j, x, y;

	U32 patch_size, render_stride;
	S32 num_vertices, num_indices;
	U32 index;

	llassert(mLastStride > 0);

	render_stride = mLastStride;
	patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
	S32 vert_size = patch_size / render_stride;

	///////////////////////////
	//
	// Render the main patch
	//
	//

	num_vertices = 0;
	num_indices = 0;
	// First, figure out how many vertices we need...
	getGeomSizesMain(render_stride, num_vertices, num_indices);

	if (num_vertices > 0)
	{
		facep->mCenterAgent = mPatchp->getPointAgent(8, 8);

		// Generate patch points first
		for (j = 0; j < vert_size; j++)
		{
			for (i = 0; i < vert_size; i++)
			{
				x = i * render_stride;
				y = j * render_stride;
				mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
				verticesp++;
				normalsp++;
				texCoords0p++;
				texCoords1p++;
			}
		}

		for (j = 0; j < (vert_size - 1); j++)
		{
			if (j % 2)
			{
				for (i = (vert_size - 1); i > 0; i--)
				{
					index = (i - 1)+ j*vert_size;
					*(indicesp++) = index_offset + index;

					index = i + (j+1)*vert_size;
					*(indicesp++) = index_offset + index;

					index = (i - 1) + (j+1)*vert_size;
					*(indicesp++) = index_offset + index;

					index = (i - 1) + j*vert_size;
					*(indicesp++) = index_offset + index;

					index = i + j*vert_size;
					*(indicesp++) = index_offset + index;

					index = i + (j+1)*vert_size;
					*(indicesp++) = index_offset + index;
				}
			}
			else
			{
				for (i = 0; i < (vert_size - 1); i++)
				{
					index = i + j*vert_size;
					*(indicesp++) = index_offset + index;

					index = (i + 1) + (j+1)*vert_size;
					*(indicesp++) = index_offset + index;

					index = i + (j+1)*vert_size;
					*(indicesp++) = index_offset + index;

					index = i + j*vert_size;
					*(indicesp++) = index_offset + index;

					index = (i + 1) + j*vert_size;
					*(indicesp++) = index_offset + index;

					index = (i + 1) + (j + 1)*vert_size;
					*(indicesp++) = index_offset + index;
				}
			}
		}
	}
	index_offset += num_vertices;
}
void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face, 
													const LLMeshSkinInfo* skin, LLVolume* volume, 
													const LLVolumeFace& vol_face, LLVOVolume* vobj)
{
	LLVector4a* weight = vol_face.mWeights;
	if (!weight)
	{
		return;
	}

	LLPointer<LLVertexBuffer> buffer = face->getVertexBuffer();
	LLDrawable* drawable = face->getDrawable();

	U32 data_mask = face->getRiggedVertexBufferDataMask();

	if (buffer.isNull() || buffer->getTypeMask() != data_mask ||
		buffer->getRequestedVerts() != vol_face.mNumVertices ||
		buffer->getRequestedIndices() != vol_face.mNumIndices ||
		(drawable && drawable->isState(LLDrawable::REBUILD_ALL)))
	{
		face->setGeomIndex(0);
		face->setIndicesIndex(0);

		if (buffer.isNull() || buffer->getTypeMask() != data_mask)
		{	//make a new buffer
			if (sShaderLevel > 0)
			{
				buffer = new LLVertexBuffer(data_mask, GL_DYNAMIC_DRAW_ARB);
			}
			else
			{
				buffer = new LLVertexBuffer(data_mask, GL_STREAM_DRAW_ARB);
			}
			buffer->allocateBuffer(vol_face.mNumVertices,
								   vol_face.mNumIndices, true);
		}
		else
		{	//resize existing buffer
			buffer->resizeBuffer(vol_face.mNumVertices, vol_face.mNumIndices);
		}

		face->setSize(vol_face.mNumVertices, vol_face.mNumIndices);
		face->setVertexBuffer(buffer);

		U16 offset = 0;

		LLMatrix4 mat_vert = skin->mBindShapeMatrix;
		glh::matrix4f m((F32*) mat_vert.mMatrix);
		m = m.inverse().transpose();

		F32 mat3[] = {	m.m[0], m.m[1], m.m[2],
						m.m[4], m.m[5], m.m[6],
						m.m[8], m.m[9], m.m[10] };

		LLMatrix3 mat_normal(mat3);

		static LLCachedControl<bool> mesh_enable_deformer(gSavedSettings, "MeshEnableDeformer");
		if (mesh_enable_deformer)
		{
			LLDeformedVolume* deformed_volume = vobj->getDeformedVolume();
			deformed_volume->deform(volume, avatar, skin, face->getTEOffset());
			face->getGeometryVolume(*deformed_volume, face->getTEOffset(), mat_vert,
									mat_normal, offset, true);
		}
		else
		{
			face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert,
 									mat_normal, offset, true);
		}
	}

	if (sShaderLevel <= 0 && face->mLastSkinTime < avatar->getLastSkinTime())
	{ //perform software vertex skinning for this face
		LLStrider<LLVector3> position;
		LLStrider<LLVector3> normal;

		bool has_normal = buffer->hasDataType(LLVertexBuffer::TYPE_NORMAL);
		buffer->getVertexStrider(position);

		if (has_normal)
		{
			buffer->getNormalStrider(normal);
		}
		LLVector4a* pos = (LLVector4a*) position.get();

		LLVector4a* norm = has_normal ? (LLVector4a*) normal.get() : NULL;

		//build matrix palette
		LLMatrix4a mp[64];
		LLMatrix4* mat = (LLMatrix4*) mp;

		for (U32 j = 0; j < skin->mJointNames.size(); ++j)
		{
			LLJoint* joint = avatar->getJoint(skin->mJointNames[j]);
			if (joint)
			{
				mat[j] = skin->mInvBindMatrix[j];
				mat[j] *= joint->getWorldMatrix();
			}
		}

		LLMatrix4a bind_shape_matrix;
		bind_shape_matrix.loadu(skin->mBindShapeMatrix);

		for (U32 j = 0; j < buffer->getRequestedVerts(); ++j)
		{
			LLMatrix4a final_mat;
			final_mat.clear();

			S32 idx[4];

			LLVector4 wght;

			F32 scale = 0.f;
			for (U32 k = 0; k < 4; k++)
		{
				F32 w = weight[j][k];

				idx[k] = llclamp((S32) floorf(w), 0, 63);
				wght[k] = w - floorf(w);
				scale += wght[k];
			}

			wght *= 1.f/scale;

			for (U32 k = 0; k < 4; k++)
			{
				F32 w = wght[k];

				LLMatrix4a src;
				src.setMul(mp[idx[k]], w);

				final_mat.add(src);
			}

			LLVector4a& v = vol_face.mPositions[j];
			LLVector4a t;
			LLVector4a dst;
			bind_shape_matrix.affineTransform(v, t);
			final_mat.affineTransform(t, dst);
			pos[j] = dst;

			if (norm)
			{
				LLVector4a& n = vol_face.mNormals[j];
				bind_shape_matrix.rotate(n, t);
				final_mat.rotate(t, dst);
				norm[j] = dst;
			}
		}
	}

	if (drawable && face->getTEOffset() == drawable->getNumFaces() - 1)
	{
		drawable->clearState(LLDrawable::REBUILD_ALL);
	}
}
void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind, bool terse_update)
{
	mFace = face;

	if (!mFace->getVertexBuffer())
	{
		return;
	}

	LLStrider<LLVector3> verticesp;
	LLStrider<LLVector3> normalsp;
	LLStrider<LLVector2> tex_coordsp;
	LLStrider<F32>		 vertex_weightsp;
	LLStrider<LLVector4> clothing_weightsp;
	LLStrider<U16> indicesp;

	// Copy data into the faces from the polymesh data.
	if (mMesh && mValid)
	{
		if (mMesh->getNumVertices())
		{
			stop_glerror();
			face->getGeometryAvatar(verticesp, normalsp, tex_coordsp, vertex_weightsp, clothing_weightsp);
			stop_glerror();
			face->getVertexBuffer()->getIndexStrider(indicesp);
			stop_glerror();

			verticesp += mMesh->mFaceVertexOffset;
			tex_coordsp += mMesh->mFaceVertexOffset;
			normalsp += mMesh->mFaceVertexOffset;
			vertex_weightsp += mMesh->mFaceVertexOffset;
			clothing_weightsp += mMesh->mFaceVertexOffset;

			const U32* __restrict coords = (U32*) mMesh->getCoords();
			const U32* __restrict tex_coords = (U32*) mMesh->getTexCoords();
			const U32* __restrict normals = (U32*) mMesh->getNormals();
			const U32* __restrict weights = (U32*) mMesh->getWeights();
			const U32* __restrict cloth_weights = (U32*) mMesh->getClothingWeights();

			const U32 num_verts = mMesh->getNumVertices();

			U32 i = 0;

			const U32 skip = verticesp.getSkip()/sizeof(U32);

			U32* __restrict v = (U32*) verticesp.get();
			U32* __restrict n = (U32*) normalsp.get();
			
			if (terse_update)
			{
				for (S32 i = num_verts; i > 0; --i)
				{
					//morph target application only, only update positions and normals
					v[0] = coords[0]; 
					v[1] = coords[1]; 
					v[2] = coords[2];		
					coords += 3;
					v += skip;
				}

				for (S32 i = num_verts; i > 0; --i)
				{
					n[0] = normals[0]; 
					n[1] = normals[1];
					n[2] = normals[2];
					normals += 3;
					n += skip;
				}
			}
			else
				{

				U32* __restrict tc = (U32*) tex_coordsp.get();
				U32* __restrict vw = (U32*) vertex_weightsp.get();
				U32* __restrict cw = (U32*) clothing_weightsp.get();
				
				do
				{
					v[0] = *(coords++); 
					v[1] = *(coords++); 
					v[2] = *(coords++);
					v += skip;

					tc[0] = *(tex_coords++); 
					tc[1] = *(tex_coords++);
					tc += skip;

					n[0] = *(normals++); 
					n[1] = *(normals++);
					n[2] = *(normals++);
					n += skip;

					vw[0] = *(weights++);
					vw += skip;

					cw[0] = *(cloth_weights++);
					cw[1] = *(cloth_weights++);
					cw[2] = *(cloth_weights++);
					cw[3] = *(cloth_weights++);
					cw += skip;
				}
				while (++i < num_verts);

				const U32 idx_count = mMesh->getNumFaces()*3;

				indicesp += mMesh->mFaceIndexOffset;

				U16* __restrict idx = indicesp.get();
				S32* __restrict src_idx = (S32*) mMesh->getFaces();

				i = 0;

				const S32 offset = (S32) mMesh->mFaceVertexOffset;

				do
				{
					*(idx++) = *(src_idx++)+offset;
				}
				while (++i < idx_count);
			}
		}
	}