void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face) { face->setGeomIndex(0); face->setIndicesIndex(0); //rigged faces do not batch textures face->setTextureIndex(255); if (buffer.isNull() || buffer->getTypeMask() != data_mask || !buffer->isWriteable()) { //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); //let getGeometryVolume know if alpha should override shiny U32 type = gPipeline.getPoolTypeFromTE(face->getTextureEntry(), face->getTexture()); if (type == LLDrawPool::POOL_ALPHA) { face->setPoolType(LLDrawPool::POOL_ALPHA); } else { face->setPoolType(LLDrawPool::POOL_AVATAR); } //llinfos << "Rebuilt face " << face->getTEOffset() << " of " << face->getDrawable() << " at " << gFrameTimeSeconds << llendl; face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_normal, offset, true); buffer->flush(); }
void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face) { 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->getNumVerts() != vol_face.mNumVertices || buffer->getNumIndices() != vol_face.mNumIndices || (drawable && drawable->isState(LLDrawable::REBUILD_ALL))) { if (drawable && drawable->isState(LLDrawable::REBUILD_ALL)) { //rebuild EVERY face in the drawable, not just this one, to avoid missing drawable wide rebuild issues for (S32 i = 0; i < drawable->getNumFaces(); ++i) { LLFace* facep = drawable->getFace(i); U32 face_data_mask = facep->getRiggedVertexBufferDataMask(); if (face_data_mask) { LLPointer<LLVertexBuffer> cur_buffer = facep->getVertexBuffer(); const LLVolumeFace& cur_vol_face = volume->getVolumeFace(i); getRiggedGeometry(facep, cur_buffer, face_data_mask, skin, volume, cur_vol_face); } } drawable->clearState(LLDrawable::REBUILD_ALL); buffer = face->getVertexBuffer(); } else { //just rebuild this face getRiggedGeometry(face, buffer, data_mask, skin, volume, vol_face); } } if (sShaderLevel <= 0 && face->mLastSkinTime < avatar->getLastSkinTime()) { avatar->updateSoftwareSkinnedVertices(skin, weight, vol_face, buffer); } }
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); } }