//create a vertex buffer for efficiently rendering cubes LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage) { LLVertexBuffer* ret = new LLVertexBuffer(type_mask, usage); ret->allocateBuffer(8, 64, true); LLStrider<LLVector3> pos; LLStrider<U16> idx; ret->getVertexStrider(pos); ret->getIndexStrider(idx); pos[0] = LLVector3(-1,-1,-1); pos[1] = LLVector3(-1,-1, 1); pos[2] = LLVector3(-1, 1,-1); pos[3] = LLVector3(-1, 1, 1); pos[4] = LLVector3( 1,-1,-1); pos[5] = LLVector3( 1,-1, 1); pos[6] = LLVector3( 1, 1,-1); pos[7] = LLVector3( 1, 1, 1); for (U32 i = 0; i < 64; i++) { idx[i] = sOcclusionIndices[i]; } ret->flush(); return ret; }
// static void LLViewerJointMesh::updateGeometry(LLFace *mFace, LLPolyMesh *mMesh) { LLStrider<LLVector3> o_vertices; LLStrider<LLVector3> o_normals; //get vertex and normal striders LLVertexBuffer* buffer = mFace->getVertexBuffer(); buffer->getVertexStrider(o_vertices, 0); buffer->getNormalStrider(o_normals, 0); F32* __restrict vert = o_vertices[0].mV; F32* __restrict norm = o_normals[0].mV; const F32* __restrict weights = mMesh->getWeights(); const LLVector4a* __restrict coords = (LLVector4a*) mMesh->getCoords(); const LLVector4a* __restrict normals = (LLVector4a*) mMesh->getNormals(); U32 offset = mMesh->mFaceVertexOffset*4; vert += offset; norm += offset; for (U32 index = 0; index < mMesh->getNumVertices(); index++) { // equivalent to joint = floorf(weights[index]); S32 joint = _mm_cvtt_ss2si(_mm_load_ss(weights+index)); F32 w = weights[index] - joint; LLMatrix4a gBlendMat; if (w != 0.f) { // blend between matrices and apply gBlendMat.setLerp(gJointMatAligned[joint+0], gJointMatAligned[joint+1], w); LLVector4a res; gBlendMat.affineTransform(coords[index], res); res.store4a(vert+index*4); gBlendMat.rotate(normals[index], res); res.store4a(norm+index*4); } else { // No lerp required in this case. LLVector4a res; gJointMatAligned[joint].affineTransform(coords[index], res); res.store4a(vert+index*4); gJointMatAligned[joint].rotate(normals[index], res); res.store4a(norm+index*4); } } buffer->flush(); }
void LLTerrainPartition::getGeometry(LLSpatialGroup* group) { LLFastTimer ftm(FTM_REBUILD_TERRAIN_VB); LLVertexBuffer* buffer = group->mVertexBuffer; //get vertex buffer striders LLStrider<LLVector3> vertices; LLStrider<LLVector3> normals; LLStrider<LLVector2> texcoords2; LLStrider<LLVector2> texcoords; LLStrider<U16> indices; llassert_always(buffer->getVertexStrider(vertices)); llassert_always(buffer->getNormalStrider(normals)); llassert_always(buffer->getTexCoord0Strider(texcoords)); llassert_always(buffer->getTexCoord1Strider(texcoords2)); llassert_always(buffer->getIndexStrider(indices)); U32 indices_index = 0; U32 index_offset = 0; for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) { LLFace* facep = *i; facep->setIndicesIndex(indices_index); facep->setGeomIndex(index_offset); facep->setVertexBuffer(buffer); LLVOSurfacePatch* patchp = (LLVOSurfacePatch*) facep->getViewerObject(); patchp->getGeometry(vertices, normals, texcoords, texcoords2, indices); indices_index += facep->getIndicesCount(); index_offset += facep->getGeomCount(); } buffer->flush(); mFaceList.clear(); }
BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable) { LLFastTimer ftm(FTM_GEO_SKY); LLStrider<LLVector3> vertices; LLStrider<LLVector2> texCoords; LLStrider<U16> indices; #if DOME_SLICES { mFanVerts = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); mFanVerts->allocateBuffer(getFanNumVerts(), getFanNumIndices(), TRUE); BOOL success = mFanVerts->getVertexStrider(vertices) && mFanVerts->getTexCoord0Strider(texCoords) && mFanVerts->getIndexStrider(indices); if(!success) { llerrs << "Failed updating WindLight sky geometry." << llendl; } buildFanBuffer(vertices, texCoords, indices); mFanVerts->flush(); } { const U32 max_buffer_bytes = gSavedSettings.getS32("RenderMaxVBOSize")*1024; const U32 data_mask = LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK; const U32 max_verts = max_buffer_bytes / LLVertexBuffer::calcVertexSize(data_mask); const U32 total_stacks = getNumStacks(); const U32 verts_per_stack = getNumSlices(); // each seg has to have one more row of verts than it has stacks // then round down const U32 stacks_per_seg = (max_verts - verts_per_stack) / verts_per_stack; // round up to a whole number of segments const U32 strips_segments = (total_stacks+stacks_per_seg-1) / stacks_per_seg; llinfos << "WL Skydome strips in " << strips_segments << " batches." << llendl; mStripsVerts.resize(strips_segments, NULL); LLTimer timer; timer.start(); for (U32 i = 0; i < strips_segments ;++i) { LLVertexBuffer * segment = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); mStripsVerts[i] = segment; U32 num_stacks_this_seg = stacks_per_seg; if ((i == strips_segments - 1) && (total_stacks % stacks_per_seg) != 0) { // for the last buffer only allocate what we'll use num_stacks_this_seg = total_stacks % stacks_per_seg; } // figure out what range of the sky we're filling const U32 begin_stack = i * stacks_per_seg; const U32 end_stack = begin_stack + num_stacks_this_seg; llassert(end_stack <= total_stacks); const U32 num_verts_this_seg = verts_per_stack * (num_stacks_this_seg+1); llassert(num_verts_this_seg <= max_verts); const U32 num_indices_this_seg = 1+num_stacks_this_seg*(2+2*verts_per_stack); llassert(num_indices_this_seg * sizeof(U16) <= max_buffer_bytes); segment->allocateBuffer(num_verts_this_seg, num_indices_this_seg, TRUE); // lock the buffer BOOL success = segment->getVertexStrider(vertices) && segment->getTexCoord0Strider(texCoords) && segment->getIndexStrider(indices); if(!success) { llerrs << "Failed updating WindLight sky geometry." << llendl; } // fill it buildStripsBuffer(begin_stack, end_stack, vertices, texCoords, indices); // and unlock the buffer segment->flush(); } llinfos << "completed in " << llformat("%.2f", timer.getElapsedTimeF32()) << "seconds" << llendl; } #else mStripsVerts = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); const F32 RADIUS = LLWLParamManager::sParamMgr->getDomeRadius(); LLPointer<LLVertexBuffer> temp = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0); temp->allocateBuffer(12, 60, TRUE); BOOL success = temp->getVertexStrider(vertices) && temp->getIndexStrider(indices); if (success) { for (U32 i = 0; i < 12; i++) { *vertices++ = icosahedron_vert[i]; } for (U32 i = 0; i < 60; i++) { *indices++ = icosahedron_ind[i]; } } LLPointer<LLVertexBuffer> temp2; for (U32 i = 0; i < 8; i++) { temp2 = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0); subdivide(*temp, temp2); temp = temp2; } temp->getVertexStrider(vertices); for (S32 i = 0; i < temp->getNumVerts(); i++) { LLVector3 v = vertices[i]; v.normVec(); vertices[i] = v*RADIUS; } temp2 = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0); chop(*temp, temp2); mStripsVerts->allocateBuffer(temp2->getNumVerts(), temp2->getNumIndices(), TRUE); success = mStripsVerts->getVertexStrider(vertices) && mStripsVerts->getTexCoordStrider(texCoords) && mStripsVerts->getIndexStrider(indices); LLStrider<LLVector3> v; temp2->getVertexStrider(v); LLStrider<U16> ind; temp2->getIndexStrider(ind); if (success) { for (S32 i = 0; i < temp2->getNumVerts(); ++i) { LLVector3 vert = *v++; vert.normVec(); F32 z0 = vert.mV[2]; F32 x0 = vert.mV[0]; vert *= RADIUS; *vertices++ = vert; *texCoords++ = LLVector2((-z0 + 1.f) / 2.f, (-x0 + 1.f) / 2.f); } for (S32 i = 0; i < temp2->getNumIndices(); ++i) { *indices++ = *ind++; } } mStripsVerts->flush(); #endif updateStarColors(); updateStarGeometry(drawable); LLPipeline::sCompiles++; return TRUE; }
BOOL LLVOWater::updateGeometry(LLDrawable *drawable) { LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WATER); LLFace *face; if (drawable->getNumFaces() < 1) { LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER); drawable->addFace(poolp, NULL); } face = drawable->getFace(0); // LLVector2 uvs[4]; // LLVector3 vtx[4]; LLStrider<LLVector3> verticesp, normalsp; LLStrider<LLVector2> texCoordsp; LLStrider<U16> indicesp; U16 index_offset; // A quad is 4 vertices and 6 indices (making 2 triangles) static const unsigned int vertices_per_quad = 4; static const unsigned int indices_per_quad = 6; static const LLCachedControl<bool> render_transparent_water("RenderTransparentWater",false); const S32 size = (render_transparent_water && !LLGLSLShader::sNoFixedFunction) ? 16 : 1; const S32 num_quads = size * size; face->setSize(vertices_per_quad * num_quads, indices_per_quad * num_quads); LLVertexBuffer* buff = face->getVertexBuffer(); if (!buff) { buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB); buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE); face->setIndicesIndex(0); face->setGeomIndex(0); face->setVertexBuffer(buff); } else { buff->resizeBuffer(face->getGeomCount(), face->getIndicesCount()); } index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); LLVector3 position_agent; position_agent = getPositionAgent(); face->mCenterAgent = position_agent; face->mCenterLocal = position_agent; S32 x, y; F32 step_x = getScale().mV[0] / size; F32 step_y = getScale().mV[1] / size; const LLVector3 up(0.f, step_y * 0.5f, 0.f); const LLVector3 right(step_x * 0.5f, 0.f, 0.f); const LLVector3 normal(0.f, 0.f, 1.f); F32 size_inv = 1.f / size; for (y = 0; y < size; y++) { for (x = 0; x < size; x++) { S32 toffset = index_offset + 4*(y*size + x); position_agent = getPositionAgent() - getScale() * 0.5f; position_agent.mV[VX] += (x + 0.5f) * step_x; position_agent.mV[VY] += (y + 0.5f) * step_y; *verticesp++ = position_agent - right + up; *verticesp++ = position_agent - right - up; *verticesp++ = position_agent + right + up; *verticesp++ = position_agent + right - up; *texCoordsp++ = LLVector2(x*size_inv, (y+1)*size_inv); *texCoordsp++ = LLVector2(x*size_inv, y*size_inv); *texCoordsp++ = LLVector2((x+1)*size_inv, (y+1)*size_inv); *texCoordsp++ = LLVector2((x+1)*size_inv, y*size_inv); *normalsp++ = normal; *normalsp++ = normal; *normalsp++ = normal; *normalsp++ = normal; *indicesp++ = toffset + 0; *indicesp++ = toffset + 1; *indicesp++ = toffset + 2; *indicesp++ = toffset + 1; *indicesp++ = toffset + 3; *indicesp++ = toffset + 2; } } buff->flush(); mDrawable->movePartition(); LLPipeline::sCompiles++; return TRUE; }
void LLParticlePartition::getGeometry(LLSpatialGroup* group) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); LLFastTimer ftm(mDrawableType == LLPipeline::RENDER_TYPE_GRASS ? LLFastTimer::FTM_REBUILD_GRASS_VB : LLFastTimer::FTM_REBUILD_PARTICLE_VB); std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); U32 index_count = 0; U32 vertex_count = 0; group->clearDrawMap(); LLVertexBuffer* buffer = group->mVertexBuffer; LLStrider<U16> indicesp; LLStrider<LLVector4a> verticesp; LLStrider<LLVector3> normalsp; LLStrider<LLVector2> texcoordsp; LLStrider<LLColor4U> colorsp; buffer->getVertexStrider(verticesp); buffer->getNormalStrider(normalsp); buffer->getColorStrider(colorsp); buffer->getTexCoord0Strider(texcoordsp); buffer->getIndexStrider(indicesp); LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass]; for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) { LLFace* facep = *i; LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); facep->setGeomIndex(vertex_count); facep->setIndicesIndex(index_count); facep->setVertexBuffer(buffer); facep->setPoolType(LLDrawPool::POOL_ALPHA); object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp); vertex_count += facep->getGeomCount(); index_count += facep->getIndicesCount(); S32 idx = draw_vec.size()-1; BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); F32 vsize = facep->getVirtualSize(); if (idx >= 0 && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && draw_vec[idx]->mTexture == facep->getTexture() && (U16) (draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount()) <= (U32) gGLManager.mGLMaxVertexRange && //draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() < 4096 && draw_vec[idx]->mFullbright == fullbright) { draw_vec[idx]->mCount += facep->getIndicesCount(); draw_vec[idx]->mEnd += facep->getGeomCount(); draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); } else { U32 start = facep->getGeomIndex(); U32 end = start + facep->getGeomCount()-1; U32 offset = facep->getIndicesStart(); U32 count = facep->getIndicesCount(); LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), //facep->getTexture(), buffer, fullbright); info->mExtents[0] = group->mObjectExtents[0]; info->mExtents[1] = group->mObjectExtents[1]; info->mVSize = vsize; draw_vec.push_back(info); //for alpha sorting facep->setDrawInfo(info); } } buffer->flush(); mFaceList.clear(); }
void LLVOTree::updateMesh() { LLMatrix4 matrix; // Translate to tree base HACK - adjustment in Z plants tree underground const LLVector3 &pos_agent = getPositionAgent(); //gGL.translatef(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); LLMatrix4 trans_mat; trans_mat.setTranslation(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); trans_mat *= matrix; // Rotate to tree position and bend for current trunk/wind // Note that trunk stiffness controls the amount of bend at the trunk as // opposed to the crown of the tree // const F32 TRUNK_STIFF = 22.f; LLQuaternion rot = LLQuaternion(mTrunkBend.magVec()*TRUNK_STIFF*DEG_TO_RAD, LLVector4(mTrunkBend.mV[VX], mTrunkBend.mV[VY], 0)) * LLQuaternion(90.f*DEG_TO_RAD, LLVector4(0,0,1)) * getRotation(); LLMatrix4 rot_mat(rot); rot_mat *= trans_mat; F32 radius = getScale().magVec()*0.05f; LLMatrix4 scale_mat; scale_mat.mMatrix[0][0] = scale_mat.mMatrix[1][1] = scale_mat.mMatrix[2][2] = radius; scale_mat *= rot_mat; // const F32 THRESH_ANGLE_FOR_BILLBOARD = 15.f; // const F32 BLEND_RANGE_FOR_BILLBOARD = 3.f; F32 droop = mDroop + 25.f*(1.f - mTrunkBend.magVec()); S32 stop_depth = 0; F32 alpha = 1.0; U32 vert_count = 0; U32 index_count = 0; calcNumVerts(vert_count, index_count, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, mBranches); LLFace* facep = mDrawable->getFace(0); LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); buff->allocateBuffer(vert_count, index_count, TRUE); facep->setVertexBuffer(buff); LLStrider<LLVector3> vertices; LLStrider<LLVector3> normals; LLStrider<LLVector2> tex_coords; LLStrider<U16> indices; U16 idx_offset = 0; buff->getVertexStrider(vertices); buff->getNormalStrider(normals); buff->getTexCoord0Strider(tex_coords); buff->getIndexStrider(indices); genBranchPipeline(vertices, normals, tex_coords, indices, idx_offset, scale_mat, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, 1.0, mTwist, droop, mBranches, alpha); mReferenceBuffer->flush(); buff->flush(); }