void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance) { mCameraDistance = distance; mCameraZoom = 1.f; mCameraPitch = 0.f; mCameraYaw = 0.f; mCameraOffset.clearVec(); if (imagep) { mVolume->sculpt(imagep->getWidth(), imagep->getHeight(), imagep->getComponents(), imagep->getData(), 0); } const LLVolumeFace &vf = mVolume->getVolumeFace(0); U32 num_indices = vf.mNumIndices; U32 num_vertices = vf.mNumVertices; mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL, 0); mVertexBuffer->allocateBuffer(num_vertices, num_indices, TRUE); LLStrider<LLVector3> vertex_strider; LLStrider<LLVector3> normal_strider; LLStrider<U16> index_strider; mVertexBuffer->getVertexStrider(vertex_strider); mVertexBuffer->getNormalStrider(normal_strider); mVertexBuffer->getIndexStrider(index_strider); // build vertices and normals LLStrider<LLVector3> pos; pos = (LLVector3*) vf.mPositions; pos.setStride(16); LLStrider<LLVector3> norm; norm = (LLVector3*) vf.mNormals; norm.setStride(16); for (U32 i = 0; i < num_vertices; i++) { *(vertex_strider++) = *pos++; LLVector3 normal = *norm++; normal.normalize(); *(normal_strider++) = normal; } // build indices for (U16 i = 0; i < num_indices; i++) { *(index_strider++) = vf.mIndices[i]; } }
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 LLVOPartGroup::getGeometry(const LLViewerPart& part, LLStrider<LLVector4a>& verticesp) { if (part.mFlags & LLPartData::LL_PART_RIBBON_MASK) { LLVector4a axis, pos, paxis, ppos; F32 scale, pscale; pos.load3(part.mPosAgent.mV); axis.load3(part.mAxis.mV); scale = part.mScale.mV[0]; if (part.mParent) { ppos.load3(part.mParent->mPosAgent.mV); paxis.load3(part.mParent->mAxis.mV); pscale = part.mParent->mScale.mV[0]; } else { //use source object as position if (part.mPartSourcep->mSourceObjectp.notNull()) { LLVector3 v = LLVector3(0,0,1); v *= part.mPartSourcep->mSourceObjectp->getRenderRotation(); paxis.load3(v.mV); ppos.load3(part.mPartSourcep->mPosAgent.mV); pscale = part.mStartScale.mV[0]; } else { //no source object, no parent, nothing to draw ppos = pos; pscale = scale; paxis = axis; } } LLVector4a p0, p1, p2, p3; scale *= 0.5f; pscale *= 0.5f; axis.mul(scale); paxis.mul(pscale); p0.setAdd(pos, axis); p1.setSub(pos,axis); p2.setAdd(ppos, paxis); p3.setSub(ppos, paxis); (*verticesp++) = p2; (*verticesp++) = p3; (*verticesp++) = p0; (*verticesp++) = p1; } else { LLVector4a part_pos_agent; part_pos_agent.load3(part.mPosAgent.mV); LLVector4a camera_agent; camera_agent.load3(getCameraPosition().mV); LLVector4a at; at.setSub(part_pos_agent, camera_agent); LLVector4a up(0, 0, 1); LLVector4a right; right.setCross3(at, up); right.normalize3fast(); up.setCross3(right, at); up.normalize3fast(); if (part.mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK) { LLVector4a normvel; normvel.load3(part.mVelocity.mV); normvel.normalize3fast(); LLVector2 up_fracs; up_fracs.mV[0] = normvel.dot3(right).getF32(); up_fracs.mV[1] = normvel.dot3(up).getF32(); up_fracs.normalize(); LLVector4a new_up; LLVector4a new_right; //new_up = up_fracs.mV[0] * right + up_fracs.mV[1]*up; LLVector4a t = right; t.mul(up_fracs.mV[0]); new_up = up; new_up.mul(up_fracs.mV[1]); new_up.add(t); //new_right = up_fracs.mV[1] * right - up_fracs.mV[0]*up; t = right; t.mul(up_fracs.mV[1]); new_right = up; new_right.mul(up_fracs.mV[0]); t.sub(new_right); up = new_up; right = t; up.normalize3fast(); right.normalize3fast(); } right.mul(0.5f*part.mScale.mV[0]); up.mul(0.5f*part.mScale.mV[1]); //HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should) // this works because there is actually a 4th float stored after the vertex position which is used as a texture index // also, somebody please VECTORIZE THIS LLVector4a ppapu; LLVector4a ppamu; ppapu.setAdd(part_pos_agent, up); ppamu.setSub(part_pos_agent, up); verticesp->setSub(ppapu, right); (*verticesp++).getF32ptr()[3] = 0.f; verticesp->setSub(ppamu, right); (*verticesp++).getF32ptr()[3] = 0.f; verticesp->setAdd(ppapu, right); (*verticesp++).getF32ptr()[3] = 0.f; verticesp->setAdd(ppamu, right); (*verticesp++).getF32ptr()[3] = 0.f; } }
void LLVOClouds::getGeometry(S32 idx, LLStrider<LLVector4a>& verticesp, LLStrider<LLVector3>& normalsp, LLStrider<LLVector2>& texcoordsp, LLStrider<LLColor4U>& colorsp, LLStrider<U16>& indicesp) { if (idx >= mCloudGroupp->getNumPuffs()) { return; } LLDrawable* drawable = mDrawable; LLFace *facep = drawable->getFace(idx); if (!facep->hasGeometry()) { return; } const LLCloudPuff &puff = mCloudGroupp->getPuff(idx); LLColor4 float_color(LLColor3(gSky.getSunDiffuseColor() + gSky.getSunAmbientColor()),puff.getAlpha()); LLColor4U color; color.setVec(float_color); facep->setFaceColor(float_color); U32 vert_offset = facep->getGeomIndex(); LLVector4a part_pos_agent; part_pos_agent.load3(facep->mCenterLocal.mV); LLVector4a at; at.load3(LLViewerCamera::getInstance()->getAtAxis().mV); LLVector4a up(0, 0, 1); LLVector4a right; right.setCross3(at, up); right.normalize3fast(); up.setCross3(right, at); up.normalize3fast(); right.mul(0.5f*CLOUD_PUFF_WIDTH); up.mul(0.5f*CLOUD_PUFF_HEIGHT); LLVector3 normal(0.f,0.f,-1.f); //HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should) // this works because there is actually a 4th float stored after the vertex position which is used as a texture index // also, somebody please VECTORIZE THIS LLVector4a ppapu; LLVector4a ppamu; ppapu.setAdd(part_pos_agent, up); ppamu.setSub(part_pos_agent, up); verticesp->setSub(ppapu, right); (*verticesp++).getF32ptr()[3] = 0.f; verticesp->setSub(ppamu, right); (*verticesp++).getF32ptr()[3] = 0.f; verticesp->setAdd(ppapu, right); (*verticesp++).getF32ptr()[3] = 0.f; verticesp->setAdd(ppamu, right); (*verticesp++).getF32ptr()[3] = 0.f; // *verticesp++ = puff_pos_agent - right + up; // *verticesp++ = puff_pos_agent - right - up; // *verticesp++ = puff_pos_agent + right + up; // *verticesp++ = puff_pos_agent + right - up; *colorsp++ = color; *colorsp++ = color; *colorsp++ = color; *colorsp++ = color; *texcoordsp++ = LLVector2(0.f, 1.f); *texcoordsp++ = LLVector2(0.f, 0.f); *texcoordsp++ = LLVector2(1.f, 1.f); *texcoordsp++ = LLVector2(1.f, 0.f); *normalsp++ = normal; *normalsp++ = normal; *normalsp++ = normal; *normalsp++ = normal; *indicesp++ = vert_offset + 0; *indicesp++ = vert_offset + 1; *indicesp++ = vert_offset + 2; *indicesp++ = vert_offset + 1; *indicesp++ = vert_offset + 3; *indicesp++ = vert_offset + 2; }
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 LLVOPartGroup::getGeometry(S32 idx, LLStrider<LLVector4a>& verticesp, LLStrider<LLVector3>& normalsp, LLStrider<LLVector2>& texcoordsp, LLStrider<LLColor4U>& colorsp, LLStrider<U16>& indicesp) { if (idx >= (S32) mViewerPartGroupp->mParticles.size()) { return; } const LLViewerPart &part = *((LLViewerPart*) (mViewerPartGroupp->mParticles[idx])); U32 vert_offset = mDrawable->getFace(idx)->getGeomIndex(); LLVector4a part_pos_agent; part_pos_agent.load3(part.mPosAgent.mV); LLVector4a camera_agent; camera_agent.load3(getCameraPosition().mV); LLVector4a at; at.setSub(part_pos_agent, camera_agent); LLVector4a up(0, 0, 1); LLVector4a right; right.setCross3(at, up); right.normalize3fast(); up.setCross3(right, at); up.normalize3fast(); if (part.mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK) { LLVector4a normvel; normvel.load3(part.mVelocity.mV); normvel.normalize3fast(); LLVector2 up_fracs; up_fracs.mV[0] = normvel.dot3(right).getF32(); up_fracs.mV[1] = normvel.dot3(up).getF32(); up_fracs.normalize(); LLVector4a new_up; LLVector4a new_right; //new_up = up_fracs.mV[0] * right + up_fracs.mV[1]*up; LLVector4a t = right; t.mul(up_fracs.mV[0]); new_up = up; new_up.mul(up_fracs.mV[1]); new_up.add(t); //new_right = up_fracs.mV[1] * right - up_fracs.mV[0]*up; t = right; t.mul(up_fracs.mV[1]); new_right = up; new_right.mul(up_fracs.mV[0]); t.sub(new_right); up = new_up; right = t; up.normalize3fast(); right.normalize3fast(); } right.mul(0.5f*part.mScale.mV[0]); up.mul(0.5f*part.mScale.mV[1]); LLVector3 normal = -LLViewerCamera::getInstance()->getXAxis(); //HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should) // this works because there is actually a 4th float stored after the vertex position which is used as a texture index // also, somebody please VECTORIZE THIS LLVector4a ppapu; LLVector4a ppamu; ppapu.setAdd(part_pos_agent, up); ppamu.setSub(part_pos_agent, up); verticesp->setSub(ppapu, right); (*verticesp++).getF32ptr()[3] = 0.f; verticesp->setSub(ppamu, right); (*verticesp++).getF32ptr()[3] = 0.f; verticesp->setAdd(ppapu, right); (*verticesp++).getF32ptr()[3] = 0.f; verticesp->setAdd(ppamu, right); (*verticesp++).getF32ptr()[3] = 0.f; //*verticesp++ = part_pos_agent + up - right; //*verticesp++ = part_pos_agent - up - right; //*verticesp++ = part_pos_agent + up + right; //*verticesp++ = part_pos_agent - up + right; *colorsp++ = part.mColor; *colorsp++ = part.mColor; *colorsp++ = part.mColor; *colorsp++ = part.mColor; *texcoordsp++ = LLVector2(0.f, 1.f); *texcoordsp++ = LLVector2(0.f, 0.f); *texcoordsp++ = LLVector2(1.f, 1.f); *texcoordsp++ = LLVector2(1.f, 0.f); *normalsp++ = normal; *normalsp++ = normal; *normalsp++ = normal; *normalsp++ = normal; *indicesp++ = vert_offset + 0; *indicesp++ = vert_offset + 1; *indicesp++ = vert_offset + 2; *indicesp++ = vert_offset + 1; *indicesp++ = vert_offset + 3; *indicesp++ = vert_offset + 2; }
BOOL LLFace::getGeometryVolume(const LLVolume& volume, const S32 &f, const LLMatrix4& mat_vert_in, const LLMatrix3& mat_norm_in, const U16 &index_offset, bool force_rebuild) { llassert(verify()); const LLVolumeFace &vf = volume.getVolumeFace(f); S32 num_vertices = (S32)vf.mNumVertices; S32 num_indices = (S32) vf.mNumIndices; if (mVertexBuffer.notNull()) { if (num_indices + (S32) mIndicesIndex > mVertexBuffer->getNumIndices()) { llwarns << "Index buffer overflow!" << llendl; llwarns << "Indices Count: " << mIndicesCount << " VF Num Indices: " << num_indices << " Indices Index: " << mIndicesIndex << " VB Num Indices: " << mVertexBuffer->getNumIndices() << llendl; llwarns << "Last Indices Count: " << mLastIndicesCount << " Last Indices Index: " << mLastIndicesIndex << " Face Index: " << f << " Pool Type: " << mPoolType << llendl; return FALSE; } if (num_vertices + mGeomIndex > mVertexBuffer->getNumVerts()) { llwarns << "Vertex buffer overflow!" << llendl; return FALSE; } } LLStrider<LLVector3> vertices; LLStrider<LLVector2> tex_coords; LLStrider<LLVector2> tex_coords2; LLStrider<LLVector3> normals; LLStrider<LLColor4U> colors; LLStrider<LLVector3> binormals; LLStrider<U16> indicesp; #if MESH_ENABLED LLStrider<LLVector4> weights; #endif //MESH_ENABLED BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME); BOOL global_volume = mDrawablep->getVOVolume()->isVolumeGlobal(); LLVector3 scale; if (global_volume) { scale.setVec(1,1,1); } else { scale = mVObjp->getScale(); } bool rebuild_pos = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_POSITION); bool rebuild_color = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_COLOR); bool rebuild_tcoord = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_TCOORD); bool rebuild_normal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); bool rebuild_binormal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_BINORMAL); #if MESH_ENABLED bool rebuild_weights = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_WEIGHT4); #endif //MESH_ENABLED const LLTextureEntry *tep = mVObjp->getTE(f); if (!tep) rebuild_color = FALSE; // can't get color when tep is NULL U8 bump_code = tep ? tep->getBumpmap() : 0; BOOL is_static = mDrawablep->isStatic(); BOOL is_global = is_static; LLVector3 center_sum(0.f, 0.f, 0.f); if (is_global) { setState(GLOBAL); } else { clearState(GLOBAL); } LLColor4U color = (tep ? LLColor4U(tep->getColor()) : LLColor4U::white); if (rebuild_color) // FALSE if tep == NULL { if (tep) { GLfloat alpha[4] = { 0.00f, 0.25f, 0.5f, 0.75f }; if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || (LLPipeline::sRenderBump && tep->getShiny()))) { color.mV[3] = U8 (alpha[tep->getShiny()] * 255); } } } // INDICES if (full_rebuild) { mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex); for (U32 i = 0; i < (U32) num_indices; i++) { indicesp[i] = vf.mIndices[i] + index_offset; } //mVertexBuffer->setBuffer(0); } LLMatrix4a mat_normal; mat_normal.loadu(mat_norm_in); //if it's not fullbright and has no normals, bake sunlight based on face normal //bool bake_sunlight = !getTextureEntry()->getFullbright() && // !mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0; if (rebuild_tcoord) { bool do_xform; if (tep) { r = tep->getRotation(); os = tep->mOffsetS; ot = tep->mOffsetT; ms = tep->mScaleS; mt = tep->mScaleT; cos_ang = cos(r); sin_ang = sin(r); if (cos_ang != 1.f || sin_ang != 0.f || os != 0.f || ot != 0.f || ms != 1.f || mt != 1.f) { do_xform = true; } else { do_xform = false; } } else { do_xform = false; } //bump setup LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f ); LLVector4a bump_s_primary_light_ray(0.f, 0.f, 0.f); LLVector4a bump_t_primary_light_ray(0.f, 0.f, 0.f); LLQuaternion bump_quat; if (mDrawablep->isActive()) { bump_quat = LLQuaternion(mDrawablep->getRenderMatrix()); } if (bump_code) { mVObjp->getVolume()->genBinormals(f); F32 offset_multiple; switch( bump_code ) { case BE_NO_BUMP: offset_multiple = 0.f; break; case BE_BRIGHTNESS: case BE_DARKNESS: if( mTexture.notNull() && mTexture->hasGLTexture()) { // Offset by approximately one texel S32 cur_discard = mTexture->getDiscardLevel(); S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() ); max_size <<= cur_discard; const F32 ARTIFICIAL_OFFSET = 2.f; offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; } else { offset_multiple = 1.f/256; } break; default: // Standard bumpmap textures. Assumed to be 256x256 offset_multiple = 1.f / 256; break; } F32 s_scale = 1.f; F32 t_scale = 1.f; if( tep ) { tep->getScale( &s_scale, &t_scale ); } // Use the nudged south when coming from above sun angle, such // that emboss mapping always shows up on the upward faces of cubes when // it's noon (since a lot of builders build with the sun forced to noon). LLVector3 sun_ray = gSky.mVOSkyp->mBumpSunDir; LLVector3 moon_ray = gSky.getMoonDirection(); LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV); bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV); } U8 texgen = getTextureEntry()->getTexGen(); if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT) { //planar texgen needs binormals mVObjp->getVolume()->genBinormals(f); } U8 tex_mode = 0; if (isState(TEXTURE_ANIM)) { LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp; tex_mode = vobj->mTexAnimMode; if (!tex_mode) { clearState(TEXTURE_ANIM); } else { os = ot = 0.f; r = 0.f; cos_ang = 1.f; sin_ang = 0.f; ms = mt = 1.f; do_xform = false; } if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) { //don't override texture transform during tc bake tex_mode = 0; } } LLVector4a scalea; scalea.load3(scale.mV); bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); bool do_tex_mat = tex_mode && mTextureMatrix; if (!do_bump) { //not in atlas or not bump mapped, might be able to do a cheap update mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex); if (texgen != LLTextureEntry::TEX_GEN_PLANAR) { if (!do_tex_mat) { if (!do_xform) { tex_coords.assignArray((U8*) vf.mTexCoords, sizeof(vf.mTexCoords[0]), num_vertices); } else { for (S32 i = 0; i < num_vertices; i++) { LLVector2 tc(vf.mTexCoords[i]); xform(tc, cos_ang, sin_ang, os, ot, ms, mt); *tex_coords++ = tc; } } } else { //do tex mat, no texgen, no atlas, no bump for (S32 i = 0; i < num_vertices; i++) { LLVector2 tc(vf.mTexCoords[i]); //LLVector4a& norm = vf.mNormals[i]; //LLVector4a& center = *(vf.mCenter); LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); tmp = tmp * *mTextureMatrix; tc.mV[0] = tmp.mV[0]; tc.mV[1] = tmp.mV[1]; *tex_coords++ = tc; } } } else { //no bump, no atlas, tex gen planar if (do_tex_mat) { for (S32 i = 0; i < num_vertices; i++) { LLVector2 tc(vf.mTexCoords[i]); LLVector4a& norm = vf.mNormals[i]; LLVector4a& center = *(vf.mCenter); LLVector4a vec = vf.mPositions[i]; vec.mul(scalea); planarProjection(tc, norm, center, vec); LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); tmp = tmp * *mTextureMatrix; tc.mV[0] = tmp.mV[0]; tc.mV[1] = tmp.mV[1]; *tex_coords++ = tc; } } else { for (S32 i = 0; i < num_vertices; i++) { LLVector2 tc(vf.mTexCoords[i]); LLVector4a& norm = vf.mNormals[i]; LLVector4a& center = *(vf.mCenter); LLVector4a vec = vf.mPositions[i]; vec.mul(scalea); planarProjection(tc, norm, center, vec); xform(tc, cos_ang, sin_ang, os, ot, ms, mt); *tex_coords++ = tc; } } } //mVertexBuffer->setBuffer(0); } else { //either bump mapped or in atlas, just do the whole expensive loop mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex); std::vector<LLVector2> bump_tc; for (S32 i = 0; i < num_vertices; i++) { LLVector2 tc(vf.mTexCoords[i]); LLVector4a& norm = vf.mNormals[i]; LLVector4a& center = *(vf.mCenter); if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) { LLVector4a vec = vf.mPositions[i]; vec.mul(scalea); switch (texgen) { case LLTextureEntry::TEX_GEN_PLANAR: planarProjection(tc, norm, center, vec); break; case LLTextureEntry::TEX_GEN_SPHERICAL: sphericalProjection(tc, norm, center, vec); break; case LLTextureEntry::TEX_GEN_CYLINDRICAL: cylindricalProjection(tc, norm, center, vec); break; default: break; } } if (tex_mode && mTextureMatrix) { LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); tmp = tmp * *mTextureMatrix; tc.mV[0] = tmp.mV[0]; tc.mV[1] = tmp.mV[1]; } else { xform(tc, cos_ang, sin_ang, os, ot, ms, mt); } *tex_coords++ = tc; if (do_bump) { bump_tc.push_back(tc); } } //mVertexBuffer->setBuffer(0); if (do_bump) { mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex); for (S32 i = 0; i < num_vertices; i++) { LLVector4a tangent; tangent.setCross3(vf.mBinormals[i], vf.mNormals[i]); LLMatrix4a tangent_to_object; tangent_to_object.setRows(tangent, vf.mBinormals[i], vf.mNormals[i]); LLVector4a t; tangent_to_object.rotate(binormal_dir, t); LLVector4a binormal; mat_normal.rotate(t, binormal); //VECTORIZE THIS if (mDrawablep->isActive()) { LLVector3 t; t.set(binormal.getF32ptr()); t *= bump_quat; binormal.load3(t.mV); } binormal.normalize3fast(); LLVector2 tc = bump_tc[i]; tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() ); *tex_coords2++ = tc; } //mVertexBuffer->setBuffer(0); } } } if (rebuild_pos) { llassert(num_vertices > 0); mVertexBuffer->getVertexStrider(vertices, mGeomIndex); LLMatrix4a mat_vert; mat_vert.loadu(mat_vert_in); LLVector4a* src = vf.mPositions; LLVector4a position; for (S32 i = 0; i < num_vertices; i++) { mat_vert.affineTransform(src[i], position); vertices[i].set(position.getF32ptr()); } //mVertexBuffer->setBuffer(0); } if (rebuild_normal) { mVertexBuffer->getNormalStrider(normals, mGeomIndex); for (S32 i = 0; i < num_vertices; i++) { LLVector4a normal; mat_normal.rotate(vf.mNormals[i], normal); normal.normalize3fast(); normals[i].set(normal.getF32ptr()); } //mVertexBuffer->setBuffer(0); } if (rebuild_binormal) { mVertexBuffer->getBinormalStrider(binormals, mGeomIndex); for (S32 i = 0; i < num_vertices; i++) { LLVector4a binormal; mat_normal.rotate(vf.mBinormals[i], binormal); binormal.normalize3fast(); binormals[i].set(binormal.getF32ptr()); } //mVertexBuffer->setBuffer(0); } #if MESH_ENABLED if (rebuild_weights && vf.mWeights) { mVertexBuffer->getWeight4Strider(weights, mGeomIndex); weights.assignArray((U8*) vf.mWeights, sizeof(vf.mWeights[0]), num_vertices); //mVertexBuffer->setBuffer(0); } #endif //MESH_ENABLED if (rebuild_color) { mVertexBuffer->getColorStrider(colors, mGeomIndex); for (S32 i = 0; i < num_vertices; i++) { colors[i] = color; } //mVertexBuffer->setBuffer(0); } if (rebuild_tcoord) { mTexExtents[0].setVec(0,0); mTexExtents[1].setVec(1,1); xform(mTexExtents[0], cos_ang, sin_ang, os, ot, ms, mt); xform(mTexExtents[1], cos_ang, sin_ang, os, ot, ms, mt); F32 es = vf.mTexCoordExtents[1].mV[0] - vf.mTexCoordExtents[0].mV[0] ; F32 et = vf.mTexCoordExtents[1].mV[1] - vf.mTexCoordExtents[0].mV[1] ; mTexExtents[0][0] *= es ; mTexExtents[1][0] *= es ; mTexExtents[0][1] *= et ; mTexExtents[1][1] *= et ; } mLastVertexBuffer = mVertexBuffer; mLastGeomCount = mGeomCount; mLastGeomIndex = mGeomIndex; mLastIndicesCount = mIndicesCount; mLastIndicesIndex = mIndicesIndex; return TRUE; }
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); } } }
void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance) { mCameraDistance = distance; mCameraZoom = 1.f; mCameraPitch = 0.f; mCameraYaw = 0.f; mCameraOffset.clearVec(); if (imagep) { mVolume->sculpt(imagep->getWidth(), imagep->getHeight(), imagep->getComponents(), imagep->getData(), 0); } const LLVolumeFace &vf = mVolume->getVolumeFace(0); U32 num_indices = vf.mNumIndices; U32 num_vertices = vf.mNumVertices; mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0, 0); mVertexBuffer->allocateBuffer(num_vertices, num_indices, TRUE); LLStrider<LLVector3> vertex_strider; LLStrider<LLVector3> normal_strider; LLStrider<LLVector2> tc_strider; LLStrider<U16> index_strider; mVertexBuffer->getVertexStrider(vertex_strider); mVertexBuffer->getNormalStrider(normal_strider); mVertexBuffer->getTexCoord0Strider(tc_strider); mVertexBuffer->getIndexStrider(index_strider); // build vertices and normals LLStrider<LLVector3> pos; pos = (LLVector3*) vf.mPositions; pos.setStride(16); LLStrider<LLVector3> norm; norm = (LLVector3*) vf.mNormals; norm.setStride(16); LLStrider<LLVector2> tc; tc = (LLVector2*) vf.mTexCoords; tc.setStride(8); #ifdef OPENSIM // <FS:ND> protect against buffer overflows pos.setCount( vf.mNumVertices ); norm.setCount( vf.mNumVertices ); tc.setCount( vf.mNumVertices ); #endif // </FS:ND> for (U32 i = 0; i < num_vertices; i++) { *(vertex_strider++) = *pos++; LLVector3 normal = *norm++; normal.normalize(); *(normal_strider++) = normal; *(tc_strider++) = *tc++; } // build indices for (U16 i = 0; i < num_indices; i++) { *(index_strider++) = vf.mIndices[i]; } }