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); } } }