From 988520f3a7d5d5e817326945d8b9c3808c4eb5f7 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 5 Mar 2010 10:50:29 -0600 Subject: Fix for avatar eyes not showing up when deferred rendering enabled. --- indra/newview/lldrawpoolavatar.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 546b60f286..012e41383f 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -157,6 +157,8 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass) { LLFastTimer t(FTM_RENDER_CHARACTERS); + sSkipTransparent = TRUE; + if (LLPipeline::sImpostorRender) { beginDeferredSkinned(); @@ -181,6 +183,8 @@ void LLDrawPoolAvatar::endDeferredPass(S32 pass) { LLFastTimer t(FTM_RENDER_CHARACTERS); + sSkipTransparent = FALSE; + if (LLPipeline::sImpostorRender) { endDeferredSkinned(); @@ -564,7 +568,6 @@ void LLDrawPoolAvatar::endSkinned() void LLDrawPoolAvatar::beginDeferredSkinned() { - sSkipTransparent = TRUE; sShaderLevel = mVertexShaderLevel; sVertexProgram = &gDeferredAvatarProgram; @@ -579,7 +582,6 @@ void LLDrawPoolAvatar::beginDeferredSkinned() void LLDrawPoolAvatar::endDeferredSkinned() { - sSkipTransparent = FALSE; // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done sRenderingSkinned = FALSE; disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); -- cgit v1.3 From 47ffcdb93d6e2ac1f9d497e43e0213c98d129254 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 6 Apr 2010 16:24:08 -0500 Subject: Rigged attachments (almost works). --- indra/llmath/llvolume.cpp | 22 +++++--- indra/llrender/llglslshader.cpp | 14 ++++- indra/llrender/llglslshader.h | 3 +- indra/llrender/llshadermgr.cpp | 8 +++ indra/newview/lldrawpoolavatar.cpp | 26 ++++++++- indra/newview/lldrawpoolavatar.h | 2 + indra/newview/llface.cpp | 18 +++++- indra/newview/llface.h | 4 +- indra/newview/llspatialpartition.h | 7 +++ indra/newview/llviewershadermgr.cpp | 25 +++++++++ indra/newview/llviewershadermgr.h | 3 + indra/newview/llvoavatar.cpp | 109 ++++++++++++++++++++++++++++++++++++ indra/newview/llvoavatar.h | 1 + indra/newview/llvovolume.cpp | 20 +++++++ 14 files changed, 247 insertions(+), 15 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index c563af592f..fdd48b9e9e 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2013,22 +2013,23 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) if (mdl[i].has("Weights")) { face.mWeights.resize(num_verts); + LLSD::Binary weights = mdl[i]["Weights"]; - LLSD::Binary::iterator iter = weights.begin(); + U32 idx = 0; U32 cur_vertex = 0; - while (iter != weights.end()) + while (idx < weights.size() && cur_vertex < num_verts) { - const S32 END_INFLUENCES = 0xFF; - U8 joint = *(iter++); + const U8 END_INFLUENCES = 0xFF; + U8 joint = weights[idx++]; U32 cur_influence = 0; while (joint != END_INFLUENCES) { - U16 influence = *(iter++); + U16 influence = weights[idx++]; influence = influence << 8; - influence |= *(iter++); + influence |= weights[idx++]; F32 w = llmin((F32) influence / 65535.f, 0.99999f); face.mWeights[cur_vertex].mV[cur_influence++] = (F32) joint + w; @@ -2039,13 +2040,18 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) } else { - joint = *(iter++); + joint = weights[idx++]; } } cur_vertex++; - iter++; } + + if (cur_vertex != num_verts || idx != weights.size()) + { + llwarns << "Vertex weight count does not match vertex count!" << llendl; + } + } LLVector3 min_pos; diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index ca92cb6580..949057df04 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -61,7 +61,7 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2) LLShaderFeatures::LLShaderFeatures() : calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false), -hasTransport(false), hasSkinning(false), hasAtmospherics(false), isSpecular(false), +hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false), hasGamma(false), hasLighting(false), calculatesAtmospherics(false) { } @@ -717,6 +717,18 @@ GLint LLGLSLShader::getUniformLocation(const string& uniform) return -1; } +GLint LLGLSLShader::getAttribLocation(U32 attrib) +{ + if (attrib < mAttribute.size()) + { + return mAttribute[attrib]; + } + else + { + return -1; + } +} + void LLGLSLShader::uniform1i(const string& uniform, GLint v) { GLint location = getUniformLocation(uniform); diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 166d4af04c..dc493ba162 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -48,6 +48,7 @@ public: bool hasWaterFog; // implies no gamma bool hasTransport; // implies no lighting (it's possible to have neither though) bool hasSkinning; + bool hasObjectSkinning; bool hasAtmospherics; bool hasGamma; @@ -109,7 +110,7 @@ public: void vertexAttrib4fv(U32 index, GLfloat* v); GLint getUniformLocation(const std::string& uniform); - + GLint getAttribLocation(U32 attrib); GLint mapUniformTextureChannel(GLint location, GLenum type); diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 1286e91e49..23b76351eb 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -152,6 +152,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) return FALSE; } } + + if (features->hasObjectSkinning) + { + if (!shader->attachObject("avatar/objectSkinV.glsl")) + { + return FALSE; + } + } /////////////////////////////////////// // Attach Fragment Shader Features Next diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 012e41383f..9311a5f60e 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -320,7 +320,7 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) S32 LLDrawPoolAvatar::getNumPasses() { - return LLPipeline::sImpostorRender ? 1 : 3; + return LLPipeline::sImpostorRender ? 1 : 4; } void LLDrawPoolAvatar::render(S32 pass) @@ -357,6 +357,8 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) break; case 2: beginSkinned(); + case 3: + beginRigged(); break; } } @@ -381,6 +383,10 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass) break; case 2: endSkinned(); + break; + case 3: + endRigged(); + break; } } @@ -566,6 +572,18 @@ void LLDrawPoolAvatar::endSkinned() gGL.getTexUnit(0)->activate(); } +void LLDrawPoolAvatar::beginRigged() +{ + gSkinnedObjectSimpleProgram.bind(); + LLVertexBuffer::sWeight4Loc = gSkinnedObjectSimpleProgram.getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); +} + +void LLDrawPoolAvatar::endRigged() +{ + gSkinnedObjectSimpleProgram.unbind(); + LLVertexBuffer::sWeight4Loc = -1; +} + void LLDrawPoolAvatar::beginDeferredSkinned() { sShaderLevel = mVertexShaderLevel; @@ -711,6 +729,12 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) avatarp->renderRigid(); return; } + + if (pass == 3) + { + avatarp->renderSkinnedAttachments(); + return; + } if (sShaderLevel > 0) { diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index b947943619..c43aa9b1e3 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -90,10 +90,12 @@ public: void beginRigid(); void beginFootShadow(); void beginSkinned(); + void beginRigged(); void endRigid(); void endFootShadow(); void endSkinned(); + void endRigged(); void beginDeferredImpostor(); void beginDeferredRigid(); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 53330e4d98..bc3e04db18 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -888,7 +888,8 @@ static LLFastTimer::DeclareTimer FTM_FACE_GET_GEOM("Face Geom"); BOOL LLFace::getGeometryVolume(const LLVolume& volume, const S32 &f, const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, - const U16 &index_offset) + const U16 &index_offset, + bool force_rebuild) { LLFastTimer t(FTM_FACE_GET_GEOM); const LLVolumeFace &vf = volume.getVolumeFace(f); @@ -925,8 +926,9 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLStrider colors; LLStrider binormals; LLStrider indicesp; + LLStrider weights; - BOOL full_rebuild = mDrawablep->isState(LLDrawable::REBUILD_VOLUME); + BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME); BOOL global_volume = mDrawablep->getVOVolume()->isVolumeGlobal(); LLVector3 scale; @@ -944,6 +946,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, 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); + bool rebuild_weights = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_WEIGHT4); const LLTextureEntry *tep = mVObjp->getTE(f); U8 bump_code = tep ? tep->getBumpmap() : 0; @@ -960,7 +963,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { mVertexBuffer->getBinormalStrider(binormals, mGeomIndex); } - + if (rebuild_weights) + { + mVertexBuffer->getWeight4Strider(weights, mGeomIndex); + } + F32 tcoord_xoffset = 0.f ; F32 tcoord_yoffset = 0.f ; F32 tcoord_xscale = 1.f ; @@ -1338,6 +1345,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, *binormals++ = binormal; } + if (rebuild_weights) + { + *weights++ = vf.mWeights[i]; + } + if (rebuild_color) { *colors++ = color; diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 67dd97e6f7..06ec043c76 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -73,6 +73,7 @@ public: HUD_RENDER = 0x0008, USE_FACE_COLOR = 0x0010, TEXTURE_ANIM = 0x0020, + RIGGED = 0x0040, }; static void initClass(); @@ -145,7 +146,8 @@ public: BOOL getGeometryVolume(const LLVolume& volume, const S32 &f, const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, - const U16 &index_offset); + const U16 &index_offset, + bool force_rebuild = false); // For avatar U16 getGeometryAvatar( diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index d74216de2d..b5e5967374 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -615,6 +615,13 @@ public: class LLVolumeGeometryManager: public LLGeometryManager { public: + typedef enum + { + NONE = 0, + BATCH_SORT, + DISTANCE_SORT + } eSortType; + virtual ~LLVolumeGeometryManager() { } virtual void rebuildGeom(LLSpatialGroup* group); virtual void rebuildMesh(LLSpatialGroup* group); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index a0d0b9d490..8a68dd6ea7 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -77,6 +77,9 @@ LLGLSLShader gObjectFullbrightShinyProgram; LLGLSLShader gObjectShinyProgram; LLGLSLShader gObjectShinyWaterProgram; +//object hardware skinning shaders +LLGLSLShader gSkinnedObjectSimpleProgram; + //environment shaders LLGLSLShader gTerrainProgram; LLGLSLShader gTerrainWaterProgram; @@ -148,6 +151,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gObjectSimpleProgram); mShaderList.push_back(&gObjectFullbrightProgram); mShaderList.push_back(&gObjectFullbrightShinyProgram); + mShaderList.push_back(&gSkinnedObjectSimpleProgram); mShaderList.push_back(&gTerrainProgram); mShaderList.push_back(&gTerrainWaterProgram); mShaderList.push_back(&gObjectSimpleWaterProgram); @@ -195,6 +199,7 @@ void LLViewerShaderMgr::initAttribsAndUniforms(void) mReservedAttribs.push_back("materialColor"); mReservedAttribs.push_back("specularColor"); mReservedAttribs.push_back("binormal"); + mReservedAttribs.push_back("object_weight"); mAvatarAttribs.reserve(5); mAvatarAttribs.push_back("weight"); @@ -548,6 +553,9 @@ void LLViewerShaderMgr::unloadShaders() gObjectShinyProgram.unload(); gObjectFullbrightShinyProgram.unload(); gObjectShinyWaterProgram.unload(); + + gSkinnedObjectSimpleProgram.unload(); + gWaterProgram.unload(); gUnderWaterProgram.unload(); gTerrainProgram.unload(); @@ -625,6 +633,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders() shaders.push_back( make_pair( "lighting/lightSpecularV.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); shaders.push_back( make_pair( "windlight/atmosphericsV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); shaders.push_back( make_pair( "avatar/avatarSkinV.glsl", 1 ) ); + shaders.push_back( make_pair( "avatar/objectSkinV.glsl", 1 ) ); // We no longer have to bind the shaders to global glhandles, they are automatically added to a map now. for (U32 i = 0; i < shaders.size(); i++) @@ -1214,6 +1223,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectSimpleWaterProgram.unload(); gObjectFullbrightProgram.unload(); gObjectFullbrightWaterProgram.unload(); + gSkinnedObjectSimpleProgram.unload(); return FALSE; } @@ -1323,6 +1333,21 @@ BOOL LLViewerShaderMgr::loadShadersObject() success = gObjectFullbrightShinyProgram.createShader(NULL, &mShinyUniforms); } + if (success) + { + gSkinnedObjectSimpleProgram.mName = "Skinned Simple Shader"; + gSkinnedObjectSimpleProgram.mFeatures.calculatesLighting = true; + gSkinnedObjectSimpleProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectSimpleProgram.mFeatures.hasGamma = true; + gSkinnedObjectSimpleProgram.mFeatures.hasAtmospherics = true; + gSkinnedObjectSimpleProgram.mFeatures.hasLighting = true; + gSkinnedObjectSimpleProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectSimpleProgram.mShaderFiles.clear(); + gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectSimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectSimpleProgram.createShader(NULL, NULL); + } if( !success ) { diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index ac2b4624e0..83a650cdbc 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -82,6 +82,7 @@ public: MATERIAL_COLOR = 0, SPECULAR_COLOR, BINORMAL, + OBJECT_WEIGHT, END_RESERVED_ATTRIBS } eGLSLReservedAttribs; @@ -313,6 +314,8 @@ extern LLGLSLShader gObjectFullbrightShinyProgram; extern LLGLSLShader gObjectShinyProgram; extern LLGLSLShader gObjectShinyWaterProgram; +extern LLGLSLShader gSkinnedObjectSimpleProgram; + //environment shaders extern LLGLSLShader gTerrainProgram; extern LLGLSLShader gTerrainWaterProgram; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index c400e8510e..535440692f 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -64,6 +64,7 @@ #include "llkeyframefallmotion.h" #include "llkeyframestandmotion.h" #include "llkeyframewalkmotion.h" +#include "llmeshrepository.h" #include "llmutelist.h" #include "llmoveview.h" #include "llquantize.h" @@ -79,6 +80,7 @@ #include "llviewermenu.h" #include "llviewerobjectlist.h" #include "llviewerparcelmgr.h" +#include "llviewershadermgr.h" #include "llviewerstats.h" #include "llvoavatarself.h" #include "llvovolume.h" @@ -3644,6 +3646,113 @@ bool LLVOAvatar::shouldAlphaMask() } +U32 LLVOAvatar::renderSkinnedAttachments() +{ + U32 num_indices = 0; + + const U32 data_mask = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_WEIGHT4; + + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + const LLViewerObject* attached_object = (*attachment_iter); + if (attached_object && !attached_object->isHUDAttachment()) + { + const LLDrawable* drawable = attached_object->mDrawable; + if (drawable) + { + for (S32 i = 0; i < drawable->getNumFaces(); ++i) + { + LLFace* face = drawable->getFace(i); + if (face->isState(LLFace::RIGGED)) + { + LLVolume* volume = attached_object->getVolume(); + const LLVolumeFace& vol_face = volume->getVolumeFace(i); + + const LLMeshSkinInfo* skin = NULL; + LLVertexBuffer* buff = face->mVertexBuffer; + + if (!buff || + !buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) || + buff->getRequestedVerts() != vol_face.mVertices.size()) + { + face->mVertexBuffer = NULL; + face->mLastVertexBuffer = NULL; + buff = NULL; + + LLUUID mesh_id = volume->getParams().getSculptID(); + if (mesh_id.notNull()) + { + skin = gMeshRepo.getSkinInfo(mesh_id); + if (skin) + { + face->mVertexBuffer = new LLVertexBuffer(data_mask, 0); + face->mVertexBuffer->allocateBuffer(vol_face.mVertices.size(), vol_face.mIndices.size(), true); + + face->setGeomIndex(0); + face->setIndicesIndex(0); + + U16 offset = 0; + + LLMatrix4 mat_vert = skin->mBindShapeMatrix; + LLMatrix3 mat_normal; + + face->getGeometryVolume(*volume, i, mat_vert, mat_normal, offset, true); + buff = face->mVertexBuffer; + } + } + } + + if (buff) + { + if (skin) + { + LLMatrix4 mat[64]; + + for (U32 i = 0; i < skin->mJointNames.size(); ++i) + { + LLJoint* joint = getJoint(skin->mJointNames[i]); + if (joint) + { + mat[i] = skin->mInvBindMatrix[i]; + mat[i] *= joint->getWorldMatrix(); + } + } + + gSkinnedObjectSimpleProgram.uniformMatrix4fv("matrixPalette", + skin->mJointNames.size(), + FALSE, + (GLfloat*) mat[0].mMatrix); + + buff->setBuffer(data_mask); + + U16 start = face->getGeomStart(); + U16 end = start + face->getGeomCount(); + S32 offset = face->getIndicesStart(); + U32 count = face->getIndicesCount(); + + buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); + } + } + } + } + } + } + } + } + + return num_indices; +} + //----------------------------------------------------------------------------- // renderSkinned() //----------------------------------------------------------------------------- diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index d5485413f4..b0535a4a26 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -339,6 +339,7 @@ public: U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0); U32 renderRigid(); U32 renderSkinned(EAvatarRenderPass pass); + U32 renderSkinnedAttachments(); U32 renderTransparent(BOOL first_pass); void renderCollisionVolumes(); static void deleteCachedImages(bool clearAll=true); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index bc83e11fd2..56fb42bb89 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3496,6 +3496,10 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) drawablep->clearState(LLDrawable::HAS_ALPHA); + bool rigged = vobj->isAttachment() && + vobj->isMesh() && + gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID()); + //for each face for (S32 i = 0; i < drawablep->getNumFaces(); i++) { @@ -3503,6 +3507,22 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) drawablep->updateFaceSize(i); LLFace* facep = drawablep->getFace(i); + if (rigged) + { + if (!facep->isState(LLFace::RIGGED)) + { + facep->mVertexBuffer = NULL; + facep->mLastVertexBuffer = NULL; + facep->setState(LLFace::RIGGED); + } + + continue; + } + else + { + facep->clearState(LLFace::RIGGED); + } + if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) { facep->mVertexBuffer = NULL; -- cgit v1.3 From b13af3b8baa05d20ae9f33046f100596182f6be0 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 9 Apr 2010 01:42:50 -0500 Subject: Tweak bias on projectors. Fix some silly shader mistakes. --- indra/newview/app_settings/settings.xml | 2 +- .../shaders/class2/deferred/sunLightF.glsl | 29 ++++------------------ .../shaders/class2/deferred/sunLightSSAOF.glsl | 16 +++++++++--- indra/newview/lldrawpoolavatar.cpp | 5 ++++ 4 files changed, 23 insertions(+), 29 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index b9647d0148..fa8dccd659 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6524,7 +6524,7 @@ Type F32 Value - -0.008 + -0.0005 RenderSpotShadowOffset diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index 4974bbef9e..46db3c990c 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -75,28 +75,10 @@ float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) //return shadow; } -float pcfSpotShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) -{ - stc.xyz /= stc.w; - stc.z += spot_shadow_bias*scl; - - float cs = shadow2DRect(shadowMap, stc.xyz).x; - float shadow = cs; - - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs); - - return shadow/5.0; - - //return shadow; -} - float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) { stc.xyz /= stc.w; - stc.z += shadow_bias*scl; + stc.z += spot_shadow_bias*scl; float cs = shadow2D(shadowMap, stc.xyz).x; float shadow = cs; @@ -107,8 +89,7 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs); shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs); shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs); - - + return shadow/5.0; //return shadow; @@ -200,15 +181,15 @@ void main() gl_FragColor[0] = shadow; gl_FragColor[1] = 1.0; - spos.xyz = shadow_pos*offset*spot_shadow_offset; + spos.xyz = shadow_pos+offset*spot_shadow_offset; //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; - gl_FragColor[2] = pcfSpotShadow(shadowMap4, lpos, 0.8).x; + gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8); //spotlight shadow 2 lpos = shadow_matrix[5]*spos; - gl_FragColor[3] = pcfSpotShadow(shadowMap5, lpos, 0.8).x; + gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8); //gl_FragColor.rgb = pos.xyz; //gl_FragColor.b = shadow; diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl index d77d17942a..a0dfc96f14 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl @@ -40,6 +40,9 @@ uniform vec2 proj_shadow_res; uniform float shadow_bias; uniform float shadow_offset; +uniform float spot_shadow_bias; +uniform float spot_shadow_offset; + vec4 getPosition(vec2 pos_screen) { float depth = texture2DRect(depthMap, pos_screen.xy).a; @@ -134,7 +137,7 @@ float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) { stc.xyz /= stc.w; - stc.z += shadow_bias*scl; + stc.z += spot_shadow_bias*scl; float cs = shadow2D(shadowMap, stc.xyz).x; float shadow = cs; @@ -173,7 +176,10 @@ void main() float shadow = 1.0; float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); - vec4 spos = vec4(pos.xyz + displace*norm + vary_light.xyz * (1.0-dp_directional_light)*shadow_offset, 1.0); + vec3 shadow_pos = pos.xyz + displace*norm; + vec3 offset = vary_light.xyz * (1.0-dp_directional_light); + + vec4 spos = vec4(shadow_pos+offset*shadow_offset, 1.0); if (spos.z > -shadow_clip.w) { @@ -235,13 +241,15 @@ void main() gl_FragColor[0] = shadow; gl_FragColor[1] = calcAmbientOcclusion(pos, norm); + spos.xyz = shadow_pos+offset*spot_shadow_offset; + //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; - gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8).x; + gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8); //spotlight shadow 2 lpos = shadow_matrix[5]*spos; - gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8).x; + gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8); //gl_FragColor.rgb = pos.xyz; //gl_FragColor.b = shadow; diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 9311a5f60e..23211d7090 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -314,6 +314,11 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) return; } + if (sShaderLevel > 0) + { + gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX]; + } + avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); } -- cgit v1.3 From fb04904336b77b480f2ebd6bf9219f85c356d36f Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 12 Apr 2010 11:11:23 -0500 Subject: Fix for avatars not rendering in non-deferred mode. --- indra/newview/lldrawpoolavatar.cpp | 5 ++++- indra/newview/llvoavatar.cpp | 22 +++++++++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 9311a5f60e..a07be30565 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -320,7 +320,7 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) S32 LLDrawPoolAvatar::getNumPasses() { - return LLPipeline::sImpostorRender ? 1 : 4; + return LLPipeline::sImpostorRender ? 1 : 3; } void LLDrawPoolAvatar::render(S32 pass) @@ -357,6 +357,7 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) break; case 2: beginSkinned(); + break; case 3: beginRigged(); break; @@ -574,12 +575,14 @@ void LLDrawPoolAvatar::endSkinned() void LLDrawPoolAvatar::beginRigged() { + sVertexProgram = NULL; gSkinnedObjectSimpleProgram.bind(); LLVertexBuffer::sWeight4Loc = gSkinnedObjectSimpleProgram.getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } void LLDrawPoolAvatar::endRigged() { + sVertexProgram = NULL; gSkinnedObjectSimpleProgram.unbind(); LLVertexBuffer::sWeight4Loc = -1; } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 6c2eb37971..201c4ce1d5 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -3645,7 +3645,8 @@ U32 LLVOAvatar::renderSkinnedAttachments() const U32 data_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_WEIGHT4; for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); @@ -3669,10 +3670,16 @@ U32 LLVOAvatar::renderSkinnedAttachments() if (face->isState(LLFace::RIGGED)) { LLVolume* volume = attached_object->getVolume(); + if (!volume || volume->getNumVolumeFaces() <= i) + { + continue; + } + const LLVolumeFace& vol_face = volume->getVolumeFace(i); const LLMeshSkinInfo* skin = NULL; LLVertexBuffer* buff = face->mVertexBuffer; + LLUUID mesh_id = volume->getParams().getSculptID();; if (!buff || !buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) || @@ -3682,7 +3689,6 @@ U32 LLVOAvatar::renderSkinnedAttachments() face->mLastVertexBuffer = NULL; buff = NULL; - LLUUID mesh_id = volume->getParams().getSculptID(); if (mesh_id.notNull()) { skin = gMeshRepo.getSkinInfo(mesh_id); @@ -3693,7 +3699,8 @@ U32 LLVOAvatar::renderSkinnedAttachments() face->setGeomIndex(0); face->setIndicesIndex(0); - + face->setSize(vol_face.mVertices.size(), vol_face.mIndices.size()); + U16 offset = 0; LLMatrix4 mat_vert = skin->mBindShapeMatrix; @@ -3705,8 +3712,13 @@ U32 LLVOAvatar::renderSkinnedAttachments() } } - if (buff) + if (buff && mesh_id.notNull()) { + if (!skin) + { + skin = gMeshRepo.getSkinInfo(mesh_id); + } + if (skin) { LLMatrix4 mat[64]; @@ -3729,7 +3741,7 @@ U32 LLVOAvatar::renderSkinnedAttachments() buff->setBuffer(data_mask); U16 start = face->getGeomStart(); - U16 end = start + face->getGeomCount(); + U16 end = start + face->getGeomCount()-1; S32 offset = face->getIndicesStart(); U32 count = face->getIndicesCount(); -- cgit v1.3 From 6b72149cf7ad90c0036d9b037594b0a8e86dc483 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 12 Apr 2010 23:15:42 -0500 Subject: Tracking down ATI deferred bugs WIP --- indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl | 4 ++-- indra/newview/lldrawpoolavatar.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl index 00083eb6b3..085ffddeec 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl @@ -10,7 +10,7 @@ uniform sampler2D diffuseMap; void main() { - gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy).a); - //gl_FragColor = vec4(1,1,1,1); + //gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy).a); + gl_FragColor = vec4(1,1,1,1); } diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 23211d7090..5a67e1753a 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -254,7 +254,7 @@ S32 LLDrawPoolAvatar::getNumShadowPasses() void LLDrawPoolAvatar::beginShadowPass(S32 pass) { LLFastTimer t(FTM_SHADOW_AVATAR); - + sSkipTransparent = TRUE; sVertexProgram = &gDeferredAvatarShadowProgram; if (sShaderLevel > 0) { @@ -276,7 +276,7 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass) void LLDrawPoolAvatar::endShadowPass(S32 pass) { LLFastTimer t(FTM_SHADOW_AVATAR); - + sSkipTransparent = FALSE; if (sShaderLevel > 0) { sRenderingSkinned = FALSE; -- cgit v1.3 From d3d180f5db0350d6a8b930227b17d5001e673295 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 14 Apr 2010 16:18:13 -0500 Subject: Hack to fix ATI depth shadows screwing up alpha masking. --- indra/newview/lldrawpoolavatar.cpp | 2 -- indra/newview/pipeline.cpp | 9 +++++---- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 588a77a620..2cd9fef9f5 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -254,7 +254,6 @@ S32 LLDrawPoolAvatar::getNumShadowPasses() void LLDrawPoolAvatar::beginShadowPass(S32 pass) { LLFastTimer t(FTM_SHADOW_AVATAR); - sSkipTransparent = TRUE; sVertexProgram = &gDeferredAvatarShadowProgram; if (sShaderLevel > 0) { @@ -276,7 +275,6 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass) void LLDrawPoolAvatar::endShadowPass(S32 pass) { LLFastTimer t(FTM_SHADOW_AVATAR); - sSkipTransparent = FALSE; if (sShaderLevel > 0) { sRenderingSkinned = FALSE; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index bd210b3376..02dc013ca4 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -572,9 +572,12 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) F32 scale = gSavedSettings.getF32("RenderShadowResolutionScale"); + //HACK: make alpha masking work on ATI depth shadows (work around for ATI driver bug) + U32 shadow_fmt = gGLManager.mIsATI ? GL_ALPHA : 0; + for (U32 i = 0; i < 4; i++) { - mShadow[i].allocate(U32(resX*scale),U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + mShadow[i].allocate(U32(resX*scale),U32(resY*scale), shadow_fmt, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE); } @@ -583,11 +586,9 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) for (U32 i = 4; i < 6; i++) { - mShadow[i].allocate(width, height, 0, TRUE, FALSE); + mShadow[i].allocate(width, height, shadow_fmt, TRUE, FALSE); } - - width = nhpo2(resX)/2; height = nhpo2(resY)/2; mLuminanceMap.allocate(width,height, GL_RGBA, FALSE, FALSE); -- cgit v1.3 From 54dd30cc426e16aa99b4f7eea080bbeae0656843 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 15 Apr 2010 00:04:17 -0500 Subject: More rigged attachments work. --- indra/llrender/llshadermgr.cpp | 33 +++++++++++++++++++++------------ indra/llrender/llvertexbuffer.cpp | 21 +++++++++++++++++++++ indra/newview/lldrawpoolavatar.cpp | 3 ++- indra/newview/llvoavatar.cpp | 12 +++++++++--- 4 files changed, 53 insertions(+), 16 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 23b76351eb..8fc7163b83 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -322,10 +322,13 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns) GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type) { GLenum error; - error = glGetError(); - if (error != GL_NO_ERROR) + if (gDebugGL) { - LL_WARNS("ShaderLoading") << "GL ERROR entering loadShaderFile(): " << error << LL_ENDL; + error = glGetError(); + if (error != GL_NO_ERROR) + { + LL_WARNS("ShaderLoading") << "GL ERROR entering loadShaderFile(): " << error << LL_ENDL; + } } LL_DEBUGS("ShaderLoading") << "Loading shader file: " << filename << " class " << shader_level << LL_ENDL; @@ -380,10 +383,13 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade //create shader object GLhandleARB ret = glCreateShaderObjectARB(type); - error = glGetError(); - if (error != GL_NO_ERROR) + if (gDebugGL) { - LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShaderObjectARB: " << error << LL_ENDL; + error = glGetError(); + if (error != GL_NO_ERROR) + { + LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShaderObjectARB: " << error << LL_ENDL; + } } else { @@ -415,13 +421,16 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade //check for errors GLint success = GL_TRUE; glGetObjectParameterivARB(ret, GL_OBJECT_COMPILE_STATUS_ARB, &success); - error = glGetError(); - if (error != GL_NO_ERROR || success == GL_FALSE) + if (gDebugGL) { - //an error occured, print log - LL_WARNS("ShaderLoading") << "GLSL Compilation Error: (" << error << ") in " << filename << LL_ENDL; - dumpObjectLog(ret); - ret = 0; + error = glGetError(); + if (error != GL_NO_ERROR || success == GL_FALSE) + { + //an error occured, print log + LL_WARNS("ShaderLoading") << "GLSL Compilation Error: (" << error << ") in " << filename << LL_ENDL; + dumpObjectLog(ret); + ret = 0; + } } } else diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index d5b00f27a7..668e9e55f9 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -212,6 +212,27 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) glClientActiveTextureARB(GL_TEXTURE0_ARB); } + if (sLastMask & MAP_WEIGHT4) + { + if (sWeight4Loc < 0) + { + llerrs << "Weighting disabled but vertex buffer still bound!" << llendl; + } + + if (!(data_mask & MAP_WEIGHT4)) + { //disable 4-component skin weight + glDisableVertexAttribArrayARB(sWeight4Loc); + } + } + else if (data_mask & MAP_WEIGHT4) + { + if (sWeight4Loc >= 0) + { //enable 4-component skin weight + glEnableVertexAttribArrayARB(sWeight4Loc); + } + } + + sLastMask = data_mask; } } diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index de9b71a9b8..1a2558ac5f 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -325,7 +325,7 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) S32 LLDrawPoolAvatar::getNumPasses() { - return LLPipeline::sImpostorRender ? 1 : 3; + return LLPipeline::sImpostorRender ? 1 : 4; } void LLDrawPoolAvatar::render(S32 pass) @@ -588,6 +588,7 @@ void LLDrawPoolAvatar::beginRigged() void LLDrawPoolAvatar::endRigged() { sVertexProgram = NULL; + LLVertexBuffer::unbind(); gSkinnedObjectSimpleProgram.unbind(); LLVertexBuffer::sWeight4Loc = -1; } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 201c4ce1d5..8bf4c0ab96 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -3728,8 +3728,8 @@ U32 LLVOAvatar::renderSkinnedAttachments() LLJoint* joint = getJoint(skin->mJointNames[i]); if (joint) { - mat[i] = skin->mInvBindMatrix[i]; - mat[i] *= joint->getWorldMatrix(); + mat[i*2+0] = skin->mInvBindMatrix[i]; + mat[i*2+1] = joint->getWorldMatrix(); } } @@ -3737,6 +3737,10 @@ U32 LLVOAvatar::renderSkinnedAttachments() skin->mJointNames.size(), FALSE, (GLfloat*) mat[0].mMatrix); + gSkinnedObjectSimpleProgram.uniformMatrix4fv("matrixPalette[0]", + skin->mJointNames.size(), + FALSE, + (GLfloat*) mat[0].mMatrix); buff->setBuffer(data_mask); @@ -3745,7 +3749,9 @@ U32 LLVOAvatar::renderSkinnedAttachments() S32 offset = face->getIndicesStart(); U32 count = face->getIndicesCount(); - buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); + glPointSize(8.f); + buff->drawRange(LLRender::POINTS, start, end, count, offset); + glPointSize(1.f); } } } -- cgit v1.3 From 71b0a63c8df29d5d69b777306dcf6280fd98886a Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 16 Apr 2010 13:00:01 -0500 Subject: Optimize LLViewerJointMesh::updateFaceData --- indra/llcommon/llstrider.h | 2 +- indra/newview/lldrawpoolavatar.cpp | 2 +- indra/newview/llviewerjointmesh.cpp | 88 +++++++++++++++++++++++++++++-------- 3 files changed, 71 insertions(+), 21 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/llcommon/llstrider.h b/indra/llcommon/llstrider.h index 369b06b48a..44ea80a36b 100644 --- a/indra/llcommon/llstrider.h +++ b/indra/llcommon/llstrider.h @@ -51,7 +51,7 @@ public: void setStride (S32 skipBytes) { mSkip = (skipBytes ? skipBytes : sizeof(Object));} void skip(const U32 index) { mBytep += mSkip*index;} - + U32 getSkip() const { return mSkip; } Object* get() { return mObjectp; } Object* operator->() { return mObjectp; } Object& operator *() { return *mObjectp; } diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 7ab85ae3e4..b509b363b7 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -123,7 +123,7 @@ void LLDrawPoolAvatar::prerender() if (sShaderLevel > 0) { - sBufferUsage = GL_STATIC_DRAW_ARB; + sBufferUsage = GL_DYNAMIC_DRAW_ARB; } else { diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 92029d10f6..90a5a29bb4 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -661,6 +661,8 @@ void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 //----------------------------------------------------------------------------- // updateFaceData() //----------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_AVATAR_FACE("Avatar Face"); + void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind) { mFace = face; @@ -670,6 +672,8 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w return; } + LLFastTimer t(FTM_AVATAR_FACE); + LLStrider verticesp; LLStrider normalsp; LLStrider tex_coordsp; @@ -688,30 +692,76 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w face->mVertexBuffer->getIndexStrider(indicesp); stop_glerror(); - for (U16 i = 0; i < mMesh->getNumVertices(); i++) + verticesp += mMesh->mFaceVertexOffset; + tex_coordsp += mMesh->mFaceVertexOffset; + normalsp += mMesh->mFaceVertexOffset; + vertex_weightsp += mMesh->mFaceVertexOffset; + clothing_weightsp += mMesh->mFaceVertexOffset; + + U32* __restrict v = (U32*) verticesp.get(); + const U32 vert_skip = verticesp.getSkip()/sizeof(U32); + + U32* __restrict tc = (U32*) tex_coordsp.get(); + const U32 tc_skip = tex_coordsp.getSkip()/sizeof(U32); + + U32* __restrict n = (U32*) normalsp.get(); + const U32 n_skip = normalsp.getSkip()/sizeof(U32); + + U32* __restrict vw = (U32*) vertex_weightsp.get(); + const U32 vw_skip = vertex_weightsp.getSkip()/sizeof(U32); + + + U32* __restrict cw = (U32*) clothing_weightsp.get(); + const U32 cw_skip = vertex_weightsp.getSkip()/sizeof(U32); + + 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; + do { - verticesp[mMesh->mFaceVertexOffset + i] = *(mMesh->getCoords() + i); - tex_coordsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getTexCoords() + i); - normalsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getNormals() + i); - vertex_weightsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getWeights() + i); - if (damp_wind) - { - clothing_weightsp[mMesh->mFaceVertexOffset + i] = LLVector4(0,0,0,0); - } - else - { - clothing_weightsp[mMesh->mFaceVertexOffset + i] = (*(mMesh->getClothingWeights() + i)); - } + v[0] = *(coords++); + v[1] = *(coords++); + v[2] = *(coords++); + v += vert_skip; + + tc[0] = *(tex_coords++); + tc[1] = *(tex_coords++); + tc += tc_skip; + + n[0] = *(normals++); + n[1] = *(normals++); + n[2] = *(normals++); + n += n_skip; + + vw[0] = *(weights++); + vw += vw_skip; + + cw[0] = *(cloth_weights++); + cw[1] = *(cloth_weights++); + cw[2] = *(cloth_weights++); + cw[3] = *(cloth_weights++); + cw += cw_skip; } + while (++i < num_verts); + + const U32 idx_count = mMesh->getNumFaces()*3; - for (S32 i = 0; i < mMesh->getNumFaces(); i++) + U16* __restrict idx = indicesp.get(); + S32* __restrict src_idx = (S32*) mMesh->getFaces(); + + i = 0; + + do { - for (U32 j = 0; j < 3; j++) - { - U32 k = i*3+j+mMesh->mFaceIndexOffset; - indicesp[k] = mMesh->getFaces()[i][j] + mMesh->mFaceVertexOffset; - } + *(idx++) = *(src_idx++); } + while (++i < idx_count); } } } -- cgit v1.3 From 12499cebcba81175ae5d92926f5ec89632f00926 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 16 Apr 2010 15:53:26 -0500 Subject: Fix for busted optimizations. --- indra/newview/lldrawpoolavatar.cpp | 4 +--- indra/newview/llviewerjointmesh.cpp | 6 +++++- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index b509b363b7..b3942d559a 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -881,9 +881,7 @@ LLColor3 LLDrawPoolAvatar::getDebugColor() const LLVertexBufferAvatar::LLVertexBufferAvatar() : LLVertexBuffer(sDataMask, - LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0 ? - GL_DYNAMIC_DRAW_ARB : - GL_STREAM_DRAW_ARB) + GL_STREAM_DRAW_ARB) //avatars are always stream draw due to morph targets { } diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 90a5a29bb4..db2279d925 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -752,14 +752,18 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w 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++); + *(idx++) = *(src_idx++)+offset; } while (++i < idx_count); } -- cgit v1.3 From 1651dd9c5b98923716a80ea476ec47360748f343 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 19 Apr 2010 23:32:27 -0500 Subject: Remove foot shadows, renaming foot shadow pass to impostor pass. --- indra/newview/lldrawpoolavatar.cpp | 12 ++++-------- indra/newview/lldrawpoolavatar.h | 4 ++-- 2 files changed, 6 insertions(+), 10 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index b3942d559a..c4581b2c78 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -353,7 +353,7 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) switch (pass) { case 0: - beginFootShadow(); + beginImpostor(); break; case 1: beginRigid(); @@ -380,7 +380,7 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass) switch (pass) { case 0: - endFootShadow(); + endImpostor(); break; case 1: endRigid(); @@ -394,7 +394,7 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass) } } -void LLDrawPoolAvatar::beginFootShadow() +void LLDrawPoolAvatar::beginImpostor() { if (!LLPipeline::sReflectionRender) { @@ -406,7 +406,7 @@ void LLDrawPoolAvatar::beginFootShadow() diffuse_channel = 0; } -void LLDrawPoolAvatar::endFootShadow() +void LLDrawPoolAvatar::endImpostor() { gPipeline.enableLightsDynamic(); } @@ -718,10 +718,6 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) } avatarp->renderImpostor(LLColor4U(255,255,255,255), diffuse_channel); } - else if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS) && !LLPipeline::sRenderDeferred) - { - avatarp->renderFootShadows(); - } return; } diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index c43aa9b1e3..45f694ccd9 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -88,12 +88,12 @@ public: /*virtual*/ void renderShadow(S32 pass); void beginRigid(); - void beginFootShadow(); + void beginImpostor(); void beginSkinned(); void beginRigged(); void endRigid(); - void endFootShadow(); + void endImpostor(); void endSkinned(); void endRigged(); -- cgit v1.3 From bf8bcfe4f76f1805a908af0368e334261b764591 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 22 Apr 2010 00:14:06 -0500 Subject: Deferred shading for rigged attachments. --- indra/newview/lldrawpoolavatar.cpp | 98 +++++++++++++++++++++++++++---------- indra/newview/lldrawpoolavatar.h | 4 ++ indra/newview/llviewershadermgr.cpp | 27 ++++++++++ indra/newview/llviewershadermgr.h | 2 + indra/newview/llvoavatar.cpp | 4 +- 5 files changed, 106 insertions(+), 29 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index c4581b2c78..4b7de97101 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -53,8 +53,9 @@ static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK; static U32 sBufferUsage = GL_STREAM_DRAW_ARB; static U32 sShaderLevel = 0; -static LLGLSLShader* sVertexProgram = NULL; + +LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL; BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE; BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE; @@ -176,6 +177,9 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass) case 2: beginDeferredSkinned(); break; + case 3: + beginDeferredRigged(); + break; } } @@ -202,6 +206,8 @@ void LLDrawPoolAvatar::endDeferredPass(S32 pass) case 2: endDeferredSkinned(); break; + case 3: + endDeferredRigged(); } } @@ -248,41 +254,58 @@ void LLDrawPoolAvatar::renderPostDeferred(S32 pass) S32 LLDrawPoolAvatar::getNumShadowPasses() { - return 1; + return 2; } void LLDrawPoolAvatar::beginShadowPass(S32 pass) { LLFastTimer t(FTM_SHADOW_AVATAR); - sVertexProgram = &gDeferredAvatarShadowProgram; - if (sShaderLevel > 0) + + if (pass == 0) { - gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX]; - } - gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.2f); - - glColor4f(1,1,1,1); + sVertexProgram = &gDeferredAvatarShadowProgram; + if (sShaderLevel > 0) + { + gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX]; + } + gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.2f); + + glColor4f(1,1,1,1); - if ((sShaderLevel > 0)) // for hardware blending + if ((sShaderLevel > 0)) // for hardware blending + { + sRenderingSkinned = TRUE; + sVertexProgram->bind(); + enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + } + } + else { - sRenderingSkinned = TRUE; + sVertexProgram = &gDeferredAttachmentShadowProgram; sVertexProgram->bind(); - enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } - } void LLDrawPoolAvatar::endShadowPass(S32 pass) { LLFastTimer t(FTM_SHADOW_AVATAR); - if (sShaderLevel > 0) + if (pass == 0) { - sRenderingSkinned = FALSE; + if (sShaderLevel > 0) + { + sRenderingSkinned = FALSE; + sVertexProgram->unbind(); + disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + } + } + else + { + LLVertexBuffer::unbind(); sVertexProgram->unbind(); - disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + LLVertexBuffer::sWeight4Loc = -1; + sVertexProgram = NULL; } - - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } void LLDrawPoolAvatar::renderShadow(S32 pass) @@ -312,13 +335,19 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) return; } - if (sShaderLevel > 0) + if (pass == 0) { - gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX]; - } - - avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); + if (sShaderLevel > 0) + { + gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX]; + } + avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); + } + else + { + avatarp->renderSkinnedAttachments(); + } } S32 LLDrawPoolAvatar::getNumPasses() @@ -578,7 +607,7 @@ void LLDrawPoolAvatar::endSkinned() void LLDrawPoolAvatar::beginRigged() { - sVertexProgram = NULL; + sVertexProgram = &gSkinnedObjectSimpleProgram; gSkinnedObjectSimpleProgram.bind(); LLVertexBuffer::sWeight4Loc = gSkinnedObjectSimpleProgram.getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -591,6 +620,21 @@ void LLDrawPoolAvatar::endRigged() LLVertexBuffer::sWeight4Loc = -1; } +void LLDrawPoolAvatar::beginDeferredRigged() +{ + sVertexProgram = &gDeferredSkinnedDiffuseProgram; + sVertexProgram->bind(); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); +} + +void LLDrawPoolAvatar::endDeferredRigged() +{ + LLVertexBuffer::unbind(); + sVertexProgram->unbind(); + LLVertexBuffer::sWeight4Loc = -1; + sVertexProgram = NULL; +} + void LLDrawPoolAvatar::beginDeferredSkinned() { sShaderLevel = mVertexShaderLevel; @@ -893,16 +937,16 @@ void LLVertexBufferAvatar::setupVertexBuffer(U32 data_mask) const glNormalPointer(GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_NORMAL])); glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD0])); - set_vertex_weights(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT], mStride, (F32*)(base + mOffsets[TYPE_WEIGHT])); + set_vertex_weights(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT], mStride, (F32*)(base + mOffsets[TYPE_WEIGHT])); if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_BUMP) { - set_binormals(sVertexProgram->mAttribute[LLViewerShaderMgr::BINORMAL], mStride, (LLVector3*)(base + mOffsets[TYPE_BINORMAL])); + set_binormals(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::BINORMAL], mStride, (LLVector3*)(base + mOffsets[TYPE_BINORMAL])); } if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH) { - set_vertex_clothing_weights(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_CLOTHING], mStride, (LLVector4*)(base + mOffsets[TYPE_CLOTHWEIGHT])); + set_vertex_clothing_weights(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_CLOTHING], mStride, (LLVector4*)(base + mOffsets[TYPE_CLOTHWEIGHT])); } } else diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 45f694ccd9..b42cc54622 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -36,6 +36,7 @@ #include "lldrawpool.h" class LLVOAvatar; +class LLGLSLShader; class LLDrawPoolAvatar : public LLFacePool { @@ -100,10 +101,12 @@ public: void beginDeferredImpostor(); void beginDeferredRigid(); void beginDeferredSkinned(); + void beginDeferredRigged(); void endDeferredImpostor(); void endDeferredRigid(); void endDeferredSkinned(); + void endDeferredRigged(); /*virtual*/ LLViewerTexture *getDebugTexture(); /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display @@ -112,6 +115,7 @@ public: static BOOL sSkipOpaque; static BOOL sSkipTransparent; + static LLGLSLShader* sVertexProgram; }; class LLVertexBufferAvatar : public LLVertexBuffer diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 8a68dd6ea7..d978e856a6 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -110,6 +110,7 @@ LLGLSLShader gDeferredImpostorProgram; LLGLSLShader gDeferredEdgeProgram; LLGLSLShader gDeferredWaterProgram; LLGLSLShader gDeferredDiffuseProgram; +LLGLSLShader gDeferredSkinnedDiffuseProgram; LLGLSLShader gDeferredBumpProgram; LLGLSLShader gDeferredTerrainProgram; LLGLSLShader gDeferredTreeProgram; @@ -124,6 +125,7 @@ LLGLSLShader gDeferredBlurLightProgram; LLGLSLShader gDeferredSoftenProgram; LLGLSLShader gDeferredShadowProgram; LLGLSLShader gDeferredAvatarShadowProgram; +LLGLSLShader gDeferredAttachmentShadowProgram; LLGLSLShader gDeferredAlphaProgram; LLGLSLShader gDeferredFullbrightProgram; LLGLSLShader gDeferredGIProgram; @@ -575,6 +577,7 @@ void LLViewerShaderMgr::unloadShaders() gPostNightVisionProgram.unload(); gDeferredDiffuseProgram.unload(); + gDeferredSkinnedDiffuseProgram.unload(); mVertexShaderLevel[SHADER_LIGHTING] = 0; mVertexShaderLevel[SHADER_OBJECT] = 0; @@ -889,6 +892,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredTreeProgram.unload(); gDeferredDiffuseProgram.unload(); + gDeferredSkinnedDiffuseProgram.unload(); gDeferredBumpProgram.unload(); gDeferredImpostorProgram.unload(); gDeferredTerrainProgram.unload(); @@ -901,6 +905,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSoftenProgram.unload(); gDeferredShadowProgram.unload(); gDeferredAvatarShadowProgram.unload(); + gDeferredAttachmentShadowProgram.unload(); gDeferredAvatarProgram.unload(); gDeferredAvatarAlphaProgram.unload(); gDeferredAlphaProgram.unload(); @@ -929,6 +934,17 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredDiffuseProgram.createShader(NULL, NULL); } + if (success) + { + gDeferredSkinnedDiffuseProgram.mName = "Deferred Skinned Diffuse Shader"; + gDeferredSkinnedDiffuseProgram.mFeatures.hasObjectSkinning = true; + gDeferredSkinnedDiffuseProgram.mShaderFiles.clear(); + gDeferredSkinnedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSkinnedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSkinnedDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredSkinnedDiffuseProgram.createShader(NULL, NULL); + } + if (success) { gDeferredBumpProgram.mName = "Deferred Bump Shader"; @@ -1104,6 +1120,17 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredAvatarShadowProgram.createShader(&mAvatarAttribs, &mAvatarUniforms); } + if (success) + { + gDeferredAttachmentShadowProgram.mName = "Deferred Attachment Shadow Shader"; + gDeferredAttachmentShadowProgram.mFeatures.hasObjectSkinning = true; + gDeferredAttachmentShadowProgram.mShaderFiles.clear(); + gDeferredAttachmentShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentShadowV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredAttachmentShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentShadowF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAttachmentShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredAttachmentShadowProgram.createShader(NULL, NULL); + } + if (success) { gTerrainProgram.mName = "Deferred Terrain Shader"; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 83a650cdbc..b279a59777 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -346,6 +346,7 @@ extern LLGLSLShader gDeferredImpostorProgram; extern LLGLSLShader gDeferredEdgeProgram; extern LLGLSLShader gDeferredWaterProgram; extern LLGLSLShader gDeferredDiffuseProgram; +extern LLGLSLShader gDeferredSkinnedDiffuseProgram; extern LLGLSLShader gDeferredBumpProgram; extern LLGLSLShader gDeferredTerrainProgram; extern LLGLSLShader gDeferredTreeProgram; @@ -363,6 +364,7 @@ extern LLGLSLShader gDeferredShadowProgram; extern LLGLSLShader gDeferredPostGIProgram; extern LLGLSLShader gDeferredPostProgram; extern LLGLSLShader gDeferredAvatarShadowProgram; +extern LLGLSLShader gDeferredAttachmentShadowProgram; extern LLGLSLShader gDeferredAlphaProgram; extern LLGLSLShader gDeferredFullbrightProgram; extern LLGLSLShader gDeferredAvatarAlphaProgram; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index e2650d22b0..7cdbebf4d1 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -3742,11 +3742,11 @@ U32 LLVOAvatar::renderSkinnedAttachments() } } - gSkinnedObjectSimpleProgram.uniformMatrix4fv("matrixPalette", + LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv("matrixPalette", skin->mJointNames.size(), FALSE, (GLfloat*) mat[0].mMatrix); - gSkinnedObjectSimpleProgram.uniformMatrix4fv("matrixPalette[0]", + LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv("matrixPalette[0]", skin->mJointNames.size(), FALSE, (GLfloat*) mat[0].mMatrix); -- cgit v1.3 From 5715a9269b66de59ee59637fbb09e9430bfb244f Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 22 Apr 2010 23:16:39 -0500 Subject: Fix for broken shader loading behavior when Debug GL enabled. --- indra/llrender/llshadermgr.cpp | 29 +++++++++++++++++------------ indra/newview/lldrawpoolavatar.cpp | 13 ++++++++++++- 2 files changed, 29 insertions(+), 13 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 8fc7163b83..17fc7fe120 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -391,26 +391,31 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShaderObjectARB: " << error << LL_ENDL; } } - else + + //load source + glShaderSourceARB(ret, count, (const GLcharARB**) text, NULL); + + if (gDebugGL) { - //load source - glShaderSourceARB(ret, count, (const GLcharARB**) text, NULL); error = glGetError(); if (error != GL_NO_ERROR) { LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSourceARB: " << error << LL_ENDL; } - else + } + + //compile source + glCompileShaderARB(ret); + + if (gDebugGL) + { + error = glGetError(); + if (error != GL_NO_ERROR) { - //compile source - glCompileShaderARB(ret); - error = glGetError(); - if (error != GL_NO_ERROR) - { - LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShaderARB: " << error << LL_ENDL; - } + LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShaderARB: " << error << LL_ENDL; } } + //free memory for (GLuint i = 0; i < count; i++) { @@ -421,7 +426,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade //check for errors GLint success = GL_TRUE; glGetObjectParameterivARB(ret, GL_OBJECT_COMPILE_STATUS_ARB, &success); - if (gDebugGL) + if (gDebugGL || success == GL_FALSE) { error = glGetError(); if (error != GL_NO_ERROR || success == GL_FALSE) diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 4b7de97101..62226383a4 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -352,7 +352,18 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) S32 LLDrawPoolAvatar::getNumPasses() { - return LLPipeline::sImpostorRender ? 1 : 4; + if (LLPipeline::sImpostorRender) + { + return 1; + } + else if (getVertexShaderLevel() > 0) + { + return 4; + } + else + { + return 3; + } } void LLDrawPoolAvatar::render(S32 pass) -- cgit v1.3 From f324787a70b8fccc7a8ea202805bf726fba765a7 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Sat, 1 May 2010 00:45:44 -0500 Subject: Rigged attachment integration WIP. --- indra/llrender/llglslshader.cpp | 2 +- .../shaders/class1/deferred/diffuseV.glsl | 2 +- indra/newview/lldrawpool.cpp | 5 - indra/newview/lldrawpool.h | 2 - indra/newview/lldrawpoolavatar.cpp | 244 ++++++++++++++++++++- indra/newview/lldrawpoolavatar.h | 42 +++- indra/newview/lldrawpoolbump.cpp | 54 +++-- indra/newview/lldrawpoolbump.h | 4 + indra/newview/llface.cpp | 5 + indra/newview/llface.h | 1 + indra/newview/llviewerobject.cpp | 19 ++ indra/newview/llviewerobject.h | 1 + indra/newview/llviewershadermgr.cpp | 27 ++- indra/newview/llviewershadermgr.h | 1 + indra/newview/llvoavatar.cpp | 99 +-------- indra/newview/llvovolume.cpp | 66 +++++- 16 files changed, 440 insertions(+), 134 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 949057df04..9256e3959c 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -124,7 +124,7 @@ BOOL LLGLSLShader::createShader(vector * attributes, { GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second); LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL; - if (mShaderLevel > 0) + if (shaderhandle > 0) { attachObject(shaderhandle); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl index 44468cdfa2..b458842657 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl @@ -13,7 +13,7 @@ void main() gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - vary_normal = normalize(gl_NormalMatrix * gl_Normal); + vary_nomral = normalize(gl_NormalMatrix * gl_Normal); gl_FrontColor = gl_Color; } diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index ae30af3647..a99b80d618 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -248,11 +248,6 @@ void LLFacePool::dirtyTextures(const std::set& textures { } -BOOL LLFacePool::moveFace(LLFace *face, LLDrawPool *poolp, BOOL copy_data) -{ - return TRUE; -} - // static S32 LLFacePool::drawLoop(face_array_t& face_list) { diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index 67870c10e9..e46d503db3 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -187,8 +187,6 @@ public: virtual void resetDrawOrders(); void resetAll(); - BOOL moveFace(LLFace *face, LLDrawPool *poolp, BOOL copy_data = FALSE); - void destroy(); void buildEdges(); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 62226383a4..02c7e3bb6f 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -39,13 +39,17 @@ #include "m3math.h" #include "lldrawable.h" +#include "lldrawpoolbump.h" #include "llface.h" +#include "llmeshrepository.h" #include "llsky.h" #include "llviewercamera.h" #include "llviewerregion.h" #include "noise.h" #include "pipeline.h" #include "llviewershadermgr.h" +#include "llvovolume.h" +#include "llvolume.h" #include "llappviewer.h" #include "llrendersphere.h" #include "llviewerpartsim.h" @@ -94,6 +98,8 @@ static BOOL sRenderingSkinned = FALSE; S32 normal_channel = -1; S32 specular_channel = -1; S32 diffuse_channel = -1; +S32 cube_channel = -1; + static LLFastTimer::DeclareTimer FTM_SHADOW_AVATAR("Avatar Shadow"); @@ -358,7 +364,7 @@ S32 LLDrawPoolAvatar::getNumPasses() } else if (getVertexShaderLevel() > 0) { - return 4; + return 5; } else { @@ -402,7 +408,10 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) beginSkinned(); break; case 3: - beginRigged(); + beginRiggedSimple(); + break; + case 4: + beginRiggedShinySimple(); break; } } @@ -429,7 +438,10 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass) endSkinned(); break; case 3: - endRigged(); + endRiggedSimple(); + break; + case 4: + endRiggedShinySimple(); break; } } @@ -616,14 +628,15 @@ void LLDrawPoolAvatar::endSkinned() gGL.getTexUnit(0)->activate(); } -void LLDrawPoolAvatar::beginRigged() +void LLDrawPoolAvatar::beginRiggedSimple() { sVertexProgram = &gSkinnedObjectSimpleProgram; + diffuse_channel = 0; gSkinnedObjectSimpleProgram.bind(); LLVertexBuffer::sWeight4Loc = gSkinnedObjectSimpleProgram.getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } -void LLDrawPoolAvatar::endRigged() +void LLDrawPoolAvatar::endRiggedSimple() { sVertexProgram = NULL; LLVertexBuffer::unbind(); @@ -631,6 +644,23 @@ void LLDrawPoolAvatar::endRigged() LLVertexBuffer::sWeight4Loc = -1; } +void LLDrawPoolAvatar::beginRiggedShinySimple() +{ + sVertexProgram = &gSkinnedObjectShinySimpleProgram; + sVertexProgram->bind(); + LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, diffuse_channel, cube_channel, false); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); +} + +void LLDrawPoolAvatar::endRiggedShinySimple() +{ + LLVertexBuffer::unbind(); + LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, diffuse_channel, cube_channel, false); + sVertexProgram->unbind(); + sVertexProgram = NULL; + LLVertexBuffer::sWeight4Loc = -1; +} + void LLDrawPoolAvatar::beginDeferredRigged() { sVertexProgram = &gDeferredSkinnedDiffuseProgram; @@ -790,9 +820,16 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) if (pass == 3) { - avatarp->renderSkinnedAttachments(); + renderRiggedSimple(avatarp); + return; + } + + if (pass == 4) + { + renderRiggedShinySimple(avatarp); return; } + if (sShaderLevel > 0) { @@ -830,13 +867,146 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) } } +void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face, U32 data_mask) +{ + LLVertexBuffer* buff = face->mVertexBuffer; + + if (!buff || + !buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) || + buff->getRequestedVerts() != vol_face.mVertices.size()) + { + face->setGeomIndex(0); + face->setIndicesIndex(0); + face->setSize(vol_face.mVertices.size(), vol_face.mIndices.size()); + + face->mVertexBuffer = new LLVertexBuffer(data_mask, 0); + face->mVertexBuffer->allocateBuffer(vol_face.mVertices.size(), vol_face.mIndices.size(), true); + + 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); + + face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_normal, offset, true); + buff = face->mVertexBuffer; + } +} + +void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, const U32 data_mask) +{ + for (U32 i = 0; i < mRiggedFace[type].size(); ++i) + { + LLFace* face = mRiggedFace[type][i]; + LLDrawable* drawable = face->getDrawable(); + if (!drawable) + { + continue; + } + + LLVOVolume* vobj = drawable->getVOVolume(); + + if (!vobj) + { + continue; + } + + LLVolume* volume = vobj->getVolume(); + S32 te = face->getTEOffset(); + + if (!volume || volume->getNumVolumeFaces() <= te) + { + continue; + } + + LLUUID mesh_id = volume->getParams().getSculptID(); + if (mesh_id.isNull()) + { + continue; + } + + const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(mesh_id); + if (!skin) + { + continue; + } + + const LLVolumeFace& vol_face = volume->getVolumeFace(te); + updateRiggedFaceVertexBuffer(face, skin, volume, vol_face, data_mask); + + LLVertexBuffer* buff = face->mVertexBuffer; + + if (buff) + { + LLMatrix4 mat[64]; + + for (U32 i = 0; i < skin->mJointNames.size(); ++i) + { + LLJoint* joint = avatar->getJoint(skin->mJointNames[i]); + if (joint) + { + mat[i] = skin->mInvBindMatrix[i]; + mat[i] *= joint->getWorldMatrix(); + } + } + + LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv("matrixPalette", + skin->mJointNames.size(), + FALSE, + (GLfloat*) mat[0].mMatrix); + LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv("matrixPalette[0]", + skin->mJointNames.size(), + FALSE, + (GLfloat*) mat[0].mMatrix); + + buff->setBuffer(data_mask); + + U16 start = face->getGeomStart(); + U16 end = start + face->getGeomCount()-1; + S32 offset = face->getIndicesStart(); + U32 count = face->getIndicesCount(); + + gGL.getTexUnit(0)->bind(face->getTexture()); + buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); + } + } +} + +void LLDrawPoolAvatar::renderRiggedSimple(LLVOAvatar* avatar) +{ + const U32 data_mask = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4; + + renderRigged(avatar, RIGGED_SIMPLE, data_mask); +} + + +void LLDrawPoolAvatar::renderRiggedShinySimple(LLVOAvatar* avatar) +{ + const U32 data_mask = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4; + + renderRigged(avatar, RIGGED_SHINY_SIMPLE, data_mask); +} + //----------------------------------------------------------------------------- // renderForSelect() //----------------------------------------------------------------------------- void LLDrawPoolAvatar::renderForSelect() { - - if (mDrawFace.empty()) { return; @@ -930,6 +1100,64 @@ LLColor3 LLDrawPoolAvatar::getDebugColor() const return LLColor3(0.f, 1.f, 0.f); } +void LLDrawPoolAvatar::addRiggedFace(LLFace* facep, U32 type) +{ + if (facep->getReferenceIndex() != -1) + { + llerrs << "Tried to add a rigged face that's referenced elsewhere." << llendl; + } + + if (type >= NUM_RIGGED_PASSES) + { + llerrs << "Invalid rigged face type." << llendl; + } + + facep->setReferenceIndex(mRiggedFace[type].size()); + facep->mDrawPoolp = this; + mRiggedFace[type].push_back(facep); +} + +void LLDrawPoolAvatar::removeRiggedFace(LLFace* facep, U32 type) +{ + S32 index = facep->getReferenceIndex(); + if (index == -1) + { + llerrs << "Tried to remove rigged face with invalid index." << llendl; + } + + if (type > RIGGED_UNKNOWN) + { + llerrs << "Invalid rigged face type." << llendl; + } + + facep->setReferenceIndex(-1); + facep->mDrawPoolp = NULL; + + if (type == RIGGED_UNKNOWN) + { + for (U32 i = 0; i < NUM_RIGGED_PASSES; ++i) + { + if (mRiggedFace[i].size() > index && mRiggedFace[i][index] == facep) + { + type = i; + break; + } + } + } + + if (type >= NUM_RIGGED_PASSES) + { + llerrs << "Could not find face for removal from current drawpool." << llendl; + } + + mRiggedFace[type].erase(mRiggedFace[type].begin()+index); + + for (S32 i = index; i < mRiggedFace[type].size(); ++i) + { //bump indexes of currently held faces down after removal + mRiggedFace[type][i]->setReferenceIndex(i); + } +} + LLVertexBufferAvatar::LLVertexBufferAvatar() : LLVertexBuffer(sDataMask, GL_STREAM_DRAW_ARB) //avatars are always stream draw due to morph targets diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index b42cc54622..0ebb035f2a 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -37,6 +37,11 @@ class LLVOAvatar; class LLGLSLShader; +class LLFace; +class LLMeshSkinInfo; +class LLVolume; +class LLVolumeFace; + class LLDrawPoolAvatar : public LLFacePool { @@ -91,12 +96,14 @@ public: void beginRigid(); void beginImpostor(); void beginSkinned(); - void beginRigged(); - + void beginRiggedSimple(); + void beginRiggedShinySimple(); + void endRigid(); void endImpostor(); void endSkinned(); - void endRigged(); + void endRiggedSimple(); + void endRiggedShinySimple(); void beginDeferredImpostor(); void beginDeferredRigid(); @@ -108,11 +115,40 @@ public: void endDeferredSkinned(); void endDeferredRigged(); + void updateRiggedFaceVertexBuffer(LLFace* facep, + const LLMeshSkinInfo* skin, + LLVolume* volume, + const LLVolumeFace& vol_face, + U32 data_mask); + + void renderRigged(LLVOAvatar* avatar, U32 type, const U32 data_mask); + void renderRiggedSimple(LLVOAvatar* avatar); + void renderRiggedShinySimple(LLVOAvatar* avatar); + /*virtual*/ LLViewerTexture *getDebugTexture(); /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display void renderAvatars(LLVOAvatar *single_avatar, S32 pass = -1); // renders only one avatar if single_avatar is not null. + typedef enum + { + RIGGED_SIMPLE = 0, + RIGGED_SHINY_SIMPLE, + RIGGED_SHINY_FULLBRIGHT, + RIGGED_SHINY_BUMP, + RIGGED_BUMP, + RIGGED_FULLBRIGHT, + RIGGED_ALPHA, + NUM_RIGGED_PASSES, + RIGGED_UNKNOWN, + } eRiggedPass; + + + void addRiggedFace(LLFace* facep, U32 type); + void removeRiggedFace(LLFace* facep, U32 type = RIGGED_UNKNOWN); + + std::vector mRiggedFace[NUM_RIGGED_PASSES]; + static BOOL sSkipOpaque; static BOOL sSkipTransparent; static LLGLSLShader* sVertexProgram; diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 8f3e775976..2f449fa42f 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -323,30 +323,43 @@ void LLDrawPoolBump::beginShiny(bool invisible) sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0; } - if (LLPipeline::sUnderWaterRender) + if (getVertexShaderLevel() > 0) { - shader = &gObjectShinyWaterProgram; + if (LLPipeline::sUnderWaterRender) + { + shader = &gObjectShinyWaterProgram; + } + else + { + shader = &gObjectShinyProgram; + } + shader->bind(); } else { - shader = &gObjectShinyProgram; + shader = NULL; } + bindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel, invisible); +} + +//static +void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible) +{ LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; if( cube_map ) { - if (!invisible && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0 ) + if (!invisible && shader ) { LLMatrix4 mat; mat.initRows(LLVector4(gGLModelView+0), LLVector4(gGLModelView+4), LLVector4(gGLModelView+8), LLVector4(gGLModelView+12)); - shader->bind(); LLVector3 vec = LLVector3(gShinyOrigin) * mat; LLVector4 vec4(vec, gShinyOrigin.mV[3]); shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV); - if (mVertexShaderLevel > 1) + if (shader_level > 1) { cube_map->setMatrix(1); // Make sure that texture coord generation happens for tex unit 1, as that's the one we use for @@ -408,22 +421,16 @@ void LLDrawPoolBump::renderShiny(bool invisible) } } -void LLDrawPoolBump::endShiny(bool invisible) +//static +void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible) { - LLFastTimer t(FTM_RENDER_SHINY); - if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| - (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) - { - return; - } - LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; if( cube_map ) { cube_map->disable(); cube_map->restoreMatrix(); - if (!invisible && mVertexShaderLevel > 1) + if (!invisible && shader_level > 1) { shader->disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); @@ -434,7 +441,6 @@ void LLDrawPoolBump::endShiny(bool invisible) shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); } } - shader->unbind(); } } gGL.getTexUnit(diffuse_channel)->disable(); @@ -442,6 +448,22 @@ void LLDrawPoolBump::endShiny(bool invisible) gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); +} + +void LLDrawPoolBump::endShiny(bool invisible) +{ + LLFastTimer t(FTM_RENDER_SHINY); + if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| + (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) + { + return; + } + + unbindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel, invisible); + if (shader) + { + shader->unbind(); + } diffuse_channel = -1; cube_channel = 0; diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h index 2019f1df26..89bbefe778 100644 --- a/indra/newview/lldrawpoolbump.h +++ b/indra/newview/lldrawpoolbump.h @@ -41,6 +41,7 @@ class LLImageRaw; class LLSpatialGroup; class LLDrawInfo; +class LLGLSLShader; class LLViewerFetchedTexture; class LLDrawPoolBump : public LLRenderPass @@ -79,6 +80,9 @@ public: void renderBump(); void endBump(); + static void bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible); + static void unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible); + virtual S32 getNumDeferredPasses(); /*virtual*/ void beginDeferredPass(S32 pass); /*virtual*/ void endDeferredPass(S32 pass); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 7866e49bae..0e0b8447ca 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -205,7 +205,12 @@ void LLFace::destroy() if (mDrawPoolp) { LLFastTimer t(FTM_DESTROY_DRAWPOOL); + + if (this->isState(LLFace::RIGGED) && mDrawPoolp->getType() == LLDrawPool::POOL_AVATAR) mDrawPoolp->removeFace(this); + + + mDrawPoolp = NULL; } diff --git a/indra/newview/llface.h b/indra/newview/llface.h index bbf8de04bc..2b8fdf2e58 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -234,6 +234,7 @@ public: private: friend class LLGeometryManager; friend class LLVolumeGeometryManager; + friend class LLDrawPoolAvatar; U32 mState; LLFacePool* mDrawPoolp; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 6bd3ceb8a8..3aecd0175d 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -5219,6 +5219,25 @@ void LLViewerObject::resetChildrenPosition(const LLVector3& offset, BOOL simplif return ; } +//virtual +LLVOAvatar* LLViewerObject::getAvatar() const +{ + if (isAttachment()) + { + LLViewerObject* vobj = (LLViewerObject*) getParent(); + + while (vobj && !vobj->asAvatar()) + { + vobj = (LLViewerObject*) vobj->getParent(); + } + + return (LLVOAvatar*) vobj; + } + + return NULL; +} + + class ObjectPhysicsProperties : public LLHTTPNode { public: diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 594d7a0827..0fd0cbfa60 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -181,6 +181,7 @@ public: void setOnActiveList(BOOL on_active) { mOnActiveList = on_active; } virtual BOOL isAttachment() const { return FALSE; } + virtual LLVOAvatar* getAvatar() const; //get the avatar this object is attached to, or NULL if object is not an attachment virtual BOOL isHUDAttachment() const { return FALSE; } virtual void updateRadius() {}; virtual F32 getVObjRadius() const; // default implemenation is mDrawable->getRadius() diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index d978e856a6..fe68d6eaa4 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -79,6 +79,7 @@ LLGLSLShader gObjectShinyWaterProgram; //object hardware skinning shaders LLGLSLShader gSkinnedObjectSimpleProgram; +LLGLSLShader gSkinnedObjectShinySimpleProgram; //environment shaders LLGLSLShader gTerrainProgram; @@ -154,6 +155,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gObjectFullbrightProgram); mShaderList.push_back(&gObjectFullbrightShinyProgram); mShaderList.push_back(&gSkinnedObjectSimpleProgram); + mShaderList.push_back(&gSkinnedObjectShinySimpleProgram); mShaderList.push_back(&gTerrainProgram); mShaderList.push_back(&gTerrainWaterProgram); mShaderList.push_back(&gObjectSimpleWaterProgram); @@ -505,6 +507,9 @@ void LLViewerShaderMgr::setShaders() if (!loadShadersDeferred()) { gSavedSettings.setBOOL("RenderDeferred", FALSE); + reentrance = false; + setShaders(); + return; } #endif } @@ -557,6 +562,8 @@ void LLViewerShaderMgr::unloadShaders() gObjectShinyWaterProgram.unload(); gSkinnedObjectSimpleProgram.unload(); + gSkinnedObjectShinySimpleProgram.unload(); + gWaterProgram.unload(); gUnderWaterProgram.unload(); @@ -917,7 +924,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredGIProgram.unload(); gDeferredGIFinalProgram.unload(); gDeferredWaterProgram.unload(); - return FALSE; + return TRUE; } mVertexShaderLevel[SHADER_AVATAR] = 1; @@ -1251,6 +1258,8 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightProgram.unload(); gObjectFullbrightWaterProgram.unload(); gSkinnedObjectSimpleProgram.unload(); + gSkinnedObjectShinySimpleProgram.unload(); + return FALSE; } @@ -1376,6 +1385,22 @@ BOOL LLViewerShaderMgr::loadShadersObject() success = gSkinnedObjectSimpleProgram.createShader(NULL, NULL); } + if (success) + { + gSkinnedObjectShinySimpleProgram.mName = "Skinned Shiny Simple Shader"; + gSkinnedObjectShinySimpleProgram.mFeatures.calculatesLighting = true; + gSkinnedObjectShinySimpleProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectShinySimpleProgram.mFeatures.hasGamma = true; + gSkinnedObjectShinySimpleProgram.mFeatures.hasAtmospherics = true; + gSkinnedObjectShinySimpleProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectShinySimpleProgram.mFeatures.isShiny = true; + gSkinnedObjectShinySimpleProgram.mShaderFiles.clear(); + gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectShinySimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectShinySimpleProgram.createShader(NULL, &mShinyUniforms); + } + if( !success ) { mVertexShaderLevel[SHADER_OBJECT] = 0; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index b279a59777..beac5462e2 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -315,6 +315,7 @@ extern LLGLSLShader gObjectShinyProgram; extern LLGLSLShader gObjectShinyWaterProgram; extern LLGLSLShader gSkinnedObjectSimpleProgram; +extern LLGLSLShader gSkinnedObjectShinySimpleProgram; //environment shaders extern LLGLSLShader gTerrainProgram; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 7cdbebf4d1..c51a7d9cbb 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -3642,7 +3642,7 @@ bool LLVOAvatar::shouldAlphaMask() U32 LLVOAvatar::renderSkinnedAttachments() { - U32 num_indices = 0; + /*U32 num_indices = 0; const U32 data_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | @@ -3670,107 +3670,14 @@ U32 LLVOAvatar::renderSkinnedAttachments() LLFace* face = drawable->getFace(i); if (face->isState(LLFace::RIGGED)) { - LLVolume* volume = attached_object->getVolume(); - if (!volume || volume->getNumVolumeFaces() <= i) - { - continue; - } - - const LLVolumeFace& vol_face = volume->getVolumeFace(i); - - const LLMeshSkinInfo* skin = NULL; - LLVertexBuffer* buff = face->mVertexBuffer; - LLUUID mesh_id = volume->getParams().getSculptID();; - - if (!buff || - !buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) || - buff->getRequestedVerts() != vol_face.mVertices.size()) - { - face->mVertexBuffer = NULL; - face->mLastVertexBuffer = NULL; - buff = NULL; - - if (mesh_id.notNull()) - { - skin = gMeshRepo.getSkinInfo(mesh_id); - if (skin) - { - face->mVertexBuffer = new LLVertexBuffer(data_mask, 0); - face->mVertexBuffer->allocateBuffer(vol_face.mVertices.size(), vol_face.mIndices.size(), true); - - face->setGeomIndex(0); - face->setIndicesIndex(0); - face->setSize(vol_face.mVertices.size(), vol_face.mIndices.size()); - - 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); - - face->getGeometryVolume(*volume, i, mat_vert, mat_normal, offset, true); - buff = face->mVertexBuffer; - } - } - } - if (buff && mesh_id.notNull()) - { - if (!skin) - { - skin = gMeshRepo.getSkinInfo(mesh_id); - } - - if (skin) - { - LLMatrix4 mat[64]; - - for (U32 i = 0; i < skin->mJointNames.size(); ++i) - { - LLJoint* joint = getJoint(skin->mJointNames[i]); - if (joint) - { - mat[i] = skin->mInvBindMatrix[i]; - mat[i] *= joint->getWorldMatrix(); - } - } - - LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv("matrixPalette", - skin->mJointNames.size(), - FALSE, - (GLfloat*) mat[0].mMatrix); - LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv("matrixPalette[0]", - skin->mJointNames.size(), - FALSE, - (GLfloat*) mat[0].mMatrix); - - buff->setBuffer(data_mask); - - U16 start = face->getGeomStart(); - U16 end = start + face->getGeomCount()-1; - S32 offset = face->getIndicesStart(); - U32 count = face->getIndicesCount(); - - gGL.getTexUnit(0)->bind(face->getTexture()); - buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); - - } - } - } - } } } } } - return num_indices; + return num_indices;*/ + return 0; } //----------------------------------------------------------------------------- diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 96f69b3676..e49b33bd80 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -52,6 +52,7 @@ #include "object_flags.h" #include "llagentconstants.h" #include "lldrawable.h" +#include "lldrawpoolavatar.h" #include "lldrawpoolbump.h" #include "llface.h" #include "llspatialpartition.h" @@ -73,6 +74,8 @@ #include "llmeshrepository.h" #include "llagent.h" #include "llviewermediafocus.h" +#include "llvoavatar.h" + const S32 MIN_QUIET_FRAMES_COALESCE = 30; const F32 FORCE_SIMPLE_RENDER_AREA = 512.f; @@ -3415,6 +3418,33 @@ void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group) static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_VB("Volume"); static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt"); +LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) +{ + LLVOAvatar* avatar = vobj->getAvatar(); + + if (avatar) + { + LLDrawable* drawable = avatar->mDrawable; + if (drawable && drawable->getNumFaces() > 0) + { + LLFace* face = drawable->getFace(0); + if (face) + { + LLDrawPool* drawpool = face->getPool(); + if (drawpool) + { + if (drawpool->getType() == LLDrawPool::POOL_AVATAR) + { + return (LLDrawPoolAvatar*) drawpool; + } + } + } + } + } + + return NULL; +} + void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { @@ -3499,13 +3529,47 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) facep->mVertexBuffer = NULL; facep->mLastVertexBuffer = NULL; facep->setState(LLFace::RIGGED); + + //get drawpool of avatar with rigged face + LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); + + if (pool) + { + const LLTextureEntry* te = facep->getTextureEntry(); + + //remove face from old pool if it exists + LLDrawPool* old_pool = facep->getPool(); + if (old_pool && old_pool->getType() == LLDrawPool::POOL_AVATAR) + { + ((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep); + } + + //add face to new pool + if (te->getShiny()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY_SIMPLE); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + } + } + } continue; } else { - facep->clearState(LLFace::RIGGED); + if (facep->isState(LLFace::RIGGED)) + { //face is not rigged but used to be, remove from rigged face pool + LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); + if (pool) + { + pool->removeRiggedFace(facep); + } + facep->clearState(LLFace::RIGGED); + } } if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) -- cgit v1.3 From 2f95a549a365ca2bedf7824014a687b3af88e20f Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Sat, 1 May 2010 01:55:21 -0500 Subject: Fullbrigt skinned and fix for silly crash from not removing face references. --- .../shaders/class1/objects/shinyV.glsl | 2 +- indra/newview/lldrawpoolavatar.cpp | 40 +++++++++++++++++++++- indra/newview/lldrawpoolavatar.h | 5 ++- indra/newview/llface.cpp | 13 ++++--- indra/newview/llviewershadermgr.cpp | 19 ++++++++++ indra/newview/llviewershadermgr.h | 1 + indra/newview/llvovolume.cpp | 9 ++++- 7 files changed, 81 insertions(+), 8 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl index c2e1ddf734..101458c438 100644 --- a/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl @@ -12,7 +12,7 @@ uniform vec4 origin; void main() { //transform vertex - gl_Position = ftransform(); //gl_ModelViewProjectionMatrix * gl_Vertex; + gl_Position = ftransform(); vec4 pos = (gl_ModelViewMatrix * gl_Vertex); vec3 norm = normalize(gl_NormalMatrix * gl_Normal); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 02c7e3bb6f..9463be6059 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -364,7 +364,7 @@ S32 LLDrawPoolAvatar::getNumPasses() } else if (getVertexShaderLevel() > 0) { - return 5; + return 6; } else { @@ -411,6 +411,9 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) beginRiggedSimple(); break; case 4: + beginRiggedFullbright(); + break; + case 5: beginRiggedShinySimple(); break; } @@ -441,6 +444,9 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass) endRiggedSimple(); break; case 4: + endRiggedFullbright(); + break; + case 5: endRiggedShinySimple(); break; } @@ -644,6 +650,22 @@ void LLDrawPoolAvatar::endRiggedSimple() LLVertexBuffer::sWeight4Loc = -1; } +void LLDrawPoolAvatar::beginRiggedFullbright() +{ + sVertexProgram = &gSkinnedObjectFullbrightProgram; + diffuse_channel = 0; + gSkinnedObjectFullbrightProgram.bind(); + LLVertexBuffer::sWeight4Loc = gSkinnedObjectFullbrightProgram.getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); +} + +void LLDrawPoolAvatar::endRiggedFullbright() +{ + sVertexProgram = NULL; + LLVertexBuffer::unbind(); + gSkinnedObjectFullbrightProgram.unbind(); + LLVertexBuffer::sWeight4Loc = -1; +} + void LLDrawPoolAvatar::beginRiggedShinySimple() { sVertexProgram = &gSkinnedObjectShinySimpleProgram; @@ -825,6 +847,12 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) } if (pass == 4) + { + renderRiggedFullbright(avatarp); + return; + } + + if (pass == 5) { renderRiggedShinySimple(avatarp); return; @@ -990,6 +1018,16 @@ void LLDrawPoolAvatar::renderRiggedSimple(LLVOAvatar* avatar) renderRigged(avatar, RIGGED_SIMPLE, data_mask); } +void LLDrawPoolAvatar::renderRiggedFullbright(LLVOAvatar* avatar) +{ + const U32 data_mask = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4; + + renderRigged(avatar, RIGGED_FULLBRIGHT, data_mask); +} + void LLDrawPoolAvatar::renderRiggedShinySimple(LLVOAvatar* avatar) { diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 0ebb035f2a..8443069376 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -97,12 +97,14 @@ public: void beginImpostor(); void beginSkinned(); void beginRiggedSimple(); + void beginRiggedFullbright(); void beginRiggedShinySimple(); void endRigid(); void endImpostor(); void endSkinned(); void endRiggedSimple(); + void endRiggedFullbright(); void endRiggedShinySimple(); void beginDeferredImpostor(); @@ -123,6 +125,7 @@ public: void renderRigged(LLVOAvatar* avatar, U32 type, const U32 data_mask); void renderRiggedSimple(LLVOAvatar* avatar); + void renderRiggedFullbright(LLVOAvatar* avatar); void renderRiggedShinySimple(LLVOAvatar* avatar); /*virtual*/ LLViewerTexture *getDebugTexture(); @@ -133,11 +136,11 @@ public: typedef enum { RIGGED_SIMPLE = 0, + RIGGED_FULLBRIGHT, RIGGED_SHINY_SIMPLE, RIGGED_SHINY_FULLBRIGHT, RIGGED_SHINY_BUMP, RIGGED_BUMP, - RIGGED_FULLBRIGHT, RIGGED_ALPHA, NUM_RIGGED_PASSES, RIGGED_UNKNOWN, diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 0e0b8447ca..9df692e787 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -41,6 +41,7 @@ #include "m3math.h" #include "v3color.h" +#include "lldrawpoolavatar.h" #include "lldrawpoolbump.h" #include "llgl.h" #include "llrender.h" @@ -207,10 +208,14 @@ void LLFace::destroy() LLFastTimer t(FTM_DESTROY_DRAWPOOL); if (this->isState(LLFace::RIGGED) && mDrawPoolp->getType() == LLDrawPool::POOL_AVATAR) - mDrawPoolp->removeFace(this); - - - + { + ((LLDrawPoolAvatar*) mDrawPoolp)->removeRiggedFace(this); + } + else + { + mDrawPoolp->removeFace(this); + } + mDrawPoolp = NULL; } diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index fe68d6eaa4..3cc5b4357a 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -79,6 +79,7 @@ LLGLSLShader gObjectShinyWaterProgram; //object hardware skinning shaders LLGLSLShader gSkinnedObjectSimpleProgram; +LLGLSLShader gSkinnedObjectFullbrightProgram; LLGLSLShader gSkinnedObjectShinySimpleProgram; //environment shaders @@ -155,6 +156,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gObjectFullbrightProgram); mShaderList.push_back(&gObjectFullbrightShinyProgram); mShaderList.push_back(&gSkinnedObjectSimpleProgram); + mShaderList.push_back(&gSkinnedObjectFullbrightProgram); mShaderList.push_back(&gSkinnedObjectShinySimpleProgram); mShaderList.push_back(&gTerrainProgram); mShaderList.push_back(&gTerrainWaterProgram); @@ -562,6 +564,7 @@ void LLViewerShaderMgr::unloadShaders() gObjectShinyWaterProgram.unload(); gSkinnedObjectSimpleProgram.unload(); + gSkinnedObjectFullbrightProgram.unload(); gSkinnedObjectShinySimpleProgram.unload(); @@ -1258,6 +1261,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightProgram.unload(); gObjectFullbrightWaterProgram.unload(); gSkinnedObjectSimpleProgram.unload(); + gSkinnedObjectFullbrightProgram.unload(); gSkinnedObjectShinySimpleProgram.unload(); return FALSE; @@ -1385,6 +1389,21 @@ BOOL LLViewerShaderMgr::loadShadersObject() success = gSkinnedObjectSimpleProgram.createShader(NULL, NULL); } + if (success) + { + gSkinnedObjectFullbrightProgram.mName = "Skinned Fullbright Shader"; + gSkinnedObjectFullbrightProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectFullbrightProgram.mFeatures.hasGamma = true; + gSkinnedObjectFullbrightProgram.mFeatures.hasTransport = true; + gSkinnedObjectFullbrightProgram.mFeatures.isFullbright = true; + gSkinnedObjectFullbrightProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectFullbrightProgram.mShaderFiles.clear(); + gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectFullbrightProgram.createShader(NULL, NULL); + } + if (success) { gSkinnedObjectShinySimpleProgram.mName = "Skinned Shiny Simple Shader"; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index beac5462e2..b4fc336bf3 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -315,6 +315,7 @@ extern LLGLSLShader gObjectShinyProgram; extern LLGLSLShader gObjectShinyWaterProgram; extern LLGLSLShader gSkinnedObjectSimpleProgram; +extern LLGLSLShader gSkinnedObjectFullbrightProgram; extern LLGLSLShader gSkinnedObjectShinySimpleProgram; //environment shaders diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index e49b33bd80..3449c05be8 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3551,7 +3551,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } else { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + } } } -- cgit v1.3 From dc15fc5ba0fcf9907d834b523e6622d800d7ed4e Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Sat, 1 May 2010 02:56:23 -0500 Subject: Fullbright shiny skinned. --- indra/newview/lldrawpoolavatar.cpp | 45 +++++++++++++++++++++++++++++++++++-- indra/newview/lldrawpoolavatar.h | 11 +++++---- indra/newview/llviewershadermgr.cpp | 20 +++++++++++++++++ indra/newview/llviewershadermgr.h | 1 + indra/newview/llvovolume.cpp | 9 +++++++- 5 files changed, 79 insertions(+), 7 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 9463be6059..8227e8ede2 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -364,7 +364,7 @@ S32 LLDrawPoolAvatar::getNumPasses() } else if (getVertexShaderLevel() > 0) { - return 6; + return 7; } else { @@ -416,6 +416,9 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) case 5: beginRiggedShinySimple(); break; + case 6: + beginRiggedFullbrightShiny(); + break; } } @@ -449,6 +452,9 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass) case 5: endRiggedShinySimple(); break; + case 6: + endRiggedFullbrightShiny(); + break; } } @@ -683,6 +689,24 @@ void LLDrawPoolAvatar::endRiggedShinySimple() LLVertexBuffer::sWeight4Loc = -1; } +void LLDrawPoolAvatar::beginRiggedFullbrightShiny() +{ + sVertexProgram = &gSkinnedObjectFullbrightShinyProgram; + sVertexProgram->bind(); + LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, diffuse_channel, cube_channel, false); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); +} + +void LLDrawPoolAvatar::endRiggedFullbrightShiny() +{ + LLVertexBuffer::unbind(); + LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, diffuse_channel, cube_channel, false); + sVertexProgram->unbind(); + sVertexProgram = NULL; + LLVertexBuffer::sWeight4Loc = -1; +} + + void LLDrawPoolAvatar::beginDeferredRigged() { sVertexProgram = &gDeferredSkinnedDiffuseProgram; @@ -858,6 +882,12 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) return; } + if (pass == 6) + { + renderRiggedFullbrightShiny(avatarp); + return; + } + if (sShaderLevel > 0) { @@ -1037,7 +1067,18 @@ void LLDrawPoolAvatar::renderRiggedShinySimple(LLVOAvatar* avatar) LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_WEIGHT4; - renderRigged(avatar, RIGGED_SHINY_SIMPLE, data_mask); + renderRigged(avatar, RIGGED_SHINY, data_mask); +} + +void LLDrawPoolAvatar::renderRiggedFullbrightShiny(LLVOAvatar* avatar) +{ + const U32 data_mask = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4; + + renderRigged(avatar, RIGGED_FULLBRIGHT_SHINY, data_mask); } //----------------------------------------------------------------------------- diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 8443069376..d758bb07f0 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -98,6 +98,7 @@ public: void beginSkinned(); void beginRiggedSimple(); void beginRiggedFullbright(); + void beginRiggedFullbrightShiny(); void beginRiggedShinySimple(); void endRigid(); @@ -105,6 +106,7 @@ public: void endSkinned(); void endRiggedSimple(); void endRiggedFullbright(); + void endRiggedFullbrightShiny(); void endRiggedShinySimple(); void beginDeferredImpostor(); @@ -127,6 +129,7 @@ public: void renderRiggedSimple(LLVOAvatar* avatar); void renderRiggedFullbright(LLVOAvatar* avatar); void renderRiggedShinySimple(LLVOAvatar* avatar); + void renderRiggedFullbrightShiny(LLVOAvatar* avatar); /*virtual*/ LLViewerTexture *getDebugTexture(); /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display @@ -137,11 +140,11 @@ public: { RIGGED_SIMPLE = 0, RIGGED_FULLBRIGHT, - RIGGED_SHINY_SIMPLE, - RIGGED_SHINY_FULLBRIGHT, - RIGGED_SHINY_BUMP, - RIGGED_BUMP, + RIGGED_SHINY, + RIGGED_FULLBRIGHT_SHINY, + RIGGED_GLOW, RIGGED_ALPHA, + RIGGED_FULLBRIGHT_ALPHA, NUM_RIGGED_PASSES, RIGGED_UNKNOWN, } eRiggedPass; diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 3cc5b4357a..eafc52748e 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -80,6 +80,7 @@ LLGLSLShader gObjectShinyWaterProgram; //object hardware skinning shaders LLGLSLShader gSkinnedObjectSimpleProgram; LLGLSLShader gSkinnedObjectFullbrightProgram; +LLGLSLShader gSkinnedObjectFullbrightShinyProgram; LLGLSLShader gSkinnedObjectShinySimpleProgram; //environment shaders @@ -157,6 +158,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gObjectFullbrightShinyProgram); mShaderList.push_back(&gSkinnedObjectSimpleProgram); mShaderList.push_back(&gSkinnedObjectFullbrightProgram); + mShaderList.push_back(&gSkinnedObjectFullbrightShinyProgram); mShaderList.push_back(&gSkinnedObjectShinySimpleProgram); mShaderList.push_back(&gTerrainProgram); mShaderList.push_back(&gTerrainWaterProgram); @@ -565,6 +567,7 @@ void LLViewerShaderMgr::unloadShaders() gSkinnedObjectSimpleProgram.unload(); gSkinnedObjectFullbrightProgram.unload(); + gSkinnedObjectFullbrightShinyProgram.unload(); gSkinnedObjectShinySimpleProgram.unload(); @@ -1262,6 +1265,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightWaterProgram.unload(); gSkinnedObjectSimpleProgram.unload(); gSkinnedObjectFullbrightProgram.unload(); + gSkinnedObjectFullbrightShinyProgram.unload(); gSkinnedObjectShinySimpleProgram.unload(); return FALSE; @@ -1404,6 +1408,22 @@ BOOL LLViewerShaderMgr::loadShadersObject() success = gSkinnedObjectFullbrightProgram.createShader(NULL, NULL); } + if (success) + { + gSkinnedObjectFullbrightShinyProgram.mName = "Skinned Fullbright Shiny Shader"; + gSkinnedObjectFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectFullbrightShinyProgram.mFeatures.hasGamma = true; + gSkinnedObjectFullbrightShinyProgram.mFeatures.hasTransport = true; + gSkinnedObjectFullbrightShinyProgram.mFeatures.isShiny = true; + gSkinnedObjectFullbrightShinyProgram.mFeatures.isFullbright = true; + gSkinnedObjectFullbrightShinyProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectFullbrightShinyProgram.mShaderFiles.clear(); + gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectFullbrightShinyProgram.createShader(NULL, &mShinyUniforms); + } + if (success) { gSkinnedObjectShinySimpleProgram.mName = "Skinned Shiny Simple Shader"; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index b4fc336bf3..bb28cd7ec2 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -316,6 +316,7 @@ extern LLGLSLShader gObjectShinyWaterProgram; extern LLGLSLShader gSkinnedObjectSimpleProgram; extern LLGLSLShader gSkinnedObjectFullbrightProgram; +extern LLGLSLShader gSkinnedObjectFullbrightShinyProgram; extern LLGLSLShader gSkinnedObjectShinySimpleProgram; //environment shaders diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 3449c05be8..43252c553c 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3547,7 +3547,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) //add face to new pool if (te->getShiny()) { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY_SIMPLE); + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); + } } else { -- cgit v1.3 From 58defe76b0eed6f773b961e8ba5cd3aeb856467a Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Sun, 2 May 2010 00:28:30 -0500 Subject: Rigged glow. --- indra/newview/lldrawpoolavatar.cpp | 214 +++++++++++++++++++++++++++++++------ indra/newview/lldrawpoolavatar.h | 13 ++- indra/newview/llface.h | 2 + indra/newview/llvovolume.cpp | 21 +++- 4 files changed, 212 insertions(+), 38 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 8227e8ede2..866aea42c4 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -364,7 +364,7 @@ S32 LLDrawPoolAvatar::getNumPasses() } else if (getVertexShaderLevel() > 0) { - return 7; + return 10; } else { @@ -419,6 +419,15 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) case 6: beginRiggedFullbrightShiny(); break; + case 7: + beginRiggedAlpha(); + break; + case 8: + beginRiggedFullbrightAlpha(); + break; + case 9: + beginRiggedGlow(); + break; } } @@ -455,6 +464,15 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass) case 6: endRiggedFullbrightShiny(); break; + case 7: + endRiggedAlpha(); + break; + case 8: + endRiggedFullbrightAlpha(); + break; + case 9: + endRiggedGlow(); + break; } } @@ -656,6 +674,55 @@ void LLDrawPoolAvatar::endRiggedSimple() LLVertexBuffer::sWeight4Loc = -1; } +void LLDrawPoolAvatar::beginRiggedAlpha() +{ + sVertexProgram = &gSkinnedObjectSimpleProgram; + diffuse_channel = 0; + sVertexProgram->bind(); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); +} + +void LLDrawPoolAvatar::endRiggedAlpha() +{ + sVertexProgram->unbind(); + sVertexProgram = NULL; + LLVertexBuffer::unbind(); + LLVertexBuffer::sWeight4Loc = -1; +} + + +void LLDrawPoolAvatar::beginRiggedFullbrightAlpha() +{ + sVertexProgram = &gSkinnedObjectFullbrightProgram; + diffuse_channel = 0; + sVertexProgram->bind(); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); +} + +void LLDrawPoolAvatar::endRiggedFullbrightAlpha() +{ + sVertexProgram->unbind(); + sVertexProgram = NULL; + LLVertexBuffer::unbind(); + LLVertexBuffer::sWeight4Loc = -1; +} + +void LLDrawPoolAvatar::beginRiggedGlow() +{ + sVertexProgram = &gSkinnedObjectFullbrightProgram; + diffuse_channel = 0; + sVertexProgram->bind(); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); +} + +void LLDrawPoolAvatar::endRiggedGlow() +{ + sVertexProgram->unbind(); + sVertexProgram = NULL; + LLVertexBuffer::unbind(); + LLVertexBuffer::sWeight4Loc = -1; +} + void LLDrawPoolAvatar::beginRiggedFullbright() { sVertexProgram = &gSkinnedObjectFullbrightProgram; @@ -888,6 +955,48 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) return; } + if (pass >= 7 && pass <= 9) + { + LLGLEnable blend(GL_BLEND); + + gGL.setColorMask(true, true); + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA, + LLRender::BF_ZERO, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA); + + + if (pass == 7) + { + renderRiggedAlpha(avatarp); + return; + } + + if (pass == 8) + { + renderRiggedFullbrightAlpha(avatarp); + return; + } + } + + if (pass == 9) + { + LLGLEnable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + gGL.flush(); + + LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -1.0f); + gGL.setSceneBlendType(LLRender::BT_ADD); + + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + gGL.setColorMask(false, true); + + renderRiggedGlow(avatarp); + gGL.setColorMask(true, false); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + } + if (sShaderLevel > 0) { @@ -958,7 +1067,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSk } } -void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, const U32 data_mask) +void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, const U32 data_mask, bool glow) { for (U32 i = 0; i < mRiggedFace[type].size(); ++i) { @@ -1031,6 +1140,11 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, const U32 data S32 offset = face->getIndicesStart(); U32 count = face->getIndicesCount(); + if (glow) + { + glColor4f(0,0,0,face->getTextureEntry()->getGlow()); + } + gGL.getTexUnit(0)->bind(face->getTexture()); buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); } @@ -1081,6 +1195,39 @@ void LLDrawPoolAvatar::renderRiggedFullbrightShiny(LLVOAvatar* avatar) renderRigged(avatar, RIGGED_FULLBRIGHT_SHINY, data_mask); } +void LLDrawPoolAvatar::renderRiggedAlpha(LLVOAvatar* avatar) +{ + const U32 data_mask = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4; + + renderRigged(avatar, RIGGED_ALPHA, data_mask); +} + +void LLDrawPoolAvatar::renderRiggedFullbrightAlpha(LLVOAvatar* avatar) +{ + const U32 data_mask = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4; + + renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA, data_mask); +} + +void LLDrawPoolAvatar::renderRiggedGlow(LLVOAvatar* avatar) +{ + const U32 data_mask = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_WEIGHT4; + + renderRigged(avatar, RIGGED_GLOW, data_mask, true); +} + + + + //----------------------------------------------------------------------------- // renderForSelect() //----------------------------------------------------------------------------- @@ -1181,60 +1328,57 @@ LLColor3 LLDrawPoolAvatar::getDebugColor() const void LLDrawPoolAvatar::addRiggedFace(LLFace* facep, U32 type) { - if (facep->getReferenceIndex() != -1) + if (facep->mRiggedIndex.empty()) { - llerrs << "Tried to add a rigged face that's referenced elsewhere." << llendl; - } + facep->mRiggedIndex.resize(LLDrawPoolAvatar::NUM_RIGGED_PASSES); + for (U32 i = 0; i < facep->mRiggedIndex.size(); ++i) + { + facep->mRiggedIndex[i] = -1; + } + } if (type >= NUM_RIGGED_PASSES) { llerrs << "Invalid rigged face type." << llendl; } - facep->setReferenceIndex(mRiggedFace[type].size()); + if (facep->mRiggedIndex[type] != -1) + { + llerrs << "Tried to add a rigged face that's referenced elsewhere." << llendl; + } + + + facep->mRiggedIndex[type] = mRiggedFace[type].size(); facep->mDrawPoolp = this; mRiggedFace[type].push_back(facep); } -void LLDrawPoolAvatar::removeRiggedFace(LLFace* facep, U32 type) +void LLDrawPoolAvatar::removeRiggedFace(LLFace* facep) { - S32 index = facep->getReferenceIndex(); - if (index == -1) - { - llerrs << "Tried to remove rigged face with invalid index." << llendl; - } - - if (type > RIGGED_UNKNOWN) - { - llerrs << "Invalid rigged face type." << llendl; - } - - facep->setReferenceIndex(-1); + facep->mDrawPoolp = NULL; - if (type == RIGGED_UNKNOWN) + for (U32 i = 0; i < NUM_RIGGED_PASSES; ++i) { - for (U32 i = 0; i < NUM_RIGGED_PASSES; ++i) + S32 index = facep->mRiggedIndex[i]; + + if (index > -1) { if (mRiggedFace[i].size() > index && mRiggedFace[i][index] == facep) { - type = i; - break; + facep->mRiggedIndex[i] = -1; + mRiggedFace[i].erase(mRiggedFace[i].begin()+index); + for (U32 j = index; j < mRiggedFace[i].size(); ++j) + { //bump indexes down for faces referenced after erased face + mRiggedFace[i][j]->mRiggedIndex[i] = j; + } + } + else + { + llerrs << "Face reference data corrupt for rigged type " << i << llendl; } } } - - if (type >= NUM_RIGGED_PASSES) - { - llerrs << "Could not find face for removal from current drawpool." << llendl; - } - - mRiggedFace[type].erase(mRiggedFace[type].begin()+index); - - for (S32 i = index; i < mRiggedFace[type].size(); ++i) - { //bump indexes of currently held faces down after removal - mRiggedFace[type][i]->setReferenceIndex(i); - } } LLVertexBufferAvatar::LLVertexBufferAvatar() diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index d758bb07f0..59f9cf7ddb 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -100,6 +100,9 @@ public: void beginRiggedFullbright(); void beginRiggedFullbrightShiny(); void beginRiggedShinySimple(); + void beginRiggedAlpha(); + void beginRiggedFullbrightAlpha(); + void beginRiggedGlow(); void endRigid(); void endImpostor(); @@ -108,6 +111,9 @@ public: void endRiggedFullbright(); void endRiggedFullbrightShiny(); void endRiggedShinySimple(); + void endRiggedAlpha(); + void endRiggedFullbrightAlpha(); + void endRiggedGlow(); void beginDeferredImpostor(); void beginDeferredRigid(); @@ -125,11 +131,14 @@ public: const LLVolumeFace& vol_face, U32 data_mask); - void renderRigged(LLVOAvatar* avatar, U32 type, const U32 data_mask); + void renderRigged(LLVOAvatar* avatar, U32 type, const U32 data_mask, bool glow = false); void renderRiggedSimple(LLVOAvatar* avatar); + void renderRiggedAlpha(LLVOAvatar* avatar); + void renderRiggedFullbrightAlpha(LLVOAvatar* avatar); void renderRiggedFullbright(LLVOAvatar* avatar); void renderRiggedShinySimple(LLVOAvatar* avatar); void renderRiggedFullbrightShiny(LLVOAvatar* avatar); + void renderRiggedGlow(LLVOAvatar* avatar); /*virtual*/ LLViewerTexture *getDebugTexture(); /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display @@ -151,7 +160,7 @@ public: void addRiggedFace(LLFace* facep, U32 type); - void removeRiggedFace(LLFace* facep, U32 type = RIGGED_UNKNOWN); + void removeRiggedFace(LLFace* facep); std::vector mRiggedFace[NUM_RIGGED_PASSES]; diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 2b8fdf2e58..f9e9c3e078 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -260,6 +260,8 @@ private: S32 mTEOffset; S32 mReferenceIndex; + std::vector mRiggedIndex; + F32 mVSize; F32 mPixelArea; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 43252c553c..e263f8d937 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3545,7 +3545,21 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } //add face to new pool - if (te->getShiny()) + LLViewerTexture* tex = facep->getTexture(); + U32 type = gPipeline.getPoolTypeFromTE(te, tex); + + if (type == LLDrawPool::POOL_ALPHA) + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); + } + } + else if (te->getShiny()) { if (te->getFullbright()) { @@ -3567,6 +3581,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); } } + + if (te->getGlow()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW); + } } } -- cgit v1.3 From eb283701afc7ecbe3009a9fb75be1dcb222a383b Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 4 May 2010 00:45:28 -0500 Subject: Deferred pipeline integration of rigged attachments and cleanup. --- indra/llrender/llvertexbuffer.h | 2 +- .../shaders/class1/deferred/alphaF.glsl | 5 +- .../shaders/class1/deferred/alphaV.glsl | 2 +- .../shaders/class1/deferred/avatarAlphaV.glsl | 4 +- .../shaders/class1/deferred/diffuseV.glsl | 2 +- .../shaders/class2/deferred/alphaF.glsl | 2 +- indra/newview/lldrawpoolavatar.cpp | 302 +++++++++++++++------ indra/newview/lldrawpoolavatar.h | 51 +++- indra/newview/lldrawpoolbump.cpp | 27 +- indra/newview/lldrawpoolbump.h | 7 +- indra/newview/llviewershadermgr.cpp | 36 ++- indra/newview/llviewershadermgr.h | 2 + indra/newview/llvovolume.cpp | 15 + 13 files changed, 359 insertions(+), 98 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 225237215c..d1700aa54a 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -190,7 +190,7 @@ public: U8* getIndicesPointer() const { return useVBOs() ? NULL : mMappedIndexData; } U8* getVerticesPointer() const { return useVBOs() ? NULL : mMappedData; } S32 getStride() const { return mStride; } - S32 getTypeMask() const { return mTypeMask; } + U32 getTypeMask() const { return mTypeMask; } BOOL hasDataType(S32 type) const { return ((1 << type) & getTypeMask()) ? TRUE : FALSE; } S32 getSize() const { return mNumVerts*mStride; } S32 getIndicesSize() const { return mNumIndices * sizeof(U16); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index fea2e16090..6f027de6a2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -22,7 +22,6 @@ varying vec3 vary_ambient; varying vec3 vary_directional; varying vec3 vary_fragcoord; varying vec3 vary_position; -varying vec3 vary_light; uniform mat4 inv_proj; @@ -55,8 +54,8 @@ void main() color.rgb = scaleSoftClip(color.rgb); - //gl_FragColor = gl_Color; - gl_FragColor = color; + gl_FragColor = gl_Color; + //gl_FragColor = color; //gl_FragColor = vec4(1,0,1,1); //gl_FragColor = vec4(1,0,1,1)*shadow; diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index 04e556c11a..43200f1b07 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -36,7 +36,7 @@ void main() vec4 pos = (gl_ModelViewMatrix * gl_Vertex); vec3 norm = normalize(gl_NormalMatrix * gl_Normal); - vary_position = pos.xyz + norm.xyz * (-pos.z/64.0*shadow_offset+shadow_bias); + vary_position = pos.xyz; calcAtmospherics(pos.xyz); diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl index 650fbcc3f5..da1dafda36 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl @@ -17,7 +17,7 @@ vec3 atmosAffectDirectionalLight(float lightIntensity); vec3 scaleDownLight(vec3 light); vec3 scaleUpLight(vec3 light); -varying vec4 vary_position; +varying vec3 vary_position; varying vec3 vary_ambient; varying vec3 vary_directional; varying vec3 vary_normal; @@ -41,7 +41,7 @@ void main() norm = normalize(norm); gl_Position = gl_ProjectionMatrix * pos; - vary_position = pos; + vary_position = pos.xyz; vary_normal = norm; calcAtmospherics(pos.xyz); diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl index b458842657..44468cdfa2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl @@ -13,7 +13,7 @@ void main() gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - vary_nomral = normalize(gl_NormalMatrix * gl_Normal); + vary_normal = normalize(gl_NormalMatrix * gl_Normal); gl_FrontColor = gl_Color; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index 665fe16b43..fa6b4e2afb 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -115,7 +115,7 @@ void main() //gl_FragColor = gl_Color; gl_FragColor = color; - //gl_FragColor = vec4(1,0,1,1)*shadow; + //gl_FragColor = vec4(1,shadow,1,1); } diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 866aea42c4..ac599caa5b 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -63,6 +63,8 @@ LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL; BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE; BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE; +static bool is_deferred_render = false; + extern BOOL gUseGLPick; F32 CLOTHING_GRAVITY_EFFECT = 0.7f; @@ -100,6 +102,18 @@ S32 specular_channel = -1; S32 diffuse_channel = -1; S32 cube_channel = -1; +static const U32 rigged_data_mask[] = { + LLDrawPoolAvatar::RIGGED_SIMPLE_MASK, + LLDrawPoolAvatar::RIGGED_FULLBRIGHT_MASK, + LLDrawPoolAvatar::RIGGED_SHINY_MASK, + LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY_MASK, + LLDrawPoolAvatar::RIGGED_GLOW_MASK, + LLDrawPoolAvatar::RIGGED_ALPHA_MASK, + LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA_MASK, + LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP_MASK, + LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE_MASK, +}; + static LLFastTimer::DeclareTimer FTM_SHADOW_AVATAR("Avatar Shadow"); @@ -155,21 +169,17 @@ LLMatrix4& LLDrawPoolAvatar::getModelView() //----------------------------------------------------------------------------- -S32 LLDrawPoolAvatar::getNumDeferredPasses() -{ - return getNumPasses(); -} void LLDrawPoolAvatar::beginDeferredPass(S32 pass) { LLFastTimer t(FTM_RENDER_CHARACTERS); sSkipTransparent = TRUE; - + is_deferred_render = true; + if (LLPipeline::sImpostorRender) - { - beginDeferredSkinned(); - return; + { //impostor pass does not have rigid or impostor rendering + pass += 2; } switch (pass) @@ -184,7 +194,10 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass) beginDeferredSkinned(); break; case 3: - beginDeferredRigged(); + beginDeferredRiggedSimple(); + break; + case 4: + beginDeferredRiggedBump(); break; } } @@ -194,11 +207,11 @@ void LLDrawPoolAvatar::endDeferredPass(S32 pass) LLFastTimer t(FTM_RENDER_CHARACTERS); sSkipTransparent = FALSE; + is_deferred_render = false; if (LLPipeline::sImpostorRender) { - endDeferredSkinned(); - return; + pass += 2; } switch (pass) @@ -213,7 +226,11 @@ void LLDrawPoolAvatar::endDeferredPass(S32 pass) endDeferredSkinned(); break; case 3: - endDeferredRigged(); + endDeferredRiggedSimple(); + break; + case 4: + endDeferredRiggedBump(); + break; } } @@ -224,10 +241,35 @@ void LLDrawPoolAvatar::renderDeferred(S32 pass) S32 LLDrawPoolAvatar::getNumPostDeferredPasses() { - return 1; + return 6; } void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) +{ + switch (pass) + { + case 0: + beginPostDeferredAlpha(); + break; + case 1: + beginRiggedFullbright(); + break; + case 2: + beginRiggedFullbrightShiny(); + break; + case 3: + beginDeferredRiggedAlpha(); + break; + case 4: + beginRiggedFullbrightAlpha(); + break; + case 5: + beginRiggedGlow(); + break; + } +} + +void LLDrawPoolAvatar::beginPostDeferredAlpha() { sSkipOpaque = TRUE; sShaderLevel = mVertexShaderLevel; @@ -240,7 +282,49 @@ void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); } +void LLDrawPoolAvatar::beginDeferredRiggedAlpha() +{ + sVertexProgram = &gDeferredSkinnedAlphaProgram; + gPipeline.bindDeferredShader(*sVertexProgram); + diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); + gPipeline.enableLightsDynamic(); +} + +void LLDrawPoolAvatar::endDeferredRiggedAlpha() +{ + LLVertexBuffer::unbind(); + gPipeline.unbindDeferredShader(*sVertexProgram); + LLVertexBuffer::sWeight4Loc = -1; + sVertexProgram = NULL; +} + void LLDrawPoolAvatar::endPostDeferredPass(S32 pass) +{ + switch (pass) + { + case 0: + endPostDeferredAlpha(); + break; + case 1: + endRiggedFullbright(); + break; + case 2: + endRiggedFullbrightShiny(); + break; + case 3: + endDeferredRiggedAlpha(); + break; + case 4: + endRiggedFullbrightAlpha(); + break; + case 5: + endRiggedGlow(); + break; + } +} + +void LLDrawPoolAvatar::endPostDeferredAlpha() { // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done sRenderingSkinned = FALSE; @@ -254,7 +338,17 @@ void LLDrawPoolAvatar::endPostDeferredPass(S32 pass) void LLDrawPoolAvatar::renderPostDeferred(S32 pass) { - render(2); //pass 2 = skinned + const S32 actual_pass[] = + { //map post deferred pass numbers to what render() expects + 2, //skinned + 4, // rigged fullbright + 6, //rigged fullbright shiny + 7, //rigged alpha + 8, //rigged fullbright alpha + 9, //rigged glow + }; + + render(actual_pass[pass]); } @@ -288,6 +382,7 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass) else { sVertexProgram = &gDeferredAttachmentShadowProgram; + diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->bind(); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -352,7 +447,12 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) } else { - avatarp->renderSkinnedAttachments(); + renderRigged(avatarp, RIGGED_SIMPLE); + renderRigged(avatarp, RIGGED_ALPHA); + renderRigged(avatarp, RIGGED_FULLBRIGHT); + renderRigged(avatarp, RIGGED_FULLBRIGHT_SHINY); + renderRigged(avatarp, RIGGED_SHINY); + renderRigged(avatarp, RIGGED_FULLBRIGHT_ALPHA); } } @@ -360,7 +460,7 @@ S32 LLDrawPoolAvatar::getNumPasses() { if (LLPipeline::sImpostorRender) { - return 1; + return 8; } else if (getVertexShaderLevel() > 0) { @@ -372,6 +472,19 @@ S32 LLDrawPoolAvatar::getNumPasses() } } +S32 LLDrawPoolAvatar::getNumDeferredPasses() +{ + if (LLPipeline::sImpostorRender) + { + return 3; + } + else + { + return 5; + } +} + + void LLDrawPoolAvatar::render(S32 pass) { LLFastTimer t(FTM_RENDER_CHARACTERS); @@ -391,9 +504,8 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) LLVertexBuffer::unbind(); if (LLPipeline::sImpostorRender) - { - beginSkinned(); - return; + { //impostor render does not have impostors or rigid rendering + pass += 2; } switch (pass) @@ -437,8 +549,7 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass) if (LLPipeline::sImpostorRender) { - endSkinned(); - return; + pass += 2; } switch (pass) @@ -536,8 +647,8 @@ void LLDrawPoolAvatar::beginDeferredImpostor() sVertexProgram = &gDeferredImpostorProgram; - normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); + normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->bind(); @@ -774,18 +885,40 @@ void LLDrawPoolAvatar::endRiggedFullbrightShiny() } -void LLDrawPoolAvatar::beginDeferredRigged() +void LLDrawPoolAvatar::beginDeferredRiggedSimple() { sVertexProgram = &gDeferredSkinnedDiffuseProgram; + diffuse_channel = 0; + sVertexProgram->bind(); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); +} + +void LLDrawPoolAvatar::endDeferredRiggedSimple() +{ + LLVertexBuffer::unbind(); + sVertexProgram->unbind(); + LLVertexBuffer::sWeight4Loc = -1; + sVertexProgram = NULL; +} + +void LLDrawPoolAvatar::beginDeferredRiggedBump() +{ + sVertexProgram = &gDeferredSkinnedBumpProgram; sVertexProgram->bind(); + normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); + diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } -void LLDrawPoolAvatar::endDeferredRigged() +void LLDrawPoolAvatar::endDeferredRiggedBump() { LLVertexBuffer::unbind(); + sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP); + sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->unbind(); LLVertexBuffer::sWeight4Loc = -1; + normal_channel = -1; + diffuse_channel = -1; sVertexProgram = NULL; } @@ -933,13 +1066,28 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) if (pass == 3) { - renderRiggedSimple(avatarp); + if (is_deferred_render) + { + renderDeferredRiggedSimple(avatarp); + } + else + { + renderRiggedSimple(avatarp); + } return; } if (pass == 4) { - renderRiggedFullbright(avatarp); + if (is_deferred_render) + { + renderDeferredRiggedBump(avatarp); + } + else + { + renderRiggedFullbright(avatarp); + } + return; } @@ -995,6 +1143,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) renderRiggedGlow(avatarp); gGL.setColorMask(true, false); gGL.setSceneBlendType(LLRender::BT_ALPHA); + return; } @@ -1034,12 +1183,21 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) } } -void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face, U32 data_mask) +void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face) { + U32 data_mask = 0; + for (U32 i = 0; i < face->mRiggedIndex.size(); ++i) + { + if (face->mRiggedIndex[i] > -1) + { + data_mask |= rigged_data_mask[i]; + } + } + LLVertexBuffer* buff = face->mVertexBuffer; if (!buff || - !buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) || + buff->getTypeMask() != data_mask || buff->getRequestedVerts() != vol_face.mVertices.size()) { face->setGeomIndex(0); @@ -1067,7 +1225,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSk } } -void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, const U32 data_mask, bool glow) +void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { for (U32 i = 0; i < mRiggedFace[type].size(); ++i) { @@ -1106,8 +1264,10 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, const U32 data } const LLVolumeFace& vol_face = volume->getVolumeFace(te); - updateRiggedFaceVertexBuffer(face, skin, volume, vol_face, data_mask); + updateRiggedFaceVertexBuffer(face, skin, volume, vol_face); + U32 data_mask = rigged_data_mask[type]; + LLVertexBuffer* buff = face->mVertexBuffer; if (buff) @@ -1145,84 +1305,72 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, const U32 data glColor4f(0,0,0,face->getTextureEntry()->getGlow()); } - gGL.getTexUnit(0)->bind(face->getTexture()); - buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); + gGL.getTexUnit(diffuse_channel)->bind(face->getTexture()); + if (normal_channel > -1) + { + LLDrawPoolBump::bindBumpMap(face, normal_channel); + } + + if (face->mTextureMatrix) + { + glMatrixMode(GL_TEXTURE); + glLoadMatrixf((F32*) face->mTextureMatrix->mMatrix); + buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + } + else + { + buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); + } } } } -void LLDrawPoolAvatar::renderRiggedSimple(LLVOAvatar* avatar) +void LLDrawPoolAvatar::renderDeferredRiggedSimple(LLVOAvatar* avatar) { - const U32 data_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4; + renderRigged(avatar, RIGGED_DEFERRED_SIMPLE); +} - renderRigged(avatar, RIGGED_SIMPLE, data_mask); +void LLDrawPoolAvatar::renderDeferredRiggedBump(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_DEFERRED_BUMP); } -void LLDrawPoolAvatar::renderRiggedFullbright(LLVOAvatar* avatar) +void LLDrawPoolAvatar::renderRiggedSimple(LLVOAvatar* avatar) { - const U32 data_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4; + renderRigged(avatar, RIGGED_SIMPLE); +} - renderRigged(avatar, RIGGED_FULLBRIGHT, data_mask); +void LLDrawPoolAvatar::renderRiggedFullbright(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_FULLBRIGHT); } void LLDrawPoolAvatar::renderRiggedShinySimple(LLVOAvatar* avatar) { - const U32 data_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4; - - renderRigged(avatar, RIGGED_SHINY, data_mask); + renderRigged(avatar, RIGGED_SHINY); } void LLDrawPoolAvatar::renderRiggedFullbrightShiny(LLVOAvatar* avatar) { - const U32 data_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4; - - renderRigged(avatar, RIGGED_FULLBRIGHT_SHINY, data_mask); + renderRigged(avatar, RIGGED_FULLBRIGHT_SHINY); } void LLDrawPoolAvatar::renderRiggedAlpha(LLVOAvatar* avatar) { - const U32 data_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4; - - renderRigged(avatar, RIGGED_ALPHA, data_mask); + renderRigged(avatar, RIGGED_ALPHA); } void LLDrawPoolAvatar::renderRiggedFullbrightAlpha(LLVOAvatar* avatar) { - const U32 data_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4; - - renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA, data_mask); + renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA); } void LLDrawPoolAvatar::renderRiggedGlow(LLVOAvatar* avatar) { - const U32 data_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_WEIGHT4; - - renderRigged(avatar, RIGGED_GLOW, data_mask, true); + renderRigged(avatar, RIGGED_GLOW, true); } diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 59f9cf7ddb..bab6f01480 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -103,6 +103,8 @@ public: void beginRiggedAlpha(); void beginRiggedFullbrightAlpha(); void beginRiggedGlow(); + void beginPostDeferredAlpha(); + void beginDeferredRiggedAlpha(); void endRigid(); void endImpostor(); @@ -114,24 +116,27 @@ public: void endRiggedAlpha(); void endRiggedFullbrightAlpha(); void endRiggedGlow(); + void endPostDeferredAlpha(); + void endDeferredRiggedAlpha(); void beginDeferredImpostor(); void beginDeferredRigid(); void beginDeferredSkinned(); - void beginDeferredRigged(); + void beginDeferredRiggedSimple(); + void beginDeferredRiggedBump(); void endDeferredImpostor(); void endDeferredRigid(); void endDeferredSkinned(); - void endDeferredRigged(); + void endDeferredRiggedSimple(); + void endDeferredRiggedBump(); void updateRiggedFaceVertexBuffer(LLFace* facep, const LLMeshSkinInfo* skin, LLVolume* volume, - const LLVolumeFace& vol_face, - U32 data_mask); + const LLVolumeFace& vol_face); - void renderRigged(LLVOAvatar* avatar, U32 type, const U32 data_mask, bool glow = false); + void renderRigged(LLVOAvatar* avatar, U32 type, bool glow = false); void renderRiggedSimple(LLVOAvatar* avatar); void renderRiggedAlpha(LLVOAvatar* avatar); void renderRiggedFullbrightAlpha(LLVOAvatar* avatar); @@ -139,6 +144,8 @@ public: void renderRiggedShinySimple(LLVOAvatar* avatar); void renderRiggedFullbrightShiny(LLVOAvatar* avatar); void renderRiggedGlow(LLVOAvatar* avatar); + void renderDeferredRiggedSimple(LLVOAvatar* avatar); + void renderDeferredRiggedBump(LLVOAvatar* avatar); /*virtual*/ LLViewerTexture *getDebugTexture(); /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display @@ -154,11 +161,43 @@ public: RIGGED_GLOW, RIGGED_ALPHA, RIGGED_FULLBRIGHT_ALPHA, + RIGGED_DEFERRED_BUMP, + RIGGED_DEFERRED_SIMPLE, NUM_RIGGED_PASSES, RIGGED_UNKNOWN, } eRiggedPass; - + typedef enum + { + RIGGED_SIMPLE_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4, + RIGGED_FULLBRIGHT_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4, + RIGGED_SHINY_MASK = RIGGED_SIMPLE_MASK, + RIGGED_FULLBRIGHT_SHINY_MASK = RIGGED_SIMPLE_MASK, + RIGGED_GLOW_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_WEIGHT4, + RIGGED_ALPHA_MASK = RIGGED_SIMPLE_MASK, + RIGGED_FULLBRIGHT_ALPHA_MASK = RIGGED_FULLBRIGHT_MASK, + RIGGED_DEFERRED_BUMP_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_BINORMAL | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4, + RIGGED_DEFERRED_SIMPLE_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4, + } eRiggedDataMask; + void addRiggedFace(LLFace* facep, U32 type); void removeRiggedFace(LLFace* facep); diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 2f449fa42f..906615ade8 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -591,18 +591,37 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL // static BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel) { - LLViewerTexture* bump = NULL; - U8 bump_code = params.mBump; + return bindBumpMap(bump_code, params.mTexture, params.mVSize, channel); +} + +//static +BOOL LLDrawPoolBump::bindBumpMap(LLFace* face, S32 channel) +{ + const LLTextureEntry* te = face->getTextureEntry(); + if (te) + { + U8 bump_code = te->getBumpmap(); + return bindBumpMap(bump_code, face->getTexture(), face->getVirtualSize(), channel); + } + + return FALSE; +} + +//static +BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsize, S32 channel) +{ //Note: texture atlas does not support bump texture now. - LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(params.mTexture) ; + LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(texture) ; if(!tex) { //if the texture is not a fetched texture return FALSE; } + LLViewerTexture* bump = NULL; + switch( bump_code ) { case BE_NO_BUMP: @@ -616,7 +635,7 @@ BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel) if( bump_code < LLStandardBumpmap::sStandardBumpmapCount ) { bump = gStandardBumpmapList[bump_code].mImage; - gBumpImageList.addTextureStats(bump_code, tex->getID(), params.mVSize); + gBumpImageList.addTextureStats(bump_code, tex->getID(), vsize); } break; } diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h index 89bbefe778..127c9efe85 100644 --- a/indra/newview/lldrawpoolbump.h +++ b/indra/newview/lldrawpoolbump.h @@ -93,7 +93,12 @@ public: /*virtual*/ void endPostDeferredPass(S32 pass); /*virtual*/ void renderPostDeferred(S32 pass); - BOOL bindBumpMap(LLDrawInfo& params, S32 channel = -2); + static BOOL bindBumpMap(LLDrawInfo& params, S32 channel = -2); + static BOOL bindBumpMap(LLFace* face, S32 channel = -2); + +private: + static BOOL bindBumpMap(U8 bump_code, LLViewerTexture* tex, F32 vsize, S32 channel); + }; enum EBumpEffect diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index eafc52748e..e64fdfc0b4 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -114,6 +114,8 @@ LLGLSLShader gDeferredEdgeProgram; LLGLSLShader gDeferredWaterProgram; LLGLSLShader gDeferredDiffuseProgram; LLGLSLShader gDeferredSkinnedDiffuseProgram; +LLGLSLShader gDeferredSkinnedBumpProgram; +LLGLSLShader gDeferredSkinnedAlphaProgram; LLGLSLShader gDeferredBumpProgram; LLGLSLShader gDeferredTerrainProgram; LLGLSLShader gDeferredTreeProgram; @@ -173,6 +175,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gDeferredLightProgram); mShaderList.push_back(&gDeferredMultiLightProgram); mShaderList.push_back(&gDeferredAlphaProgram); + mShaderList.push_back(&gDeferredSkinnedAlphaProgram); mShaderList.push_back(&gDeferredFullbrightProgram); mShaderList.push_back(&gDeferredPostGIProgram); mShaderList.push_back(&gDeferredEdgeProgram); @@ -591,6 +594,8 @@ void LLViewerShaderMgr::unloadShaders() gDeferredDiffuseProgram.unload(); gDeferredSkinnedDiffuseProgram.unload(); + gDeferredSkinnedBumpProgram.unload(); + gDeferredSkinnedAlphaProgram.unload(); mVertexShaderLevel[SHADER_LIGHTING] = 0; mVertexShaderLevel[SHADER_OBJECT] = 0; @@ -906,6 +911,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredTreeProgram.unload(); gDeferredDiffuseProgram.unload(); gDeferredSkinnedDiffuseProgram.unload(); + gDeferredSkinnedBumpProgram.unload(); + gDeferredSkinnedAlphaProgram.unload(); gDeferredBumpProgram.unload(); gDeferredImpostorProgram.unload(); gDeferredTerrainProgram.unload(); @@ -958,6 +965,33 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredSkinnedDiffuseProgram.createShader(NULL, NULL); } + if (success) + { + gDeferredSkinnedBumpProgram.mName = "Deferred Skinned Bump Shader"; + gDeferredSkinnedBumpProgram.mFeatures.hasObjectSkinning = true; + gDeferredSkinnedBumpProgram.mShaderFiles.clear(); + gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSkinnedBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredSkinnedBumpProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredSkinnedAlphaProgram.mName = "Deferred Skinned Alpha Shader"; + gDeferredSkinnedAlphaProgram.mFeatures.hasObjectSkinning = true; + gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true; + gDeferredSkinnedAlphaProgram.mFeatures.calculatesAtmospherics = true; + gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true; + gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true; + gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true; + gDeferredSkinnedAlphaProgram.mShaderFiles.clear(); + gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSkinnedAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredSkinnedAlphaProgram.createShader(NULL, NULL); + } + if (success) { gDeferredBumpProgram.mName = "Deferred Bump Shader"; @@ -1176,7 +1210,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true; gDeferredAvatarAlphaProgram.mShaderFiles.clear(); gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredAvatarAlphaProgram.createShader(&mAvatarAttribs, &mAvatarUniforms); } diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index bb28cd7ec2..da16a38427 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -350,6 +350,8 @@ extern LLGLSLShader gDeferredEdgeProgram; extern LLGLSLShader gDeferredWaterProgram; extern LLGLSLShader gDeferredDiffuseProgram; extern LLGLSLShader gDeferredSkinnedDiffuseProgram; +extern LLGLSLShader gDeferredSkinnedBumpProgram; +extern LLGLSLShader gDeferredSkinnedAlphaProgram; extern LLGLSLShader gDeferredBumpProgram; extern LLGLSLShader gDeferredTerrainProgram; extern LLGLSLShader gDeferredTreeProgram; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index e263f8d937..220634897e 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3586,6 +3586,21 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW); } + + if (LLPipeline::sRenderDeferred) + { + if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) + { + if (te->getBumpmap()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); + } + } + } } } -- cgit v1.3 From 744f2e4951fc6fc1a1f08e97fc446e909c1fe39e Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 4 May 2010 12:14:47 -0500 Subject: Cleanup from review. --- indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl | 3 +-- indra/newview/lldrawpoolavatar.cpp | 2 +- indra/newview/llvovolume.cpp | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index 6f027de6a2..7d18ae5036 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -54,8 +54,7 @@ void main() color.rgb = scaleSoftClip(color.rgb); - gl_FragColor = gl_Color; - //gl_FragColor = color; + gl_FragColor = color; //gl_FragColor = vec4(1,0,1,1); //gl_FragColor = vec4(1,0,1,1)*shadow; diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index ac599caa5b..a49cf8781e 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1103,7 +1103,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) return; } - if (pass >= 7 && pass <= 9) + if (pass >= 7 && pass < 9) { LLGLEnable blend(GL_BLEND); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 220634897e..1ed8da85a8 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3418,7 +3418,7 @@ void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group) static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_VB("Volume"); static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt"); -LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) +static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) { LLVOAvatar* avatar = vobj->getAvatar(); -- cgit v1.3 From 49579bebdd274a88c2381c4cab3d09ecd393564d Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 10 May 2010 13:00:36 -0500 Subject: Fix for wierd triangle shadow bug and fix for ATI hating deferred rendering. --- indra/llrender/llrender.cpp | 1 + .../shaders/class2/deferred/avatarAlphaV.glsl | 3 +- indra/newview/featuretable.txt | 1 + indra/newview/lldrawpoolavatar.cpp | 43 ++++++++++++---------- indra/newview/lldrawpoolavatar.h | 4 +- indra/newview/llviewerjointmesh.cpp | 30 ++++++++------- indra/newview/pipeline.cpp | 2 +- 7 files changed, 47 insertions(+), 37 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 43662fbb5c..2472339ec4 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -165,6 +165,7 @@ void LLTexUnit::enable(eTextureType type) if ( (mCurrTexType != type || gGL.mDirty) && (type != TT_NONE) ) { activate(); + if (mCurrTexType != TT_NONE && !gGL.mDirty) { disable(); // Force a disable of a previous texture type if it's enabled. diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl index f8dd1b7431..de423ee22a 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl @@ -21,6 +21,7 @@ varying vec3 vary_position; varying vec3 vary_ambient; varying vec3 vary_directional; varying vec3 vary_normal; +varying vec3 vary_fragcoord; uniform float near_clip; uniform float shadow_offset; @@ -77,7 +78,7 @@ void main() gl_FrontColor = col; gl_FogFragCoord = pos.z; - + vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); } diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 1913f52499..74d14c49b0 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -57,6 +57,7 @@ RenderShaderLightingMaxLevel 1 3 RenderDeferred 1 1 RenderDeferredSSAO 1 1 RenderShadowDetail 1 2 +RenderUseFBO 1 1 // diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index a49cf8781e..d1f4be71f5 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -62,6 +62,8 @@ static U32 sShaderLevel = 0; LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL; BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE; BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE; +S32 LLDrawPoolAvatar::sDiffuseChannel = 0; + static bool is_deferred_render = false; @@ -99,7 +101,6 @@ BOOL gAvatarEmbossBumpMap = FALSE; static BOOL sRenderingSkinned = FALSE; S32 normal_channel = -1; S32 specular_channel = -1; -S32 diffuse_channel = -1; S32 cube_channel = -1; static const U32 rigged_data_mask[] = { @@ -279,6 +280,7 @@ void LLDrawPoolAvatar::beginPostDeferredAlpha() gPipeline.bindDeferredShader(*sVertexProgram); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); } @@ -286,7 +288,7 @@ void LLDrawPoolAvatar::beginDeferredRiggedAlpha() { sVertexProgram = &gDeferredSkinnedAlphaProgram; gPipeline.bindDeferredShader(*sVertexProgram); - diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); gPipeline.enableLightsDynamic(); } @@ -295,6 +297,7 @@ void LLDrawPoolAvatar::endDeferredRiggedAlpha() { LLVertexBuffer::unbind(); gPipeline.unbindDeferredShader(*sVertexProgram); + sDiffuseChannel = 0; LLVertexBuffer::sWeight4Loc = -1; sVertexProgram = NULL; } @@ -332,7 +335,7 @@ void LLDrawPoolAvatar::endPostDeferredAlpha() disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); gPipeline.unbindDeferredShader(*sVertexProgram); - + sDiffuseChannel = 0; sShaderLevel = mVertexShaderLevel; } @@ -382,7 +385,7 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass) else { sVertexProgram = &gDeferredAttachmentShadowProgram; - diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->bind(); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -596,7 +599,7 @@ void LLDrawPoolAvatar::beginImpostor() } gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); - diffuse_channel = 0; + sDiffuseChannel = 0; } void LLDrawPoolAvatar::endImpostor() @@ -649,7 +652,7 @@ void LLDrawPoolAvatar::beginDeferredImpostor() specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); - diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->bind(); } @@ -772,7 +775,7 @@ void LLDrawPoolAvatar::endSkinned() void LLDrawPoolAvatar::beginRiggedSimple() { sVertexProgram = &gSkinnedObjectSimpleProgram; - diffuse_channel = 0; + sDiffuseChannel = 0; gSkinnedObjectSimpleProgram.bind(); LLVertexBuffer::sWeight4Loc = gSkinnedObjectSimpleProgram.getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -788,7 +791,7 @@ void LLDrawPoolAvatar::endRiggedSimple() void LLDrawPoolAvatar::beginRiggedAlpha() { sVertexProgram = &gSkinnedObjectSimpleProgram; - diffuse_channel = 0; + sDiffuseChannel = 0; sVertexProgram->bind(); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -805,7 +808,7 @@ void LLDrawPoolAvatar::endRiggedAlpha() void LLDrawPoolAvatar::beginRiggedFullbrightAlpha() { sVertexProgram = &gSkinnedObjectFullbrightProgram; - diffuse_channel = 0; + sDiffuseChannel = 0; sVertexProgram->bind(); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -821,7 +824,7 @@ void LLDrawPoolAvatar::endRiggedFullbrightAlpha() void LLDrawPoolAvatar::beginRiggedGlow() { sVertexProgram = &gSkinnedObjectFullbrightProgram; - diffuse_channel = 0; + sDiffuseChannel = 0; sVertexProgram->bind(); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -837,7 +840,7 @@ void LLDrawPoolAvatar::endRiggedGlow() void LLDrawPoolAvatar::beginRiggedFullbright() { sVertexProgram = &gSkinnedObjectFullbrightProgram; - diffuse_channel = 0; + sDiffuseChannel = 0; gSkinnedObjectFullbrightProgram.bind(); LLVertexBuffer::sWeight4Loc = gSkinnedObjectFullbrightProgram.getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -854,14 +857,14 @@ void LLDrawPoolAvatar::beginRiggedShinySimple() { sVertexProgram = &gSkinnedObjectShinySimpleProgram; sVertexProgram->bind(); - LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, diffuse_channel, cube_channel, false); + LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } void LLDrawPoolAvatar::endRiggedShinySimple() { LLVertexBuffer::unbind(); - LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, diffuse_channel, cube_channel, false); + LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); sVertexProgram->unbind(); sVertexProgram = NULL; LLVertexBuffer::sWeight4Loc = -1; @@ -871,14 +874,14 @@ void LLDrawPoolAvatar::beginRiggedFullbrightShiny() { sVertexProgram = &gSkinnedObjectFullbrightShinyProgram; sVertexProgram->bind(); - LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, diffuse_channel, cube_channel, false); + LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } void LLDrawPoolAvatar::endRiggedFullbrightShiny() { LLVertexBuffer::unbind(); - LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, diffuse_channel, cube_channel, false); + LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); sVertexProgram->unbind(); sVertexProgram = NULL; LLVertexBuffer::sWeight4Loc = -1; @@ -888,7 +891,7 @@ void LLDrawPoolAvatar::endRiggedFullbrightShiny() void LLDrawPoolAvatar::beginDeferredRiggedSimple() { sVertexProgram = &gDeferredSkinnedDiffuseProgram; - diffuse_channel = 0; + sDiffuseChannel = 0; sVertexProgram->bind(); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -906,7 +909,7 @@ void LLDrawPoolAvatar::beginDeferredRiggedBump() sVertexProgram = &gDeferredSkinnedBumpProgram; sVertexProgram->bind(); normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); - diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -918,7 +921,7 @@ void LLDrawPoolAvatar::endDeferredRiggedBump() sVertexProgram->unbind(); LLVertexBuffer::sWeight4Loc = -1; normal_channel = -1; - diffuse_channel = -1; + sDiffuseChannel = 0; sVertexProgram = NULL; } @@ -1047,7 +1050,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) avatarp->mImpostor.bindTexture(1, specular_channel); } } - avatarp->renderImpostor(LLColor4U(255,255,255,255), diffuse_channel); + avatarp->renderImpostor(LLColor4U(255,255,255,255), sDiffuseChannel); } return; } @@ -1305,7 +1308,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) glColor4f(0,0,0,face->getTextureEntry()->getGlow()); } - gGL.getTexUnit(diffuse_channel)->bind(face->getTexture()); + gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture()); if (normal_channel > -1) { LLDrawPoolBump::bindBumpMap(face, normal_channel); diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index bab6f01480..4a5b009412 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -1,4 +1,4 @@ -/** + /** * @file lldrawpoolavatar.h * @brief LLDrawPoolAvatar class definition * @@ -205,6 +205,8 @@ public: static BOOL sSkipOpaque; static BOOL sSkipTransparent; + static S32 sDiffuseChannel; + static LLGLSLShader* sVertexProgram; }; diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index fb6cc8d790..deb3d8fd97 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -516,6 +516,8 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) U32 triangle_count = 0; + S32 diffuse_channel = LLDrawPoolAvatar::sDiffuseChannel; + stop_glerror(); //---------------------------------------------------------------- @@ -541,7 +543,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) LLTexUnit::eTextureAddressMode old_mode = LLTexUnit::TAM_WRAP; if (mTestImageName) { - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTestImageName); + gGL.getTexUnit(diffuse_channel)->bindManual(LLTexUnit::TT_TEXTURE, mTestImageName); if (mIsTransparent) { @@ -550,18 +552,18 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) else { glColor4f(0.7f, 0.6f, 0.3f, 1.f); - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_LERP_TEX_ALPHA, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); + gGL.getTexUnit(diffuse_channel)->setTextureColorBlend(LLTexUnit::TBO_LERP_TEX_ALPHA, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); } } else if( !is_dummy && mLayerSet ) { if( mLayerSet->hasComposite() ) { - gGL.getTexUnit(0)->bind(mLayerSet->getComposite()); + gGL.getTexUnit(diffuse_channel)->bind(mLayerSet->getComposite()); } else { - gGL.getTexUnit(0)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT)); + gGL.getTexUnit(diffuse_channel)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT)); } } else @@ -571,25 +573,25 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) { old_mode = mTexture->getAddressMode(); } - gGL.getTexUnit(0)->bind(mTexture.get()); - gGL.getTexUnit(0)->bind(mTexture); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + gGL.getTexUnit(diffuse_channel)->bind(mTexture.get()); + gGL.getTexUnit(diffuse_channel)->bind(mTexture); + gGL.getTexUnit(diffuse_channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); } else { - gGL.getTexUnit(0)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT)); + gGL.getTexUnit(diffuse_channel)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT)); } if (gRenderForSelect) { if (isTransparent()) { - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_CONST_ALPHA); + gGL.getTexUnit(diffuse_channel)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); + gGL.getTexUnit(diffuse_channel)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_CONST_ALPHA); } else { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE); } } @@ -626,13 +628,13 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) if (mTestImageName) { - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + gGL.getTexUnit(diffuse_channel)->setTextureBlendType(LLTexUnit::TB_MULT); } if (mTexture.notNull() && !is_dummy) { - gGL.getTexUnit(0)->bind(mTexture); - gGL.getTexUnit(0)->setTextureAddressMode(old_mode); + gGL.getTexUnit(diffuse_channel)->bind(mTexture); + gGL.getTexUnit(diffuse_channel)->setTextureAddressMode(old_mode); } return triangle_count; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9bcec9e13d..da01ae44db 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -7778,7 +7778,7 @@ BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector 0,1, 1,2, 2,3, - 3,1, + 3,0, 4,5, 5,6, -- cgit v1.3 From 05a23f8dbaa45c64bcf6c55dd09a468ba2b1f144 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 21 May 2010 04:49:12 -0500 Subject: Vectorized memcpy. 16-byte aligned vertex buffers. (almost) fully vectorized avatar vertex buffer updating --- index buffers still need to be vectorized --- indra/llrender/llvertexbuffer.cpp | 195 +++++++++++++++++++++++++++++++++++- indra/llrender/llvertexbuffer.h | 7 +- indra/newview/lldrawpoolavatar.cpp | 4 +- indra/newview/llpolymesh.cpp | 25 +++-- indra/newview/llviewerjointmesh.cpp | 169 +++++++++++-------------------- 5 files changed, 273 insertions(+), 127 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 7fa47cd171..a50eb7211c 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -39,6 +39,7 @@ #include "llglheaders.h" #include "llmemtype.h" #include "llrender.h" +#include "llvector4a.h" //============================================================================ @@ -66,6 +67,27 @@ S32 LLVertexBuffer::sWeight4Loc = -1; std::vector LLVertexBuffer::sDeleteList; +#define LL_ALIGNED_VB 1 + +#if LL_ALIGNED_VB + +S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] = +{ + sizeof(LLVector4), // TYPE_VERTEX, + sizeof(LLVector4), // TYPE_NORMAL, + sizeof(LLVector2), // TYPE_TEXCOORD0, + sizeof(LLVector2), // TYPE_TEXCOORD1, + sizeof(LLVector2), // TYPE_TEXCOORD2, + sizeof(LLVector2), // TYPE_TEXCOORD3, + sizeof(LLColor4U), // TYPE_COLOR, + sizeof(LLVector4), // TYPE_BINORMAL, + sizeof(F32), // TYPE_WEIGHT, + sizeof(LLVector4), // TYPE_WEIGHT4, + sizeof(LLVector4), // TYPE_CLOTHWEIGHT, +}; + +#else + S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] = { sizeof(LLVector3), // TYPE_VERTEX, @@ -81,6 +103,8 @@ S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] = sizeof(LLVector4), // TYPE_CLOTHWEIGHT, }; +#endif + U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] = { GL_TRIANGLES, @@ -428,11 +452,41 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : mTypeMask = typemask; mStride = stride; + mAlignedOffset = 0; + sCount++; } +#if LL_ALIGNED_VB +//static +S32 LLVertexBuffer::calcStride(const U32& typemask, S32* offsets, S32 num_vertices) +{ + S32 offset = 0; + for (S32 i=0; i(src); + mAlignedOffset = mMappedData - src; + stop_glerror(); } { @@ -975,6 +1042,45 @@ void LLVertexBuffer::unmapBuffer() //---------------------------------------------------------------------------- +#if LL_ALIGNED_VB + +template struct VertexBufferStrider +{ + typedef LLStrider strider_t; + static bool get(LLVertexBuffer& vbo, + strider_t& strider, + S32 index) + { + if (vbo.mapBuffer() == NULL) + { + llwarns << "mapBuffer failed!" << llendl; + return FALSE; + } + + if (type == LLVertexBuffer::TYPE_INDEX) + { + S32 stride = sizeof(T); + strider = (T*)(vbo.getMappedIndices() + index*stride); + strider.setStride(0); + return TRUE; + } + else if (vbo.hasDataType(type)) + { + S32 stride = LLVertexBuffer::sTypeOffsets[type]; + strider = (T*)(vbo.getMappedData() + vbo.getOffset(type)+index*stride); + strider.setStride(stride); + return TRUE; + } + else + { + llerrs << "VertexBufferStrider could not find valid vertex data." << llendl; + } + return FALSE; + } +}; + +#else + template struct VertexBufferStrider { typedef LLStrider strider_t; @@ -1010,6 +1116,7 @@ template struct VertexBufferStrider } }; +#endif bool LLVertexBuffer::getVertexStrider(LLStrider& strider, S32 index) { @@ -1272,6 +1379,82 @@ void LLVertexBuffer::setBuffer(U32 data_mask) } } +#if LL_ALIGNED_VB + +// virtual (default) +void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const +{ + LLMemType mt2(LLMemType::MTYPE_VERTEX_SETUP_VERTEX_BUFFER); + stop_glerror(); + U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; + + if ((data_mask & mTypeMask) != data_mask) + { + llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl; + } + + + if (data_mask & MAP_NORMAL) + { + glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeOffsets[TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL])); + } + if (data_mask & MAP_TEXCOORD3) + { + glClientActiveTextureARB(GL_TEXTURE3_ARB); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeOffsets[TYPE_TEXCOORD3], (void*)(base + mOffsets[TYPE_TEXCOORD3])); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } + if (data_mask & MAP_TEXCOORD2) + { + glClientActiveTextureARB(GL_TEXTURE2_ARB); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeOffsets[TYPE_TEXCOORD2], (void*)(base + mOffsets[TYPE_TEXCOORD2])); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } + if (data_mask & MAP_TEXCOORD1) + { + glClientActiveTextureARB(GL_TEXTURE1_ARB); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeOffsets[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1])); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } + if (data_mask & MAP_BINORMAL) + { + glClientActiveTextureARB(GL_TEXTURE2_ARB); + glTexCoordPointer(3,GL_FLOAT, LLVertexBuffer::sTypeOffsets[TYPE_BINORMAL], (void*)(base + mOffsets[TYPE_BINORMAL])); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } + if (data_mask & MAP_TEXCOORD0) + { + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeOffsets[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); + } + if (data_mask & MAP_COLOR) + { + glColorPointer(4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeOffsets[TYPE_COLOR], (void*)(base + mOffsets[TYPE_COLOR])); + } + + if (data_mask & MAP_WEIGHT) + { + glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, LLVertexBuffer::sTypeOffsets[TYPE_WEIGHT], (void*)(base + mOffsets[TYPE_WEIGHT])); + } + + if (data_mask & MAP_WEIGHT4 && sWeight4Loc != -1) + { + glVertexAttribPointerARB(sWeight4Loc, 4, GL_FLOAT, FALSE, LLVertexBuffer::sTypeOffsets[TYPE_WEIGHT4], (void*)(base+mOffsets[TYPE_WEIGHT4])); + } + + if (data_mask & MAP_CLOTHWEIGHT) + { + glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, LLVertexBuffer::sTypeOffsets[TYPE_CLOTHWEIGHT], (void*)(base + mOffsets[TYPE_CLOTHWEIGHT])); + } + if (data_mask & MAP_VERTEX) + { + glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeOffsets[TYPE_VERTEX], (void*)(base + 0)); + } + + llglassertok(); +} + +#else + // virtual (default) void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const { @@ -1344,6 +1527,8 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const llglassertok(); } +#endif + void LLVertexBuffer::markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count) { // TODO: use GL_APPLE_flush_buffer_range here diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index d1700aa54a..03799af978 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -98,7 +98,7 @@ public: //if offsets is not NULL, its contents will be filled //with the offset of each vertex component in the buffer, // indexed by the following enum - static S32 calcStride(const U32& typemask, S32* offsets = NULL); + static S32 calcStride(const U32& typemask, S32* offsets = NULL, S32 num_vertices = 0); enum { TYPE_VERTEX, @@ -192,7 +192,7 @@ public: S32 getStride() const { return mStride; } U32 getTypeMask() const { return mTypeMask; } BOOL hasDataType(S32 type) const { return ((1 << type) & getTypeMask()) ? TRUE : FALSE; } - S32 getSize() const { return mNumVerts*mStride; } + S32 getSize() const; S32 getIndicesSize() const { return mNumIndices * sizeof(U16); } U8* getMappedData() const { return mMappedData; } U8* getMappedIndices() const { return mMappedIndexData; } @@ -213,6 +213,7 @@ protected: S32 mRequestedNumVerts; // Number of vertices requested S32 mRequestedNumIndices; // Number of indices requested + ptrdiff_t mAlignedOffset; S32 mStride; U32 mTypeMask; S32 mUsage; // GL usage @@ -227,7 +228,7 @@ protected: S32 mOffsets[TYPE_MAX]; BOOL mResized; // if TRUE, client buffer has been resized and GL buffer has not BOOL mDynamicSize; // if TRUE, buffer has been resized at least once (and should be padded) - + class DirtyRegion { public: diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index d1f4be71f5..1e9053239d 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1542,7 +1542,7 @@ LLVertexBufferAvatar::LLVertexBufferAvatar() void LLVertexBufferAvatar::setupVertexBuffer(U32 data_mask) const { - if (sRenderingSkinned) +/* if (sRenderingSkinned) { U8* base = useVBOs() ? NULL : mMappedData; @@ -1562,7 +1562,7 @@ void LLVertexBufferAvatar::setupVertexBuffer(U32 data_mask) const set_vertex_clothing_weights(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_CLOTHING], mStride, (LLVector4*)(base + mOffsets[TYPE_CLOTHWEIGHT])); } } - else + else*/ { LLVertexBuffer::setupVertexBuffer(data_mask); } diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp index b8bdbfb2f8..98c0191397 100644 --- a/indra/newview/llpolymesh.cpp +++ b/indra/newview/llpolymesh.cpp @@ -140,7 +140,7 @@ void LLPolyMeshSharedData::freeMeshData() delete [] mDetailTexCoords; mDetailTexCoords = NULL; - delete [] mWeights; + _mm_free(mWeights); mWeights = NULL; } @@ -230,7 +230,7 @@ BOOL LLPolyMeshSharedData::allocateVertexData( U32 numVertices ) mBaseBinormals = new LLVector3[ numVertices ]; mTexCoords = new LLVector2[ numVertices ]; mDetailTexCoords = new LLVector2[ numVertices ]; - mWeights = new F32[ numVertices ]; + mWeights = (F32*) _mm_malloc((numVertices*sizeof(F32)+0xF) & ~0xF, 16); for (i = 0; i < numVertices; i++) { mWeights[i] = 0.f; @@ -717,13 +717,20 @@ LLPolyMesh::LLPolyMesh(LLPolyMeshSharedData *shared_data, LLPolyMesh *reference_ //use aligned vertex data to make LLPolyMesh SSE friendly mVertexData = (F32*) _mm_malloc(nfloats*4, 16); int offset = 0; - mCoords = (LLVector4*)(mVertexData + offset); offset += 4*nverts; - mNormals = (LLVector4*)(mVertexData + offset); offset += 4*nverts; - mScaledNormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; - mBinormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; - mScaledBinormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; - mTexCoords = (LLVector2*)(mVertexData + offset); offset += 2*nverts; - mClothingWeights = (LLVector4*)(mVertexData + offset); offset += 4*nverts; + + //all members must be 16-byte aligned except the last 3 + mCoords = (LLVector4*)(mVertexData + offset); offset += 4*nverts; + mNormals = (LLVector4*)(mVertexData + offset); offset += 4*nverts; + mClothingWeights = (LLVector4*)(mVertexData + offset); offset += 4*nverts; + mTexCoords = (LLVector2*)(mVertexData + offset); offset += 2*nverts; + + // these members don't need to be 16-byte aligned, but the first one might be + // read during an aligned memcpy of mTexCoords + mScaledNormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; + mBinormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; + mScaledBinormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; + + #else mCoords = new LLVector3[mSharedData->mNumVertices]; mNormals = new LLVector3[mSharedData->mNumVertices]; diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 236ad98d68..a7e7bfadd6 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -655,6 +655,9 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) //----------------------------------------------------------------------------- void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area) { + //bump num_vertices to next multiple of 4 + num_vertices = (num_vertices + 0x3) & ~0x3; + // Do a pre-alloc pass to determine sizes of data. if (mMesh && mValid) { @@ -677,6 +680,8 @@ static LLFastTimer::DeclareTimer FTM_AVATAR_FACE("Avatar Face"); 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->mVertexBuffer.isNull()) @@ -684,6 +689,16 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w 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 verticesp; @@ -696,108 +711,52 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w // Copy data into the faces from the polymesh data. if (mMesh && mValid) { - if (mMesh->getNumVertices()) + const U32 num_verts = mMesh->getNumVertices(); + + if (num_verts) { - stop_glerror(); face->getGeometryAvatar(verticesp, normalsp, tex_coordsp, vertex_weightsp, clothing_weightsp); - stop_glerror(); face->mVertexBuffer->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); + + F32* v = (F32*) verticesp.get(); + F32* n = (F32*) normalsp.get(); + + U32 words = num_verts*4; - U32* __restrict v = (U32*) verticesp.get(); - U32* __restrict n = (U32*) normalsp.get(); + LLVector4a::memcpyNonAliased16(v, (F32*) mMesh->getCoords(), words); + LLVector4a::memcpyNonAliased16(n, (F32*) mMesh->getNormals(), words); + - if (terse_update) + 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 += 4; - v += skip; - } + 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(); - for (S32 i = num_verts; i > 0; --i) - { - n[0] = normals[0]; - n[1] = normals[1]; - n[2] = normals[2]; - normals += 4; - n += skip; - } + LLVector4a::memcpyNonAliased16(tc, (F32*) mMesh->getTexCoords(), num_verts*2); + LLVector4a::memcpyNonAliased16(vw, (F32*) mMesh->getWeights(), num_verts); + LLVector4a::memcpyNonAliased16(cw, (F32*) mMesh->getClothingWeights(), num_verts*4); } - 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[0]; - v[1] = coords[1]; - v[2] = coords[2]; - coords += 4; - v += skip; - - tc[0] = *(tex_coords++); - tc[1] = *(tex_coords++); - tc += skip; - - n[0] = normals[0]; - n[1] = normals[1]; - n[2] = normals[2]; - normals += 4; - 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; + const U32 idx_count = mMesh->getNumFaces()*3; - U16* __restrict idx = indicesp.get(); - S32* __restrict src_idx = (S32*) mMesh->getFaces(); + indicesp += mMesh->mFaceIndexOffset; - i = 0; + U16* __restrict idx = indicesp.get(); + S32* __restrict src_idx = (S32*) mMesh->getFaces(); - const S32 offset = (S32) mMesh->mFaceVertexOffset; + const S32 offset = (S32) mMesh->mFaceVertexOffset; - do - { - *(idx++) = *(src_idx++)+offset; - } - while (++i < idx_count); + for (S32 i = 0; i < idx_count; ++i) + { + *(idx++) = *(src_idx++)+offset; } } } @@ -824,50 +783,44 @@ void LLViewerJointMesh::updateGeometryOriginal(LLFace *mFace, LLPolyMesh *mMesh) buffer->getVertexStrider(o_vertices, 0); buffer->getNormalStrider(o_normals, 0); - //F32 last_weight = F32_MAX; - LLMatrix4a gBlendMat; + 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++) { - U32 bidx = index + mMesh->mFaceVertexOffset; - - // blend by first matrix - F32 w = weights[index]; - - //LLVector4a coord; - //coord.load4a(coords[index].mV); + // equivalent to joint = floorf(weights[index]); + S32 joint = _mm_cvtt_ss2si(_mm_load_ss(weights+index)); + F32 w = weights[index] - joint; - //LLVector4a norm; - //norm.load4a(normals[index].mV); + LLMatrix4a gBlendMat; - S32 joint = llfloor(w); - w -= joint; - - if (w > 0.f) + if (w != 0.f) { - // Try to keep all the accesses to the matrix data as close - // together as possible. This function is a hot spot on the - // Mac. JC + // blend between matrices and apply gBlendMat.setLerp(gJointMatAligned[joint+0], gJointMatAligned[joint+1], w); LLVector4a res; gBlendMat.affineTransform(coords[index], res); - o_vertices[bidx].setVec(res[0], res[1], res[2]); + res.store4a(vert+index*4); gBlendMat.rotate(normals[index], res); - o_normals[bidx].setVec(res[0], res[1], res[2]); + res.store4a(norm+index*4); } else { // No lerp required in this case. LLVector4a res; gJointMatAligned[joint].affineTransform(coords[index], res); - o_vertices[bidx].setVec(res[0], res[1], res[2]); + res.store4a(vert+index*4); gJointMatAligned[joint].rotate(normals[index], res); - o_normals[bidx].setVec(res[0], res[1], res[2]); + res.store4a(norm+index*4); } } -- cgit v1.3 From e90d2f88e5ce584b52b24315c85845a9e5113b50 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 21 May 2010 14:31:17 -0500 Subject: Aligned index buffers. --- indra/llrender/llvertexbuffer.cpp | 56 +++++++++++--------------------------- indra/llrender/llvertexbuffer.h | 3 +- indra/newview/lldrawpoolavatar.cpp | 19 +++++++------ 3 files changed, 29 insertions(+), 49 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index a50eb7211c..0f3c900d2b 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -453,6 +453,7 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : mTypeMask = typemask; mStride = stride; mAlignedOffset = 0; + mAlignedIndexOffset = 0; sCount++; } @@ -642,16 +643,20 @@ void LLVertexBuffer::createGLIndices() mEmpty = TRUE; + //pad by 16 bytes for aligned copies + size += 16; + if (useVBOs()) { + //pad by another 16 bytes for VBO pointer adjustment + size += 16; mMappedIndexData = NULL; genIndices(); mResized = TRUE; } else { - mMappedIndexData = new U8[size]; - memset(mMappedIndexData, 0, size); + mMappedIndexData = (U8*) _mm_malloc(size, 16); static int gl_buffer_idx = 0; mGLIndices = ++gl_buffer_idx; } @@ -699,7 +704,7 @@ void LLVertexBuffer::destroyGLIndices() } else { - delete [] mMappedIndexData; + _mm_free(mMappedIndexData); mMappedIndexData = NULL; mEmpty = TRUE; } @@ -836,26 +841,10 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) } else { - //delete old buffer, keep GL buffer for now if (!useVBOs()) { - U8* old = mMappedData; - mMappedData = new U8[newsize]; - if (old) - { - memcpy(mMappedData, old, llmin(newsize, oldsize)); - if (newsize > oldsize) - { - memset(mMappedData+oldsize, 0, newsize-oldsize); - } - - delete [] old; - } - else - { - memset(mMappedData, 0, newsize); - mEmpty = TRUE; - } + _mm_free(mMappedData); + mMappedData = (U8*) _mm_malloc(newsize, 16); } mResized = TRUE; } @@ -875,24 +864,8 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) { if (!useVBOs()) { - //delete old buffer, keep GL buffer for now - U8* old = mMappedIndexData; - mMappedIndexData = new U8[new_index_size]; - - if (old) - { - memcpy(mMappedIndexData, old, llmin(new_index_size, old_index_size)); - if (new_index_size > old_index_size) - { - memset(mMappedIndexData+old_index_size, 0, new_index_size - old_index_size); - } - delete [] old; - } - else - { - memset(mMappedIndexData, 0, new_index_size); - mEmpty = TRUE; - } + _mm_free(mMappedIndexData); + mMappedIndexData = (U8*) _mm_malloc(new_index_size, 16); } mResized = TRUE; } @@ -958,7 +931,10 @@ U8* LLVertexBuffer::mapBuffer(S32 access) } { LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES); - mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + U8* src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + mMappedIndexData = LL_NEXT_ALIGNED_ADDRESS(src); + mAlignedIndexOffset = mMappedIndexData - src; + stop_glerror(); } diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 03799af978..c6fd0a9e3c 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -187,7 +187,7 @@ public: S32 getRequestedVerts() const { return mRequestedNumVerts; } S32 getRequestedIndices() const { return mRequestedNumIndices; } - U8* getIndicesPointer() const { return useVBOs() ? NULL : mMappedIndexData; } + U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; } U8* getVerticesPointer() const { return useVBOs() ? NULL : mMappedData; } S32 getStride() const { return mStride; } U32 getTypeMask() const { return mTypeMask; } @@ -214,6 +214,7 @@ protected: S32 mRequestedNumIndices; // Number of indices requested ptrdiff_t mAlignedOffset; + ptrdiff_t mAlignedIndexOffset; S32 mStride; U32 mTypeMask; S32 mUsage; // GL usage diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 1e9053239d..4fb8f5266e 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1542,27 +1542,30 @@ LLVertexBufferAvatar::LLVertexBufferAvatar() void LLVertexBufferAvatar::setupVertexBuffer(U32 data_mask) const { -/* if (sRenderingSkinned) + if (sRenderingSkinned) { U8* base = useVBOs() ? NULL : mMappedData; - glVertexPointer(3,GL_FLOAT, mStride, (void*)(base + 0)); - glNormalPointer(GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_NORMAL])); - glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD0])); + glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_VERTEX], (void*)(base + 0)); + glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL])); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); - set_vertex_weights(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT], mStride, (F32*)(base + mOffsets[TYPE_WEIGHT])); + set_vertex_weights(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT], + LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_WEIGHT], (F32*)(base + mOffsets[TYPE_WEIGHT])); if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_BUMP) { - set_binormals(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::BINORMAL], mStride, (LLVector3*)(base + mOffsets[TYPE_BINORMAL])); + set_binormals(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::BINORMAL], + LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_BINORMAL], (LLVector3*)(base + mOffsets[TYPE_BINORMAL])); } if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH) { - set_vertex_clothing_weights(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_CLOTHING], mStride, (LLVector4*)(base + mOffsets[TYPE_CLOTHWEIGHT])); + set_vertex_clothing_weights(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_CLOTHING], + LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_CLOTHWEIGHT], (LLVector4*)(base + mOffsets[TYPE_CLOTHWEIGHT])); } } - else*/ + else { LLVertexBuffer::setupVertexBuffer(data_mask); } -- cgit v1.3 From 4d57cb3c0975ff0bcea0d6fb3498f2d90962ff16 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Sat, 22 May 2010 04:35:02 -0500 Subject: Vectorize/memory align buffers in llvolumeface WIP --- indra/llmath/llvolume.cpp | 720 ++++++++++++++++---------------- indra/llmath/llvolume.h | 35 +- indra/newview/lldrawpoolavatar.cpp | 6 +- indra/newview/llface.cpp | 55 +-- indra/newview/llfloaterimagepreview.cpp | 6 +- indra/newview/llhudicon.cpp | 2 + indra/newview/llhudtext.cpp | 5 + indra/newview/llviewercamera.cpp | 5 +- indra/newview/llvograss.cpp | 2 + indra/newview/llvotextbubble.cpp | 33 +- indra/newview/llvovolume.cpp | 29 +- 11 files changed, 474 insertions(+), 424 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 4e342b0b48..01fe2be371 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1,4 +1,5 @@ /** + * @file llvolume.cpp * * $LicenseInfo:firstyear=2002&license=viewergpl$ @@ -89,8 +90,6 @@ const F32 SKEW_MAX = 0.95f; const F32 SCULPT_MIN_AREA = 0.002f; const S32 SCULPT_MIN_AREA_DETAIL = 1; -#define GEN_TRI_STRIP 0 - BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm) { LLVector3 test = (pt2-pt1)%(pt3-pt2); @@ -134,21 +133,25 @@ BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, con // and returns the intersection point along dir in intersection_t. // Moller-Trumbore algorithm -BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir, +BOOL LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, F32* intersection_a, F32* intersection_b, F32* intersection_t, BOOL two_sided) { F32 u, v, t; /* find vectors for two edges sharing vert0 */ - LLVector3 edge1 = vert1 - vert0; + LLVector4a edge1; + edge1.setSub(vert1, vert0); - LLVector3 edge2 = vert2 - vert0;; + + LLVector4a edge2; + edge2.setSub(vert2, vert0); /* begin calculating determinant - also used to calculate U parameter */ - LLVector3 pvec = dir % edge2; - + LLVector4a pvec; + pvec.setCross3(dir, edge2); + /* if determinant is near zero, ray lies in plane of triangle */ - F32 det = edge1 * pvec; + F32 det = edge1.dot3(pvec); if (!two_sided) { @@ -158,10 +161,11 @@ BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, cons } /* calculate distance from vert0 to ray origin */ - LLVector3 tvec = orig - vert0; + LLVector4a tvec; + tvec.setSub(orig, vert0); /* calculate U parameter and test bounds */ - u = tvec * pvec; + u = tvec.dot3(pvec); if (u < 0.f || u > det) { @@ -169,17 +173,18 @@ BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, cons } /* prepare to test V parameter */ - LLVector3 qvec = tvec % edge1; + LLVector4a qvec; + qvec.setCross3(tvec, edge1); /* calculate V parameter and test bounds */ - v = dir * qvec; + v = dir.dot3(qvec); if (v < 0.f || u + v > det) { return FALSE; } /* calculate t, scale parameters, ray intersects triangle */ - t = edge2 * qvec; + t = edge2.dot3(qvec); F32 inv_det = 1.0 / det; t *= inv_det; u *= inv_det; @@ -195,20 +200,22 @@ BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, cons F32 inv_det = 1.0 / det; /* calculate distance from vert0 to ray origin */ - LLVector3 tvec = orig - vert0; + LLVector4a tvec; + tvec.setSub(orig, vert0); /* calculate U parameter and test bounds */ - u = (tvec * pvec) * inv_det; + u = (tvec.dot3(pvec)) * inv_det; if (u < 0.f || u > 1.f) { return FALSE; } /* prepare to test V parameter */ - LLVector3 qvec = tvec - edge1; + LLVector4a qvec; + qvec.setSub(tvec, edge1); /* calculate V parameter and test bounds */ - v = (dir * qvec) * inv_det; + v = (dir.dot3(qvec)) * inv_det; if (v < 0.f || u + v > 1.f) { @@ -216,7 +223,7 @@ BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, cons } /* calculate t, ray intersects triangle */ - t = (edge2 * qvec) * inv_det; + t = (edge2.dot3(qvec)) * inv_det; } if (intersection_a != NULL) @@ -4120,13 +4127,14 @@ void LLVolume::generateSilhouetteVertices(std::vector &vertices, norm_mat.rotate(n[v1], t); t.normalize3Fast(); - LLVector3 norm1 = LLVector3(t[0], t[1], t[2]); - normals.push_back(norm1); + normals.push_back(LLVector3(t[0], t[1], t[2])); - vertices.push_back(face.mVertices[v2].mPosition*mat); - LLVector3 norm2 = face.mVertices[v2].mNormal * norm_mat; - norm2.normVec(); - normals.push_back(norm2); + mat.affineTransform(v[v2], t); + vertices.push_back(LLVector3(t[0], t[1], t[2])); + + norm_mat.rotate(n[v2], t); + t.normalize3Fast(); + normals.push_back(LLVector3(t[0], t[1], t[2])); segments.push_back(vertices.size()); } @@ -4177,6 +4185,10 @@ S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, genBinormals(i); } + LLVector4a starta, dira; + + LLVector4a* p = (LLVector4a*) face.mPositions; + for (U32 tri = 0; tri < face.mNumIndices/3; tri++) { S32 index1 = face.mIndices[tri*3+0]; @@ -4185,15 +4197,15 @@ S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, F32 a, b, t; - if (LLTriangleRayIntersect(face.mVertices[index1].mPosition, - face.mVertices[index2].mPosition, - face.mVertices[index3].mPosition, - start, dir, &a, &b, &t, FALSE)) + if (LLTriangleRayIntersect(p[index1], + p[index2], + p[index3], + starta, dira, &a, &b, &t, FALSE)) { if ((t >= 0.f) && // if hit is after start (t <= 1.f) && // and before end (t < closest_t)) // and this hit is closer - { + { closest_t = t; hit_face = i; @@ -4201,27 +4213,35 @@ S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, { *intersection = start + dir * closest_t; } - + + if (tex_coord != NULL) - { - *tex_coord = ((1.f - a - b) * face.mVertices[index1].mTexCoord + - a * face.mVertices[index2].mTexCoord + - b * face.mVertices[index3].mTexCoord); + { + LLVector2* tc = (LLVector2*) face.mTexCoords; + *tex_coord = ((1.f - a - b) * tc[index1] + + a * tc[index2] + + b * tc[index3]); } if (normal != NULL) - { - *normal = ((1.f - a - b) * face.mVertices[index1].mNormal + - a * face.mVertices[index2].mNormal + - b * face.mVertices[index3].mNormal); + { + LLVector4* norm = (LLVector4*) face.mNormals; + + *normal = ((1.f - a - b) * LLVector3(norm[index1]) + + a * LLVector3(norm[index2]) + + b * LLVector3(norm[index3])); } if (bi_normal != NULL) - { - *bi_normal = ((1.f - a - b) * face.mVertices[index1].mBinormal + - a * face.mVertices[index2].mBinormal + - b * face.mVertices[index3].mBinormal); + { + LLVector4* binormal = (LLVector4*) face.mBinormals; + if (binormal) + { + *bi_normal = ((1.f - a - b) * LLVector3(binormal[index1]) + + a * LLVector3(binormal[index2]) + + b * LLVector3(binormal[index3])); + } } } @@ -4992,6 +5012,14 @@ std::ostream& operator<<(std::ostream &s, const LLVolume *volumep) return s; } +LLVolumeFace::~LLVolumeFace() +{ + _mm_free(mPositions); + _mm_free(mNormals); + _mm_free(mTexCoords); + _mm_free(mIndices); + _mm_free(mBinormals); +} BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build) { @@ -5012,6 +5040,7 @@ BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build) void LLVolumeFace::optimize(F32 angle_cutoff) { +#if 0 //disabling until a vectorized version is available LLVolumeFace new_face; VertexMapData::PointMap point_map; @@ -5063,6 +5092,7 @@ void LLVolumeFace::optimize(F32 angle_cutoff) mVertices = new_face.mVertices; mIndices = new_face.mIndices; +#endif } void LerpPlanarVertex(LLVolumeFace::VertexData& v0, @@ -5127,20 +5157,22 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) corners[1].mTexCoord=corners[2].mTexCoord; corners[2].mTexCoord=swap; } - baseVert.mBinormal = calc_binormal_from_triangle( + + LLVector4a binormal; + + calc_binormal_from_triangle( binormal, corners[0].mPosition, corners[0].mTexCoord, corners[1].mPosition, corners[1].mTexCoord, corners[2].mPosition, corners[2].mTexCoord); - for(int t = 0; t < 4; t++){ - corners[t].mBinormal = baseVert.mBinormal; - corners[t].mNormal = baseVert.mNormal; - } - mHasBinormals = TRUE; - if (partial_build) - { - mVertices.clear(); - } + S32 size = (grid_size+1)*(grid_size+1); + resizeVertices(size); + allocateBinormals(size); + + LLVector4a* pos = (LLVector4a*) mPositions; + LLVector4a* norm = (LLVector4a*) mNormals; + LLVector4a* binorm = (LLVector4a*) mBinormals; + LLVector2* tc = (LLVector2*) mTexCoords; S32 vtop = mNumVertices; for(int gx = 0;gx=0;i--) { - mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]); - } - -#if GEN_TRI_STRIP - if (gy == 0) - { - mTriStrip.push_back((gx+1)*(grid_size+1)); - mTriStrip.push_back((gx+1)*(grid_size+1)); - mTriStrip.push_back(gx*(grid_size+1)); - } - - mTriStrip.push_back(gy+1+(gx+1)*(grid_size+1)); - mTriStrip.push_back(gy+1+gx*(grid_size+1)); - - - if (gy == grid_size-1) - { - mTriStrip.push_back(gy+1+gx*(grid_size+1)); - } -#endif + *out++ = (vtop+(gy*(grid_size+1))+gx+idxs[i]); + } } else { for(S32 i=0;i<6;i++) { - mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]); - } - -#if GEN_TRI_STRIP - if (gy == 0) - { - mTriStrip.push_back(gx*(grid_size+1)); - mTriStrip.push_back(gx*(grid_size+1)); - mTriStrip.push_back((gx+1)*(grid_size+1)); + *out++ = (vtop+(gy*(grid_size+1))+gx+idxs[i]); } - - mTriStrip.push_back(gy+1+gx*(grid_size+1)); - mTriStrip.push_back(gy+1+(gx+1)*(grid_size+1)); - - if (gy == grid_size-1) - { - mTriStrip.push_back(gy+1+(gx+1)*(grid_size+1)); - } -#endif } } } - -#if GEN_TRI_STRIP - if (mTriStrip.size()%2 == 1) - { - mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]); - } -#endif } return TRUE; @@ -5267,11 +5262,25 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) num_vertices = profile.size(); num_indices = (profile.size() - 2)*3; - mVertices.resize(num_vertices); + if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK)) + { + resizeVertices(num_vertices+1); + allocateBinormals(num_vertices+1); - if (!partial_build) + if (!partial_build) + { + resizeIndices(num_indices+3); + } + } + else { - mIndices.resize(num_indices); + resizeVertices(num_vertices); + allocateBinormals(num_vertices); + + if (!partial_build) + { + resizeIndices(num_indices); + } } S32 max_s = volume->getProfile().getTotal(); @@ -5298,79 +5307,87 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) LLVector3& min = mExtents[0]; LLVector3& max = mExtents[1]; + LLVector2* tc = (LLVector2*) mTexCoords; + LLVector4a* pos = (LLVector4a*) mPositions; + LLVector4a* norm = (LLVector4a*) mNormals; + LLVector4a* binorm = (LLVector4a*) mBinormals; + // Copy the vertices into the array for (S32 i = 0; i < num_vertices; i++) { if (mTypeMask & TOP_MASK) { - mVertices[i].mTexCoord.mV[0] = profile[i].mV[0]+0.5f; - mVertices[i].mTexCoord.mV[1] = profile[i].mV[1]+0.5f; + tc[i].mV[0] = profile[i].mV[0]+0.5f; + tc[i].mV[1] = profile[i].mV[1]+0.5f; } else { // Mirror for underside. - mVertices[i].mTexCoord.mV[0] = profile[i].mV[0]+0.5f; - mVertices[i].mTexCoord.mV[1] = 0.5f - profile[i].mV[1]; + tc[i].mV[0] = profile[i].mV[0]+0.5f; + tc[i].mV[1] = 0.5f - profile[i].mV[1]; } - mVertices[i].mPosition = mesh[i + offset].mPos; + pos[i].load3(mesh[i + offset].mPos.mV); if (i == 0) { - min = max = mVertices[i].mPosition; - min_uv = max_uv = mVertices[i].mTexCoord; + min = max = mesh[i+offset].mPos; + min_uv = max_uv = tc[i]; } else { - update_min_max(min,max, mVertices[i].mPosition); - update_min_max(min_uv, max_uv, mVertices[i].mTexCoord); + update_min_max(min,max, mesh[i+offset].mPos); + update_min_max(min_uv, max_uv, tc[i]); } } mCenter = (min+max)*0.5f; cuv = (min_uv + max_uv)*0.5f; - LLVector3 binormal = calc_binormal_from_triangle( + LLVector4a binormal; + calc_binormal_from_triangle(binormal, mCenter, cuv, - mVertices[0].mPosition, mVertices[0].mTexCoord, - mVertices[1].mPosition, mVertices[1].mTexCoord); - binormal.normVec(); + mesh[0+offset].mPos, tc[0], + mesh[1+offset].mPos, tc[1]); + binormal.normalize3Fast(); + + LLVector4a normal; + LLVector4a d0, d1; + LLVector4a center; + + center.load3(mCenter.mV); - LLVector3 d0; - LLVector3 d1; - LLVector3 normal; + d0.setSub(center, pos[0]); + d1.setSub(center, pos[1]); - d0 = mCenter-mVertices[0].mPosition; - d1 = mCenter-mVertices[1].mPosition; + if (mTypeMask & TOP_MASK) + { + normal.setCross3(d0, d1); + } + else + { + normal.setCross3(d1, d0); + } - normal = (mTypeMask & TOP_MASK) ? (d0%d1) : (d1%d0); - normal.normVec(); + normal.normalize3Fast(); VertexData vd; vd.mPosition = mCenter; - vd.mNormal = normal; - vd.mBinormal = binormal; vd.mTexCoord = cuv; if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK)) { - mVertices.push_back(vd); + pos[num_vertices].load4a((F32*) ¢er.mQ); + tc[num_vertices] = cuv; num_vertices++; - if (!partial_build) - { - vector_append(mIndices, 3); - } } - for (S32 i = 0; i < num_vertices; i++) { - mVertices[i].mBinormal = binormal; - mVertices[i].mNormal = normal; + binorm[i].load4a((F32*) &binormal.mQ); + norm[i].load4a((F32*) &normal.mQ); } - mHasBinormals = TRUE; - if (partial_build) { return TRUE; @@ -5478,8 +5495,6 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) pt2--; } } - - makeTriStrip(); } else { @@ -5584,8 +5599,6 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) pt2--; } } - - makeTriStrip(); } } else @@ -5607,131 +5620,63 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) mIndices[3*i+v2] = i + 1; } -#if GEN_TRI_STRIP - //make tri strip - if (mTypeMask & OPEN_MASK) - { - makeTriStrip(); - } - else - { - S32 j = num_vertices-2; - if (mTypeMask & TOP_MASK) - { - mTriStrip.push_back(0); - for (S32 i = 0; i <= j; ++i) - { - mTriStrip.push_back(i); - if (i != j) - { - mTriStrip.push_back(j); - } - --j; - } - } - else - { - mTriStrip.push_back(j); - for (S32 i = 0; i <= j; ++i) - { - if (i != j) - { - mTriStrip.push_back(j); - } - mTriStrip.push_back(i); - --j; - } - } - - mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]); - if (mTriStrip.size()%2 == 1) - { - mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]); - } - } -#endif } return TRUE; } -void LLVolumeFace::makeTriStrip() -{ -#if GEN_TRI_STRIP - for (U32 i = 0; i < mNumIndices; i+=3) - { - U16 i0 = mIndices[i]; - U16 i1 = mIndices[i+1]; - U16 i2 = mIndices[i+2]; - - if ((i/3)%2 == 1) - { - mTriStrip.push_back(i0); - mTriStrip.push_back(i0); - mTriStrip.push_back(i1); - mTriStrip.push_back(i2); - mTriStrip.push_back(i2); - } - else - { - mTriStrip.push_back(i2); - mTriStrip.push_back(i2); - mTriStrip.push_back(i1); - mTriStrip.push_back(i0); - mTriStrip.push_back(i0); - } - } - - if (mTriStrip.size()%2 == 1) - { - mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]); - } -#endif -} - void LLVolumeFace::createBinormals() { LLMemType m1(LLMemType::MTYPE_VOLUME); - if (!mHasBinormals) + if (!mBinormals) { + allocateBinormals(mNumVertices); + //generate binormals + LLStrider pos; + pos = (LLVector3*) mPositions; + pos.setStride(16); + + LLVector2* tc = (LLVector2*) mTexCoords; + LLVector4a* binorm = (LLVector4a*) mBinormals; + for (U32 i = 0; i < mNumIndices/3; i++) { //for each triangle - const VertexData& v0 = mVertices[mIndices[i*3+0]]; - const VertexData& v1 = mVertices[mIndices[i*3+1]]; - const VertexData& v2 = mVertices[mIndices[i*3+2]]; + const U16& i0 = mIndices[i*3+0]; + const U16& i1 = mIndices[i*3+1]; + const U16& i2 = mIndices[i*3+2]; //calculate binormal - LLVector3 binorm = calc_binormal_from_triangle(v0.mPosition, v0.mTexCoord, - v1.mPosition, v1.mTexCoord, - v2.mPosition, v2.mTexCoord); + LLVector4a binormal; + calc_binormal_from_triangle(binormal, + pos[i0], tc[i0], + pos[i1], tc[i1], + pos[i2], tc[i2]); - for (U32 j = 0; j < 3; j++) - { //add triangle normal to vertices - mVertices[mIndices[i*3+j]].mBinormal += binorm; // * (weight_sum - d[j])/weight_sum; - } + + //add triangle normal to vertices + binorm[i0].add(binormal); + binorm[i1].add(binormal); + binorm[i2].add(binormal); //even out quad contributions if (i % 2 == 0) { - mVertices[mIndices[i*3+2]].mBinormal += binorm; + binorm[i2].add(binormal); } else { - mVertices[mIndices[i*3+1]].mBinormal += binorm; + binorm[i1].add(binormal); } } //normalize binormals for (U32 i = 0; i < mNumVertices; i++) { - mVertices[i].mBinormal.normVec(); - mVertices[i].mNormal.normVec(); + binorm[i].normalize3Fast(); } - - mHasBinormals = TRUE; } } @@ -5754,6 +5699,13 @@ void LLVolumeFace::resizeVertices(S32 num_verts) mNumVertices = num_verts; } +void LLVolumeFace::allocateBinormals(S32 num_verts) +{ + _mm_free(mBinormals); + mBinormals = (F32*) _mm_malloc(num_verts*16, 16); +} + + void LLVolumeFace::resizeIndices(S32 num_indices) { _mm_free(mIndices); @@ -5761,44 +5713,107 @@ void LLVolumeFace::resizeIndices(S32 num_indices) //pad index block end to allow for QWORD reads S32 size = ((num_indices*2) + 0xF) & ~0xF; - mIndices = (U16*) _mm_malloc(size); + mIndices = (U16*) _mm_malloc(size,16); mNumIndices = num_indices; } -void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat, LLMatrix4& norm_mat) +void LLVolumeFace::fillFromLegacyData(std::vector& v, std::vector& idx) +{ + resizeVertices(v.size()); + resizeIndices(idx.size()); + + for (U32 i = 0; i < v.size(); ++i) + { + for (U32 j = 0; j < 3; ++j) + { + mPositions[i*4+j] = v[i].mPosition[j]; + mNormals[i*4+j] = v[i].mNormal[j]; + } + + mTexCoords[i*2+0] = v[i].mTexCoord.mV[0]; + mTexCoords[i*2+1] = v[i].mTexCoord.mV[1]; + } + + for (U32 i = 0; i < idx.size(); ++i) + { + mIndices[i] = idx[i]; + } +} + +void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMatrix4& norm_mat_in) { U16 offset = mNumVertices; - if (face.mNumVertices + mNumVertices > 65536) + S32 new_count = face.mNumVertices + mNumVertices; + + if (new_count > 65536) { llerrs << "Cannot append face -- 16-bit overflow will occur." << llendl; } + + F32* new_pos = (F32*) _mm_malloc(new_count*16, 16); + F32* new_norm = (F32*) _mm_malloc(new_count*16, 16); + F32* new_tc = (F32*) _mm_malloc((new_count*8+0xF) & ~0xF, 16); + + LLVector4a::memcpyNonAliased16(new_pos, mPositions, new_count*4); + LLVector4a::memcpyNonAliased16(new_norm, mNormals, new_count*4); + LLVector4a::memcpyNonAliased16(new_tc, mTexCoords, new_count*2); + + _mm_free(mPositions); + _mm_free(mNormals); + _mm_free(mTexCoords); + + mPositions = new_pos; + mNormals = new_norm; + mTexCoords = new_tc; + + mNumVertices = new_count; + + LLVector4a* dst_pos = (LLVector4a*) mPositions+offset; + LLVector2* dst_tc = (LLVector2*) mTexCoords+offset; + LLVector4a* dst_norm = (LLVector4a*) mNormals+offset; + + LLVector4a* src_pos = (LLVector4a*) face.mPositions; + LLVector2* src_tc = (LLVector2*) face.mTexCoords; + LLVector4a* src_norm = (LLVector4a*) face.mNormals; + + LLMatrix4a mat, norm_mat; + mat.loadu(mat_in); + norm_mat.loadu(norm_mat_in); + for (U32 i = 0; i < face.mNumVertices; ++i) { - VertexData v = face.mVertices[i]; - v.mPosition = v.mPosition*mat; - v.mNormal = v.mNormal * norm_mat; + mat.affineTransform(src_pos[i], dst_pos[i]); + norm_mat.rotate(src_norm[i], dst_norm[i]); + dst_norm[i].normalize3Fast(); - v.mNormal.normalize(); - - mVertices.push_back(v); + dst_tc[i] = src_tc[i]; if (offset == 0 && i == 0) { - mExtents[0] = mExtents[1] = v.mPosition; + mExtents[0] = mExtents[1] = LLVector3((F32*) &(dst_pos[i].mQ)); } else { - update_min_max(mExtents[0], mExtents[1], v.mPosition); + update_min_max(mExtents[0], mExtents[1], (F32*) &(dst_pos[i].mQ)); } } - + + new_count = mNumIndices + face.mNumIndices; + U16* new_indices = (U16*) _mm_malloc((new_count*2+0xF) & ~0xF, 16); + LLVector4a::memcpyNonAliased16((F32*) new_indices, (F32*) mIndices, new_count/2); + _mm_free(mIndices); + mIndices = new_indices; + mNumIndices = new_count; + + U16* dst_idx = mIndices+offset; + for (U32 i = 0; i < face.mNumIndices; ++i) { - mIndices.push_back(face.mIndices[i]+offset); + dst_idx[i] = face.mIndices[i]+offset; } } @@ -5828,21 +5843,20 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) num_vertices = mNumS*mNumT; num_indices = (mNumS-1)*(mNumT-1)*6; - mVertices.resize(num_vertices); - if (!partial_build) { - mIndices.resize(num_indices); + resizeVertices(num_vertices); + resizeIndices(num_indices); if ((volume->getParams().getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH) { mEdge.resize(num_indices); } } - else - { - mHasBinormals = FALSE; - } + + LLVector4a* pos = (LLVector4a*) mPositions; + LLVector4a* norm = (LLVector4a*) mNormals; + LLVector2* tc = (LLVector2*) mTexCoords; S32 begin_stex = llfloor( profile[mBeginS].mV[2] ); S32 num_s = ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) ? mNumS/2 : mNumS; @@ -5894,21 +5908,21 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) i = mBeginS + s + max_s*t; } - mVertices[cur_vertex].mPosition = mesh[i].mPos; - mVertices[cur_vertex].mTexCoord = LLVector2(ss,tt); + pos[cur_vertex].load3(mesh[i].mPos.mV); + tc[cur_vertex] = LLVector2(ss,tt); - mVertices[cur_vertex].mNormal = LLVector3(0,0,0); - mVertices[cur_vertex].mBinormal = LLVector3(0,0,0); + norm[cur_vertex].clear(); cur_vertex++; if ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2 && s > 0) { - mVertices[cur_vertex].mPosition = mesh[i].mPos; - mVertices[cur_vertex].mTexCoord = LLVector2(ss,tt); + + pos[cur_vertex].load3(mesh[i].mPos.mV); + tc[cur_vertex] = LLVector2(ss,tt); - mVertices[cur_vertex].mNormal = LLVector3(0,0,0); - mVertices[cur_vertex].mBinormal = LLVector3(0,0,0); + norm[cur_vertex].clear(); + cur_vertex++; } } @@ -5926,12 +5940,10 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) i = mBeginS + s + max_s*t; ss = profile[mBeginS + s].mV[2] - begin_stex; - mVertices[cur_vertex].mPosition = mesh[i].mPos; - mVertices[cur_vertex].mTexCoord = LLVector2(ss,tt); - - mVertices[cur_vertex].mNormal = LLVector3(0,0,0); - mVertices[cur_vertex].mBinormal = LLVector3(0,0,0); - + pos[cur_vertex].load3(mesh[i].mPos.mV); + tc[cur_vertex] = LLVector2(ss,tt); + norm[cur_vertex].clear(); + cur_vertex++; } } @@ -5942,10 +5954,11 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) LLVector3& face_max = mExtents[1]; mCenter.clearVec(); - face_min = face_max = mVertices[0].mPosition; + face_min = face_max = LLVector3((F32*) &(pos[i].mQ)); + for (U32 i = 1; i < mNumVertices; ++i) { - update_min_max(face_min, face_max, mVertices[i].mPosition); + update_min_max(face_min, face_max, (F32*) &(pos[i].mQ)); } mCenter = (face_min + face_max) * 0.5f; @@ -5956,18 +5969,9 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) if (!partial_build) { -#if GEN_TRI_STRIP - mTriStrip.clear(); -#endif - // Now we generate the indices. for (t = 0; t < (mNumT-1); t++) { -#if GEN_TRI_STRIP - //prepend terminating index to strip - mTriStrip.push_back(mNumS*t); -#endif - for (s = 0; s < (mNumS-1); s++) { mIndices[cur_index++] = s + mNumS*t; //bottom left @@ -5977,16 +5981,6 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) mIndices[cur_index++] = s+1 + mNumS*t; //bottom right mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right -#if GEN_TRI_STRIP - if (s == 0) - { - mTriStrip.push_back(s+mNumS*t); - mTriStrip.push_back(s+mNumS*(t+1)); - } - mTriStrip.push_back(s+1+mNumS*t); - mTriStrip.push_back(s+1+mNumS*(t+1)); -#endif - mEdge[cur_edge++] = (mNumS-1)*2*t+s*2+1; //bottom left/top right neighbor face if (t < mNumT-2) { //top right/top left neighbor face mEdge[cur_edge++] = (mNumS-1)*2*(t+1)+s*2+1; @@ -6027,52 +6021,55 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) } mEdge[cur_edge++] = (mNumS-1)*2*t+s*2; //top right/bottom left neighbor face } -#if GEN_TRI_STRIP - //append terminating vertex to strip - mTriStrip.push_back(mNumS-1+mNumS*(t+1)); -#endif } - -#if GEN_TRI_STRIP - if (mTriStrip.size()%2 == 1) - { - mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]); - } -#endif } //generate normals for (U32 i = 0; i < mNumIndices/3; i++) //for each triangle { const U16* idx = &(mIndices[i*3]); - - VertexData* v[] = - { &mVertices[idx[0]], &mVertices[idx[1]], &mVertices[idx[2]] }; - - //calculate triangle normal - LLVector3 norm = (v[0]->mPosition-v[1]->mPosition) % (v[0]->mPosition-v[2]->mPosition); + - v[0]->mNormal += norm; - v[1]->mNormal += norm; - v[2]->mNormal += norm; + LLVector4a* v[] = + { pos+idx[0], pos+idx[1], pos+idx[2] }; + + LLVector4a* n[] = + { norm+idx[0], norm+idx[1], norm+idx[2] }; + + //calculate triangle normal + LLVector4a a, b, c; + + a.setSub(*v[0], *v[1]); + b.setSub(*v[0], *v[2]); + c.setCross3(a,b); + n[0]->add(c); + n[1]->add(c); + n[2]->add(c); + //even out quad contributions - v[i%2+1]->mNormal += norm; + n[i%2+1]->add(c); } // adjust normals based on wrapping and stitching - BOOL s_bottom_converges = ((mVertices[0].mPosition - mVertices[mNumS*(mNumT-2)].mPosition).magVecSquared() < 0.000001f); - BOOL s_top_converges = ((mVertices[mNumS-1].mPosition - mVertices[mNumS*(mNumT-2)+mNumS-1].mPosition).magVecSquared() < 0.000001f); + LLVector4a top; + top.setSub(pos[0], pos[mNumS*(mNumT-2)]); + BOOL s_bottom_converges = (top.dot3(top) < 0.000001f); + + top.setSub(pos[mNumS-1], pos[mNumS*(mNumT-2)+mNumS-1]); + BOOL s_top_converges = (top.dot3(top) < 0.000001f); + if (sculpt_stitching == LL_SCULPT_TYPE_NONE) // logic for non-sculpt volumes { if (volume->getPath().isOpen() == FALSE) { //wrap normals on T for (S32 i = 0; i < mNumS; i++) { - LLVector3 norm = mVertices[i].mNormal + mVertices[mNumS*(mNumT-1)+i].mNormal; - mVertices[i].mNormal = norm; - mVertices[mNumS*(mNumT-1)+i].mNormal = norm; + LLVector4a n; + n.setAdd(norm[i], norm[mNumS*(mNumT-1)+i]); + norm[i] = n; + norm[mNumS*(mNumT-1)+i] = n; } } @@ -6080,9 +6077,10 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) { //wrap normals on S for (S32 i = 0; i < mNumT; i++) { - LLVector3 norm = mVertices[mNumS*i].mNormal + mVertices[mNumS*i+mNumS-1].mNormal; - mVertices[mNumS * i].mNormal = norm; - mVertices[mNumS * i+mNumS-1].mNormal = norm; + LLVector4a n; + n.setAdd(norm[mNumS*i], norm[mNumS*i+mNumS-1]); + norm[mNumS * i] = n; + norm[mNumS * i+mNumS-1] = n; } } @@ -6093,7 +6091,7 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) { //all lower S have same normal for (S32 i = 0; i < mNumT; i++) { - mVertices[mNumS*i].mNormal = LLVector3(1,0,0); + norm[mNumS*i].set(1,0,0); } } @@ -6101,7 +6099,7 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) { //all upper S have same normal for (S32 i = 0; i < mNumT; i++) { - mVertices[mNumS*i+mNumS-1].mNormal = LLVector3(-1,0,0); + norm[mNumS*i+mNumS-1].set(-1,0,0); } } } @@ -6129,30 +6127,33 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) { // average normals for north pole - LLVector3 average(0.0, 0.0, 0.0); + LLVector4a average; + average.clear(); + for (S32 i = 0; i < mNumS; i++) { - average += mVertices[i].mNormal; + average.add(norm[i]); } // set average for (S32 i = 0; i < mNumS; i++) { - mVertices[i].mNormal = average; + norm[i] = average; } // average normals for south pole - average = LLVector3(0.0, 0.0, 0.0); + average.clear(); + for (S32 i = 0; i < mNumS; i++) { - average += mVertices[i + mNumS * (mNumT - 1)].mNormal; + average.add(norm[i + mNumS * (mNumT - 1)]); } // set average for (S32 i = 0; i < mNumS; i++) { - mVertices[i + mNumS * (mNumT - 1)].mNormal = average; + norm[i + mNumS * (mNumT - 1)] = average; } } @@ -6162,23 +6163,22 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) { for (S32 i = 0; i < mNumT; i++) { - LLVector3 norm = mVertices[mNumS*i].mNormal + mVertices[mNumS*i+mNumS-1].mNormal; - mVertices[mNumS * i].mNormal = norm; - mVertices[mNumS * i+mNumS-1].mNormal = norm; + LLVector4a n; + n.setAdd(norm[mNumS*i], norm[mNumS*i+mNumS-1]); + norm[mNumS * i] = n; + norm[mNumS * i+mNumS-1] = n; } } - - if (wrap_t) { for (S32 i = 0; i < mNumS; i++) { - LLVector3 norm = mVertices[i].mNormal + mVertices[mNumS*(mNumT-1)+i].mNormal; - mVertices[i].mNormal = norm; - mVertices[mNumS*(mNumT-1)+i].mNormal = norm; + LLVector4a n; + n.setAdd(norm[i], norm[mNumS*(mNumT-1)+i]); + norm[i] = n; + norm[mNumS*(mNumT-1)+i] = n; } - } } @@ -6188,7 +6188,8 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) // Finds binormal based on three vertices with texture coordinates. // Fills in dummy values if the triangle has degenerate texture coordinates. -LLVector3 calc_binormal_from_triangle( +void calc_binormal_from_triangle(LLVector4a& binormal, + const LLVector3& pos0, const LLVector2& tex0, const LLVector3& pos1, @@ -6196,33 +6197,42 @@ LLVector3 calc_binormal_from_triangle( const LLVector3& pos2, const LLVector2& tex2) { - LLVector3 rx0( pos0.mV[VX], tex0.mV[VX], tex0.mV[VY] ); - LLVector3 rx1( pos1.mV[VX], tex1.mV[VX], tex1.mV[VY] ); - LLVector3 rx2( pos2.mV[VX], tex2.mV[VX], tex2.mV[VY] ); + LLVector4a rx0; rx0.set( pos0.mV[VX], tex0.mV[VX], tex0.mV[VY] ); + LLVector4a rx1; rx1.set( pos1.mV[VX], tex1.mV[VX], tex1.mV[VY] ); + LLVector4a rx2; rx2.set( pos2.mV[VX], tex2.mV[VX], tex2.mV[VY] ); - LLVector3 ry0( pos0.mV[VY], tex0.mV[VX], tex0.mV[VY] ); - LLVector3 ry1( pos1.mV[VY], tex1.mV[VX], tex1.mV[VY] ); - LLVector3 ry2( pos2.mV[VY], tex2.mV[VX], tex2.mV[VY] ); + LLVector4a ry0; ry0.set( pos0.mV[VY], tex0.mV[VX], tex0.mV[VY] ); + LLVector4a ry1; ry1.set( pos1.mV[VY], tex1.mV[VX], tex1.mV[VY] ); + LLVector4a ry2; ry2.set( pos2.mV[VY], tex2.mV[VX], tex2.mV[VY] ); - LLVector3 rz0( pos0.mV[VZ], tex0.mV[VX], tex0.mV[VY] ); - LLVector3 rz1( pos1.mV[VZ], tex1.mV[VX], tex1.mV[VY] ); - LLVector3 rz2( pos2.mV[VZ], tex2.mV[VX], tex2.mV[VY] ); + LLVector4a rz0; rz0.set( pos0.mV[VZ], tex0.mV[VX], tex0.mV[VY] ); + LLVector4a rz1; rz1.set( pos1.mV[VZ], tex1.mV[VX], tex1.mV[VY] ); + LLVector4a rz2; rz2.set( pos2.mV[VZ], tex2.mV[VX], tex2.mV[VY] ); - LLVector3 r0 = (rx0 - rx1) % (rx0 - rx2); - LLVector3 r1 = (ry0 - ry1) % (ry0 - ry2); - LLVector3 r2 = (rz0 - rz1) % (rz0 - rz2); + LLVector4a lhs, rhs; + + LLVector4a r0; + lhs.setSub(rx0, rx1); rhs.setSub(rx0, rx2); + r0.setCross3(lhs, rhs); + + LLVector4a r1; + lhs.setSub(ry0, ry1); rhs.setSub(ry0, ry2); + r1.setCross3(lhs, rhs); + + LLVector4a r2; + lhs.setSub(rz0, rz1); rhs.setSub(rz0, rz2); + r2.setCross3(lhs, rhs); - if( r0.mV[VX] && r1.mV[VX] && r2.mV[VX] ) + if( r0[VX] && r1[VX] && r2[VX] ) { - LLVector3 binormal( - -r0.mV[VZ] / r0.mV[VX], - -r1.mV[VZ] / r1.mV[VX], - -r2.mV[VZ] / r2.mV[VX]); + binormal.set( + -r0[VZ] / r0[VX], + -r1[VZ] / r1[VX], + -r2[VZ] / r2[VX]); // binormal.normVec(); - return binormal; } else { - return LLVector3( 0, 1 , 0 ); + binormal.set( 0, 1 , 0 ); } } diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 17be642d4a..911db6f94b 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -40,6 +40,7 @@ class LLPathParams; class LLVolumeParams; class LLProfile; class LLPath; +class LLVector4a; class LLVolumeFace; class LLVolume; @@ -791,6 +792,19 @@ public: class LLVolumeFace { public: + class VertexData + { + public: + LLVector3 mPosition; + LLVector3 mNormal; + LLVector3 mBinormal; + LLVector2 mTexCoord; + + bool operator<(const VertexData& rhs) const; + bool operator==(const VertexData& rhs) const; + bool compareNormal(const VertexData& rhs, F32 angle_cutoff) const; + }; + LLVolumeFace() : mID(0), mTypeMask(0), @@ -808,26 +822,18 @@ public: { } + ~LLVolumeFace(); + BOOL create(LLVolume* volume, BOOL partial_build = FALSE); void createBinormals(); void appendFace(const LLVolumeFace& face, LLMatrix4& transform, LLMatrix4& normal_tranform); void resizeVertices(S32 num_verts); + void allocateBinormals(S32 num_verts); void resizeIndices(S32 num_indices); + void fillFromLegacyData(std::vector& v, std::vector& idx); - class VertexData - { - public: - LLVector3 mPosition; - LLVector3 mNormal; - LLVector3 mBinormal; - LLVector2 mTexCoord; - - bool operator<(const VertexData& rhs) const; - bool operator==(const VertexData& rhs) const; - bool compareNormal(const VertexData& rhs, F32 angle_cutoff) const; - }; class VertexMapData : public LLVolumeFace::VertexData { @@ -1051,7 +1057,8 @@ public: std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params); -LLVector3 calc_binormal_from_triangle( +void calc_binormal_from_triangle( + LLVector4a& binormal, const LLVector3& pos0, const LLVector2& tex0, const LLVector3& pos1, @@ -1060,7 +1067,7 @@ LLVector3 calc_binormal_from_triangle( const LLVector2& tex2); BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size); -BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir, +BOOL LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, F32* intersection_a, F32* intersection_b, F32* intersection_t, BOOL two_sided); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 4fb8f5266e..0fa0e80cb7 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1201,14 +1201,14 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSk if (!buff || buff->getTypeMask() != data_mask || - buff->getRequestedVerts() != vol_face.mVertices.size()) + buff->getRequestedVerts() != vol_face.mNumVertices) { face->setGeomIndex(0); face->setIndicesIndex(0); - face->setSize(vol_face.mVertices.size(), vol_face.mIndices.size()); + face->setSize(vol_face.mNumVertices, vol_face.mNumIndices); face->mVertexBuffer = new LLVertexBuffer(data_mask, 0); - face->mVertexBuffer->allocateBuffer(vol_face.mVertices.size(), vol_face.mIndices.size(), true); + face->mVertexBuffer->allocateBuffer(vol_face.mNumVertices, vol_face.mNumIndices, true); U16 offset = 0; diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 53dc335c16..77e8a6fdf9 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -928,8 +928,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { LLFastTimer t(FTM_FACE_GET_GEOM); const LLVolumeFace &vf = volume.getVolumeFace(f); - S32 num_vertices = (S32)vf.mVertices.size(); - S32 num_indices = LLPipeline::sUseTriStrips ? (S32)vf.mTriStrip.size() : (S32) vf.mIndices.size(); + S32 num_vertices = (S32)vf.mNumVertices; + S32 num_indices = (S32) vf.mNumIndices; if (mVertexBuffer.notNull()) { @@ -1128,19 +1128,9 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (full_rebuild) { mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex); - if (LLPipeline::sUseTriStrips) + for (U32 i = 0; i < (U32) num_indices; i++) { - for (U32 i = 0; i < (U32) num_indices; i++) - { - *indicesp++ = vf.mTriStrip[i] + index_offset; - } - } - else - { - for (U32 i = 0; i < (U32) num_indices; i++) - { - *indicesp++ = vf.mIndices[i] + index_offset; - } + *indicesp++ = vf.mIndices[i] + index_offset; } } @@ -1214,28 +1204,41 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, bool bake_sunlight = !getTextureEntry()->getFullbright() && !mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); + //VECTORIZE THIS for (S32 i = 0; i < num_vertices; i++) { + LLVector3 vf_binormal; + if (vf.mBinormals) + { + vf_binormal.set(vf.mBinormals+i*4); + } + + LLVector3 vf_normal; + vf_normal.set(vf.mNormals+i*4); + + LLVector3 vf_position; + vf_position.set(vf.mPositions+i*4); + if (rebuild_tcoord) { - LLVector2 tc = vf.mVertices[i].mTexCoord; + LLVector2 tc(vf.mTexCoords+i*2); if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) { - LLVector3 vec = vf.mVertices[i].mPosition; + LLVector3 vec = vf_position; vec.scaleVec(scale); switch (texgen) { case LLTextureEntry::TEX_GEN_PLANAR: - planarProjection(tc, vf.mVertices[i].mNormal, vf.mCenter, vec); + planarProjection(tc, vf_normal, vf.mCenter, vec); break; case LLTextureEntry::TEX_GEN_SPHERICAL: - sphericalProjection(tc, vf.mVertices[i].mNormal, vf.mCenter, vec); + sphericalProjection(tc, vf_normal, vf.mCenter, vec); break; case LLTextureEntry::TEX_GEN_CYLINDRICAL: - cylindricalProjection(tc, vf.mVertices[i].mNormal, vf.mCenter, vec); + cylindricalProjection(tc, vf_normal, vf.mCenter, vec); break; default: break; @@ -1345,10 +1348,10 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)) { - LLVector3 tangent = vf.mVertices[i].mBinormal % vf.mVertices[i].mNormal; + LLVector3 tangent = vf_binormal % vf_normal; LLMatrix3 tangent_to_object; - tangent_to_object.setRows(tangent, vf.mVertices[i].mBinormal, vf.mVertices[i].mNormal); + tangent_to_object.setRows(tangent, vf_binormal, vf_normal); LLVector3 binormal = binormal_dir * tangent_to_object; binormal = binormal * mat_normal; @@ -1366,12 +1369,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_pos) { - *vertices++ = vf.mVertices[i].mPosition * mat_vert; + *vertices++ = vf_position * mat_vert; } if (rebuild_normal) { - LLVector3 normal = vf.mVertices[i].mNormal * mat_normal; + LLVector3 normal = vf_normal * mat_normal; normal.normVec(); *normals++ = normal; @@ -1379,21 +1382,21 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_binormal) { - LLVector3 binormal = vf.mVertices[i].mBinormal * mat_normal; + LLVector3 binormal = vf_binormal * mat_normal; binormal.normVec(); *binormals++ = binormal; } if (rebuild_weights && vf.mWeights.size() > i) { - *weights++ = vf.mWeights[i]; + (*weights++) = vf.mWeights[i]; } if (rebuild_color) { if (bake_sunlight) { - LLVector3 normal = vf.mVertices[i].mNormal * mat_normal; + LLVector3 normal = vf_normal * mat_normal; normal.normVec(); F32 da = normal * gPipeline.mSunDir; diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 159e4b41ca..dae301ae29 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -852,6 +852,7 @@ S8 LLImagePreviewSculpted::getType() const void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance) { +#if 0 //VECTORIZE THIS mCameraDistance = distance; mCameraZoom = 1.f; mCameraPitch = 0.f; @@ -892,6 +893,7 @@ void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance) { *(index_strider++) = vf.mIndices[i]; } +#endif } @@ -901,7 +903,7 @@ void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance) BOOL LLImagePreviewSculpted::render() { mNeedsUpdate = FALSE; - +#if 0 //VECTORIZE THIS LLGLSUIDefault def; LLGLDisable no_blend(GL_BLEND); LLGLEnable cull(GL_CULL_FACE); @@ -959,7 +961,7 @@ BOOL LLImagePreviewSculpted::render() mVertexBuffer->draw(LLRender::TRIANGLES, num_indices, 0); gGL.popMatrix(); - +#endif return TRUE; } diff --git a/indra/newview/llhudicon.cpp b/indra/newview/llhudicon.cpp index 28b0e7356a..c7ad0bde7e 100644 --- a/indra/newview/llhudicon.cpp +++ b/indra/newview/llhudicon.cpp @@ -271,6 +271,7 @@ BOOL LLHUDIcon::lineSegmentIntersect(const LLVector3& start, const LLVector3& en LLVector3 upper_left = icon_position - (x_scale * 0.5f) + y_scale; LLVector3 upper_right = icon_position + (x_scale * 0.5f) + y_scale; +#if 0 //VECTORIZE THIS F32 t = 0.f; LLVector3 dir = end-start; @@ -284,6 +285,7 @@ BOOL LLHUDIcon::lineSegmentIntersect(const LLVector3& start, const LLVector3& en } return TRUE; } +#endif return FALSE; } diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index 9ed5d13831..64c01d0937 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -206,6 +206,8 @@ BOOL LLHUDText::lineSegmentIntersect(const LLVector3& start, const LLVector3& en gGL.end(); } +#if 0 //VECTORIZE THIS + LLVector3 dir = end-start; F32 t = 0.f; @@ -218,6 +220,9 @@ BOOL LLHUDText::lineSegmentIntersect(const LLVector3& start, const LLVector3& en return TRUE; } } + +#endif + } return FALSE; diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index aa82c216d9..7eca276358 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -788,13 +788,14 @@ BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts) LLMatrix4 render_mat(vo_volume->getRenderRotation(), LLVector4(vo_volume->getRenderPosition())); num_faces = volume->getNumVolumeFaces(); + //VECTORIZE THIS for (i = 0; i < num_faces; i++) { const LLVolumeFace& face = volume->getVolumeFace(i); - for (U32 v = 0; v < face.mVertices.size(); v++) + for (U32 v = 0; v < face.mNumVertices; v++) { - LLVector4 vec = LLVector4(face.mVertices[v].mPosition) * mat; + LLVector4 vec = LLVector4(face.mPositions+v*4) * mat; if (drawablep->isActive()) { diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index a82afbeb76..edb97eef24 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -640,6 +640,7 @@ BOOL LLVOGrass::lineSegmentIntersect(const LLVector3& start, const LLVector3& en position.mV[2] += blade_height; v[3] = v1 = position + mRegionp->getOriginAgent(); +#if 0 //VECTORIZE THIS F32 a,b,t; @@ -703,6 +704,7 @@ BOOL LLVOGrass::lineSegmentIntersect(const LLVector3& start, const LLVector3& en } } } +#endif } return ret; diff --git a/indra/newview/llvotextbubble.cpp b/indra/newview/llvotextbubble.cpp index 428ef20006..339da3c0bf 100644 --- a/indra/newview/llvotextbubble.cpp +++ b/indra/newview/llvotextbubble.cpp @@ -45,6 +45,7 @@ #include "llviewertexturelist.h" #include "llvolume.h" #include "pipeline.h" +#include "llvector4a.h" #include "llviewerregion.h" LLVOTextBubble::LLVOTextBubble(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) @@ -217,7 +218,7 @@ void LLVOTextBubble::updateFaceSize(S32 idx) else { const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); - face->setSize(vol_face.mVertices.size(), vol_face.mIndices.size()); + face->setSize(vol_face.mNumVertices, vol_face.mNumIndices); } } @@ -235,19 +236,37 @@ void LLVOTextBubble::getGeometry(S32 idx, const LLVolumeFace& face = getVolume()->getVolumeFace(idx); - LLVector3 pos = getPositionAgent(); + LLVector4a pos; + pos.load3(getPositionAgent().mV); + + LLVector4a scale; + scale.load3(getScale().mV); + LLColor4U color = LLColor4U(getTE(idx)->getColor()); U32 offset = mDrawable->getFace(idx)->getGeomIndex(); - for (U32 i = 0; i < face.mVertices.size(); i++) + LLVector4a* dst_pos = (LLVector4a*) verticesp.get(); + LLVector4a* src_pos = (LLVector4a*) face.mPositions; + + LLVector4a* dst_norm = (LLVector4a*) normalsp.get(); + LLVector4a* src_norm = (LLVector4a*) face.mNormals; + + LLVector2* dst_tc = (LLVector2*) texcoordsp.get(); + LLVector2* src_tc = (LLVector2*) face.mTexCoords; + + LLVector4a::memcpyNonAliased16((F32*) dst_norm, (F32*) src_norm, face.mNumVertices*4); + LLVector4a::memcpyNonAliased16((F32*) dst_tc, (F32*) src_tc, face.mNumVertices*2); + + + for (U32 i = 0; i < face.mNumVertices; i++) { - *verticesp++ = face.mVertices[i].mPosition.scaledVec(getScale()) + pos; - *normalsp++ = face.mVertices[i].mNormal; - *texcoordsp++ = face.mVertices[i].mTexCoord; + LLVector4a t; + t.setMul(src_pos[i], scale); + dst_pos[i].setAdd(t, pos); *colorsp++ = color; } - for (U32 i = 0; i < face.mIndices.size(); i++) + for (U32 i = 0; i < face.mNumIndices; i++) { *indicesp++ = face.mIndices[i] + offset; } diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index cea964a100..7d80a66041 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -60,6 +60,7 @@ #include "llflexibleobject.h" #include "llsky.h" #include "lltexturefetch.h" +#include "llvector4a.h" #include "llviewercamera.h" #include "llviewertexturelist.h" #include "llviewerobjectlist.h" @@ -1601,14 +1602,8 @@ void LLVOVolume::updateFaceSize(S32 idx) else { const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); - if (LLPipeline::sUseTriStrips) - { - facep->setSize(vol_face.mVertices.size(), vol_face.mTriStrip.size()); - } - else - { - facep->setSize(vol_face.mVertices.size(), vol_face.mIndices.size()); - } + facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices); + } } @@ -1863,21 +1858,25 @@ bool LLVOVolume::hasMedia() const LLVector3 LLVOVolume::getApproximateFaceNormal(U8 face_id) { LLVolume* volume = getVolume(); - LLVector3 result; + LLVector4a result; + result.clear(); + + LLVector3 ret; if (volume && face_id < volume->getNumVolumeFaces()) { const LLVolumeFace& face = volume->getVolumeFace(face_id); - for (S32 i = 0; i < (S32)face.mVertices.size(); ++i) + for (S32 i = 0; i < (S32)face.mNumVertices; ++i) { - result += face.mVertices[i].mNormal; + result.add(*((LLVector4a*) face.mNormals+i*4)); } - result = volumeDirectionToAgent(result); - result.normVec(); + LLVector3 ret((F32*) &result.mQ); + ret = volumeDirectionToAgent(ret); + ret.normVec(); } - return result; + return ret; } void LLVOVolume::requestMediaDataUpdate(bool isNew) @@ -3032,7 +3031,7 @@ F32 LLVOVolume::getBinRadius() for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) { const LLVolumeFace& face = volume->getVolumeFace(i); - vert_count += face.mVertices.size(); + vert_count += face.mNumVertices; } scale = 1.f/llmax(vert_count/1024.f, 1.f); -- cgit v1.3 From f9b13d8f8510b1f7f02fcf92685471461b79858e Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 10 Jun 2010 00:45:48 -0500 Subject: Add "LL_MESH_ENABLED" preprocessor flag for toggling mesh code. Couple of merge fixes. --- indra/llcommon/llassettype.cpp | 3 +- indra/llcommon/llassettype.h | 3 +- indra/llinventory/llinventorytype.cpp | 5 ++- indra/llinventory/llinventorytype.h | 2 + indra/llmath/llvolume.cpp | 13 +++--- indra/llmath/llvolume.h | 7 ++++ indra/llrender/llvertexbuffer.cpp | 4 +- indra/llvfs/llvfs.cpp | 2 + indra/newview/app_settings/settings.xml | 4 +- indra/newview/llappviewer.cpp | 4 ++ indra/newview/llassetuploadresponders.cpp | 5 +++ indra/newview/llassetuploadresponders.h | 3 +- indra/newview/lldrawpoolavatar.cpp | 48 +++++++++++++++++++++- indra/newview/lldrawpoolavatar.h | 40 ++++++++++-------- indra/newview/llface.cpp | 2 + indra/newview/llinventorybridge.cpp | 10 ++++- indra/newview/llinventorybridge.h | 4 +- indra/newview/llpanelgroupnotices.cpp | 2 + indra/newview/llpanelobjectinventory.cpp | 6 +++ indra/newview/llselectmgr.cpp | 2 + indra/newview/lltexturectrl.cpp | 12 +++++- indra/newview/lltooldraganddrop.cpp | 10 +++++ indra/newview/lltooldraganddrop.h | 4 ++ indra/newview/llviewerassettype.cpp | 2 + indra/newview/llviewerfloaterreg.cpp | 4 ++ indra/newview/llviewermenufile.cpp | 9 +++- indra/newview/llviewermenufile.h | 2 + indra/newview/llviewertexteditor.cpp | 2 + indra/newview/llviewerwindow.cpp | 4 ++ indra/newview/llvovolume.cpp | 15 ++++++- indra/newview/pipeline.cpp | 4 ++ indra/newview/pipeline.h | 13 +++--- .../default/xui/en/panel_preferences_graphics1.xml | 10 ++--- 33 files changed, 209 insertions(+), 51 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index e19f8b0454..476a23ec64 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -99,8 +99,9 @@ LLAssetDictionary::LLAssetDictionary() addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "sym link", false, false, true)); addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "sym folder link", false, false, true)); - +#if LL_MESH_ENABLED addEntry(LLAssetType::AT_MESH, new AssetEntry("MESH", "mesh", "mesh", false, false, false)); +#endif addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE, FALSE, FALSE)); diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index 90cd03c433..ebc43134cb 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -114,9 +114,10 @@ public: AT_LINK_FOLDER = 25, // Inventory folder link - +#if LL_MESH_ENABLED AT_MESH = 49, // Mesh data in our proprietary SLM format +#endif AT_COUNT = 50, diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp index 2d4ee604b0..82cd22a832 100644 --- a/indra/llinventory/llinventorytype.cpp +++ b/indra/llinventory/llinventorytype.cpp @@ -89,7 +89,9 @@ LLInventoryDictionary::LLInventoryDictionary() addEntry(LLInventoryType::IT_WEARABLE, new InventoryEntry("wearable", "wearable", 2, LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART)); addEntry(LLInventoryType::IT_ANIMATION, new InventoryEntry("animation", "animation", 1, LLAssetType::AT_ANIMATION)); addEntry(LLInventoryType::IT_GESTURE, new InventoryEntry("gesture", "gesture", 1, LLAssetType::AT_GESTURE)); +#if LL_MESH_ENABLED addEntry(LLInventoryType::IT_MESH, new InventoryEntry("mesh", "mesh", 1, LLAssetType::AT_MESH)); +#endif } @@ -150,8 +152,9 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] = LLInventoryType::IT_NONE, // AT_NONE LLInventoryType::IT_NONE, // AT_NONE LLInventoryType::IT_NONE, // AT_NONE - +#if LL_MESH_ENABLED LLInventoryType::IT_MESH // AT_MESH +#endif }; // static diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h index 37829f5eae..d2fc67ef64 100644 --- a/indra/llinventory/llinventorytype.h +++ b/indra/llinventory/llinventorytype.h @@ -68,7 +68,9 @@ public: IT_ANIMATION = 19, IT_GESTURE = 20, +#if LL_MESH_ENABLED IT_MESH = 22, +#endif IT_COUNT = 23, IT_NONE = -1 diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 09ab47b890..05868e3517 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2546,10 +2546,12 @@ S32 LLVolume::getNumFaces() const { U8 sculpt_type = (mParams.getSculptType() & LL_SCULPT_TYPE_MASK); +#if LL_MESH_ENABLED if (sculpt_type == LL_SCULPT_TYPE_MESH) { return LL_SCULPT_MESH_MAX_FACES; } +#endif return (S32)mProfilep->mFaces.size(); } @@ -2922,11 +2924,6 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, LLMemType m1(LLMemType::MTYPE_VOLUME); U8 sculpt_type = mParams.getSculptType(); - if (sculpt_type & LL_SCULPT_TYPE_MASK == LL_SCULPT_TYPE_MESH) - { - llerrs << "WTF?" << llendl; - } - BOOL data_is_empty = FALSE; if (sculpt_width == 0 || sculpt_height == 0 || sculpt_components < 3 || sculpt_data == NULL) @@ -4135,10 +4132,12 @@ void LLVolume::generateSilhouetteVertices(std::vector &vertices, normals.clear(); segments.clear(); +#if LL_MESH_ENABLED if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) { return; } +#endif S32 cur_index = 0; //for each face @@ -6335,10 +6334,14 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) resizeVertices(num_vertices); resizeIndices(num_indices); +#if LL_MESH_ENABLED if ((volume->getParams().getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH) { mEdge.resize(num_indices); } +#else + mEdge.resize(num_indices); +#endif } LLVector4a* pos = (LLVector4a*) mPositions; diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index c49d1c650d..0782944079 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -41,6 +41,8 @@ class LLVolumeParams; class LLProfile; class LLPath; +#define LL_MESH_ENABLED 0 + template class LLOctreeNode; class LLVector4a; @@ -190,10 +192,15 @@ const U8 LL_SCULPT_TYPE_SPHERE = 1; const U8 LL_SCULPT_TYPE_TORUS = 2; const U8 LL_SCULPT_TYPE_PLANE = 3; const U8 LL_SCULPT_TYPE_CYLINDER = 4; +#if LL_MESH_ENABLED const U8 LL_SCULPT_TYPE_MESH = 5; const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH; +#else +const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | + LL_SCULPT_TYPE_CYLINDER; +#endif const U8 LL_SCULPT_FLAG_INVERT = 64; const U8 LL_SCULPT_FLAG_MIRROR = 128; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 48c20b09a8..514ca25aa0 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -1318,7 +1318,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask) { if (mGLBuffer) { - if (useVBOs() && sVBOActive) + if (sVBOActive) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); sBindCount++; @@ -1330,7 +1330,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask) setup = TRUE; // ... or a client memory pointer changed } } - if (useVBOs() && mGLIndices && sIBOActive) + if (mGLIndices && sIBOActive) { /*if (sMapped) { diff --git a/indra/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp index ddb76fb2ba..2b01288fd7 100644 --- a/indra/llvfs/llvfs.cpp +++ b/indra/llvfs/llvfs.cpp @@ -2041,9 +2041,11 @@ std::string get_extension(LLAssetType::EType type) case LLAssetType::AT_ANIMATION: extension = ".lla"; break; +#if LL_MESH_ENABLED case LLAssetType::AT_MESH: extension = ".slm"; break; +#endif default: // Just use the asset server filename extension in most cases extension += "."; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 79b58bcd7c..df9393c316 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4908,7 +4908,7 @@ Type Boolean Value - 1 + 0 MigrateCacheDirectory @@ -6818,7 +6818,7 @@ Type F32 Value - 0.0 + -0.001 RenderSpotShadowOffset diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 512b1dde7f..6978cdf672 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1302,8 +1302,10 @@ bool LLAppViewer::cleanup() llinfos << "Cleaning Up" << llendflush; +#if LL_MESH_ENABLED // shut down mesh streamer gMeshRepo.shutdown(); +#endif // Must clean up texture references before viewer window is destroyed. LLHUDManager::getInstance()->updateEffects(); @@ -1728,8 +1730,10 @@ bool LLAppViewer::initThreads() mFastTimerLogThread->start(); } +#if LL_MESH_ENABLED // Mesh streaming and caching gMeshRepo.init(); +#endif LLFilePickerThread::initClass(); diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index c48dcdb061..afb76735ec 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -305,6 +305,7 @@ void LLAssetUploadResponder::uploadComplete(const LLSD& content) { } +#if LL_MESH_ENABLED LLNewAgentInventoryResponder::LLNewAgentInventoryResponder( const LLSD& post_data, const LLUUID& vfile_id, @@ -426,6 +427,7 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, content["new_asset"], TRUE); } +#endif LLSendTexLayerResponder::LLSendTexLayerResponder(const LLSD& post_data, const LLUUID& vfile_id, @@ -675,6 +677,7 @@ void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content) } +#if LL_MESH_ENABLED ///////////////////////////////////////////////////// // LLNewAgentInventoryVariablePriceResponder::Impl // ///////////////////////////////////////////////////// @@ -1142,3 +1145,5 @@ void LLNewAgentInventoryVariablePriceResponder::showConfirmationDialog( boost::intrusive_ptr(this))); } } +#endif + diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index af3b3daf46..9abaccfde0 100644 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -61,7 +61,7 @@ protected: std::string mFileName; }; - +#if LL_MESH_ENABLED // TODO*: Remove this once deprecated class LLNewAgentInventoryResponder : public LLAssetUploadResponder { @@ -116,6 +116,7 @@ private: class Impl; Impl* mImpl; }; +#endif struct LLBakedUploadData; class LLSendTexLayerResponder : public LLAssetUploadResponder diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 9268cb1d47..63ca17d62d 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -103,6 +103,7 @@ S32 normal_channel = -1; S32 specular_channel = -1; S32 cube_channel = -1; +#if LL_MESH_ENABLED static const U32 rigged_data_mask[] = { LLDrawPoolAvatar::RIGGED_SIMPLE_MASK, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_MASK, @@ -114,6 +115,7 @@ static const U32 rigged_data_mask[] = { LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP_MASK, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE_MASK, }; +#endif static LLFastTimer::DeclareTimer FTM_SHADOW_AVATAR("Avatar Shadow"); @@ -194,12 +196,14 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass) case 2: beginDeferredSkinned(); break; +#if LL_MESH_ENABLED case 3: beginDeferredRiggedSimple(); break; case 4: beginDeferredRiggedBump(); break; +#endif } } @@ -226,12 +230,14 @@ void LLDrawPoolAvatar::endDeferredPass(S32 pass) case 2: endDeferredSkinned(); break; +#if LL_MESH_ENABLED case 3: endDeferredRiggedSimple(); break; case 4: endDeferredRiggedBump(); break; +#endif } } @@ -242,7 +248,11 @@ void LLDrawPoolAvatar::renderDeferred(S32 pass) S32 LLDrawPoolAvatar::getNumPostDeferredPasses() { +#if LL_MESH_ENABLED return 6; +#else + return 1; +#endif } void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) @@ -252,6 +262,7 @@ void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) case 0: beginPostDeferredAlpha(); break; +#if LL_MESH_ENABLED case 1: beginRiggedFullbright(); break; @@ -267,6 +278,7 @@ void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) case 5: beginRiggedGlow(); break; +#endif } } @@ -284,6 +296,7 @@ void LLDrawPoolAvatar::beginPostDeferredAlpha() enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); } +#if LL_MESH_ENABLED void LLDrawPoolAvatar::beginDeferredRiggedAlpha() { sVertexProgram = &gDeferredSkinnedAlphaProgram; @@ -301,6 +314,7 @@ void LLDrawPoolAvatar::endDeferredRiggedAlpha() LLVertexBuffer::sWeight4Loc = -1; sVertexProgram = NULL; } +#endif void LLDrawPoolAvatar::endPostDeferredPass(S32 pass) { @@ -309,6 +323,7 @@ void LLDrawPoolAvatar::endPostDeferredPass(S32 pass) case 0: endPostDeferredAlpha(); break; +#if LL_MESH_ENABLED case 1: endRiggedFullbright(); break; @@ -324,6 +339,7 @@ void LLDrawPoolAvatar::endPostDeferredPass(S32 pass) case 5: endRiggedGlow(); break; +#endif } } @@ -357,7 +373,11 @@ void LLDrawPoolAvatar::renderPostDeferred(S32 pass) S32 LLDrawPoolAvatar::getNumShadowPasses() { +#if LL_MESH_ENABLED return 2; +#else + return 1; +#endif } void LLDrawPoolAvatar::beginShadowPass(S32 pass) @@ -448,6 +468,7 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); } +#if LL_MESH_ENABLED else { renderRigged(avatarp, RIGGED_SIMPLE); @@ -457,10 +478,12 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) renderRigged(avatarp, RIGGED_SHINY); renderRigged(avatarp, RIGGED_FULLBRIGHT_ALPHA); } +#endif } S32 LLDrawPoolAvatar::getNumPasses() { +#if LL_MESH_ENABLED if (LLPipeline::sImpostorRender) { return 8; @@ -473,8 +496,19 @@ S32 LLDrawPoolAvatar::getNumPasses() { return 3; } +#else + if (LLPipeline::sImpostorRender) + { + return 1; + } + else + { + return 3; + } +#endif } + S32 LLDrawPoolAvatar::getNumDeferredPasses() { if (LLPipeline::sImpostorRender) @@ -522,6 +556,7 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) case 2: beginSkinned(); break; +#if LL_MESH_ENABLED case 3: beginRiggedSimple(); break; @@ -543,6 +578,7 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) case 9: beginRiggedGlow(); break; +#endif } } @@ -566,6 +602,7 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass) case 2: endSkinned(); break; +#if LL_MESH_ENABLED case 3: endRiggedSimple(); break; @@ -587,6 +624,7 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass) case 9: endRiggedGlow(); break; +#endif } } @@ -772,6 +810,7 @@ void LLDrawPoolAvatar::endSkinned() gGL.getTexUnit(0)->activate(); } +#if LL_MESH_ENABLED void LLDrawPoolAvatar::beginRiggedSimple() { sVertexProgram = &gSkinnedObjectSimpleProgram; @@ -924,6 +963,7 @@ void LLDrawPoolAvatar::endDeferredRiggedBump() sDiffuseChannel = 0; sVertexProgram = NULL; } +#endif void LLDrawPoolAvatar::beginDeferredSkinned() { @@ -1069,6 +1109,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) return; } +#if LL_MESH_ENABLED if (pass == 3) { if (is_deferred_render) @@ -1150,7 +1191,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) gGL.setSceneBlendType(LLRender::BT_ALPHA); return; } - +#endif if (sShaderLevel > 0) { @@ -1188,6 +1229,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) } } +#if LL_MESH_ENABLED void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face) { U32 data_mask = 0; @@ -1377,7 +1419,7 @@ void LLDrawPoolAvatar::renderRiggedGlow(LLVOAvatar* avatar) { renderRigged(avatar, RIGGED_GLOW, true); } - +#endif @@ -1479,6 +1521,7 @@ LLColor3 LLDrawPoolAvatar::getDebugColor() const return LLColor3(0.f, 1.f, 0.f); } +#if LL_MESH_ENABLED void LLDrawPoolAvatar::addRiggedFace(LLFace* facep, U32 type) { if (facep->mRiggedIndex.empty()) @@ -1533,6 +1576,7 @@ void LLDrawPoolAvatar::removeRiggedFace(LLFace* facep) } } } +#endif LLVertexBufferAvatar::LLVertexBufferAvatar() : LLVertexBuffer(sDataMask, diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 4a5b009412..46ffc42f04 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -96,6 +96,23 @@ public: void beginRigid(); void beginImpostor(); void beginSkinned(); + + void endRigid(); + void endImpostor(); + void endSkinned(); + + void beginDeferredImpostor(); + void beginDeferredRigid(); + void beginDeferredSkinned(); + + void endDeferredImpostor(); + void endDeferredRigid(); + void endDeferredSkinned(); + + void beginPostDeferredAlpha(); + void endPostDeferredAlpha(); + +#if LL_MESH_ENABLED void beginRiggedSimple(); void beginRiggedFullbright(); void beginRiggedFullbrightShiny(); @@ -103,12 +120,8 @@ public: void beginRiggedAlpha(); void beginRiggedFullbrightAlpha(); void beginRiggedGlow(); - void beginPostDeferredAlpha(); void beginDeferredRiggedAlpha(); - void endRigid(); - void endImpostor(); - void endSkinned(); void endRiggedSimple(); void endRiggedFullbright(); void endRiggedFullbrightShiny(); @@ -116,18 +129,11 @@ public: void endRiggedAlpha(); void endRiggedFullbrightAlpha(); void endRiggedGlow(); - void endPostDeferredAlpha(); void endDeferredRiggedAlpha(); - void beginDeferredImpostor(); - void beginDeferredRigid(); - void beginDeferredSkinned(); void beginDeferredRiggedSimple(); void beginDeferredRiggedBump(); - void endDeferredImpostor(); - void endDeferredRigid(); - void endDeferredSkinned(); void endDeferredRiggedSimple(); void endDeferredRiggedBump(); @@ -147,11 +153,6 @@ public: void renderDeferredRiggedSimple(LLVOAvatar* avatar); void renderDeferredRiggedBump(LLVOAvatar* avatar); - /*virtual*/ LLViewerTexture *getDebugTexture(); - /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display - - void renderAvatars(LLVOAvatar *single_avatar, S32 pass = -1); // renders only one avatar if single_avatar is not null. - typedef enum { RIGGED_SIMPLE = 0, @@ -202,6 +203,13 @@ public: void removeRiggedFace(LLFace* facep); std::vector mRiggedFace[NUM_RIGGED_PASSES]; +#endif + + /*virtual*/ LLViewerTexture *getDebugTexture(); + /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display + + void renderAvatars(LLVOAvatar *single_avatar, S32 pass = -1); // renders only one avatar if single_avatar is not null. + static BOOL sSkipOpaque; static BOOL sSkipTransparent; diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index e4f9e28c77..c48106863e 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -224,11 +224,13 @@ void LLFace::destroy() { LLFastTimer t(FTM_DESTROY_DRAWPOOL); +#if LL_MESH_ENABLED if (this->isState(LLFace::RIGGED) && mDrawPoolp->getType() == LLDrawPool::POOL_AVATAR) { ((LLDrawPoolAvatar*) mDrawPoolp)->removeRiggedFace(this); } else +#endif { mDrawPoolp->removeFace(this); } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 78789eb9ce..3999a8ee88 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -917,6 +917,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, // Only should happen for broken links. new_listener = new LLLinkItemBridge(inventory, root, uuid); break; +#if LL_MESH_ENABLED case LLAssetType::AT_MESH: if(!(inv_type == LLInventoryType::IT_MESH)) { @@ -924,6 +925,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, } new_listener = new LLMeshBridge(inventory, root, uuid); break; +#endif default: llinfos << "Unhandled asset type (llassetstorage.h): " @@ -2765,7 +2767,9 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, case DAD_ANIMATION: case DAD_GESTURE: case DAD_LINK: +#if LL_MESH_ENABLED case DAD_MESH: +#endif accept = dragItemIntoFolder((LLInventoryItem*)cargo_data, drop); break; @@ -3635,7 +3639,9 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop, case DAD_BODYPART: case DAD_ANIMATION: case DAD_GESTURE: - case DAD_MESH: +#if LL_MESH_ENABLED + case DAD_MESH: +#endif { LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; const LLPermissions& perm = inv_item->getPermissions(); @@ -4843,6 +4849,7 @@ void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags) hide_context_entries(menu, items, disabled_items); } +#if LL_MESH_ENABLED // +=================================================+ // | LLMeshBridge | // +=================================================+ @@ -4899,6 +4906,7 @@ void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) hide_context_entries(menu, items, disabled_items); } +#endif // +=================================================+ // | LLLinkBridge | diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index d637fc6e36..8de7d63173 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -527,7 +527,7 @@ protected: }; - +#if LL_MESH_ENABLED class LLMeshBridge : public LLItemBridge { friend class LLInvFVBridge; @@ -543,7 +543,7 @@ protected: const LLUUID& uuid) : LLItemBridge(inventory, root, uuid) {} }; - +#endif diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 7d82a10ca2..d8cfd4fc5d 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -159,7 +159,9 @@ BOOL LLGroupDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, case DAD_ANIMATION: case DAD_GESTURE: case DAD_CALLINGCARD: +#if LL_MESH_ENABLED case DAD_MESH: +#endif { LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data; if(gInventory.getItem(inv_item->getUUID()) diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 898cabb03d..58df2746f3 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -819,7 +819,9 @@ BOOL LLTaskCategoryBridge::dragOrDrop(MASK mask, BOOL drop, case DAD_ANIMATION: case DAD_GESTURE: case DAD_CALLINGCARD: +#if LL_MESH_ENABLED case DAD_MESH: +#endif accept = LLToolDragAndDrop::isInventoryDropAcceptable(object, (LLViewerInventoryItem*)cargo_data); if(accept && drop) { @@ -1240,6 +1242,7 @@ LLUIImagePtr LLTaskWearableBridge::getIcon() const return LLInventoryIcon::getIcon(mAssetType, mInventoryType, FALSE, mFlags, FALSE ); } +#if LL_MESH_ENABLED ///---------------------------------------------------------------------------- /// Class LLTaskMeshBridge ///---------------------------------------------------------------------------- @@ -1351,6 +1354,7 @@ void LLTaskMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) hide_context_entries(menu, items, disabled_items); } +#endif ///---------------------------------------------------------------------------- /// LLTaskInvFVBridge impl @@ -1431,11 +1435,13 @@ LLTaskInvFVBridge* LLTaskInvFVBridge::createObjectBridge(LLPanelObjectInventory* object->getUUID(), object->getName()); break; +#if LL_MESH_ENABLED case LLAssetType::AT_MESH: new_bridge = new LLTaskMeshBridge(panel, object->getUUID(), object->getName()); break; +#endif default: llinfos << "Unhandled inventory type (llassetstorage.h): " << (S32)type << llendl; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index ceef03d2f8..0ce7ffb077 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -6165,6 +6165,7 @@ S32 LLObjectSelection::getObjectCount(BOOL mesh_adjust) cleanupNodes(); S32 count = mList.size(); +#if LL_MESH_ENABLED if (mesh_adjust) { for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) @@ -6185,6 +6186,7 @@ S32 LLObjectSelection::getObjectCount(BOOL mesh_adjust) } } +#endif return count; } diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 7b57f09e59..6088c31559 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -292,7 +292,11 @@ BOOL LLFloaterTexturePicker::handleDragAndDrop( { BOOL handled = FALSE; - if ((cargo_type == DAD_TEXTURE) || (cargo_type == DAD_MESH)) + bool is_mesh = false; +#if LL_MESH_ENABLED + is_mesh = cargo_type == DAD_MESH; +#endif + if ((cargo_type == DAD_TEXTURE) || is_mesh) { LLInventoryItem *item = (LLInventoryItem *)cargo_data; @@ -1177,8 +1181,12 @@ BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, // returns true, then the cast was valid, and we can perform // the third test without problems. LLInventoryItem* item = (LLInventoryItem*)cargo_data; + bool is_mesh = false; +#if LL_MESH_ENABLED + is_mesh = cargo_type == DAD_MESH; +#endif if (getEnabled() && - ((cargo_type == DAD_TEXTURE) || (cargo_type == DAD_MESH)) && + ((cargo_type == DAD_TEXTURE) || is_mesh) && allowDrop(item)) { if (drop) diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 15924d67cf..d679ccd3d8 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -331,7 +331,9 @@ LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary() addEntry(DAD_ANIMATION, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); addEntry(DAD_GESTURE, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dActivateGesture, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); addEntry(DAD_LINK, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL)); +#if LL_MESH_ENABLED addEntry(DAD_MESH, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dMeshObject, &LLToolDragAndDrop::dad3dNULL)); +#endif // TODO: animation on self could play it? edit it? // TODO: gesture on self could play it? edit it? }; @@ -1035,6 +1037,7 @@ void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj, hit_obj->sendTEUpdate(); } +#if LL_MESH_EANBLED void LLToolDragAndDrop::dropMesh(LLViewerObject* hit_obj, LLInventoryItem* item, LLToolDragAndDrop::ESource source, @@ -1059,6 +1062,7 @@ void LLToolDragAndDrop::dropMesh(LLViewerObject* hit_obj, dialog_refresh_all(); } +#endif /* void LLToolDragAndDrop::dropTextureOneFaceAvatar(LLVOAvatar* avatar, S32 hit_face, LLInventoryItem* item) @@ -1501,7 +1505,9 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_ case DAD_ANIMATION: case DAD_GESTURE: case DAD_CALLINGCARD: +#if LL_MESH_ENABLED case DAD_MESH: +#endif { LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data; if(gInventory.getItem(inv_item->getUUID()) @@ -1858,10 +1864,12 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject( dropTextureOneFace(obj, face, item, mSource, mSourceID); } } +#if LL_MESH_ENABLED else if (cargo_type == DAD_MESH) { dropMesh(obj, item, mSource, mSourceID); } +#endif else { llwarns << "unsupported asset type" << llendl; @@ -1886,11 +1894,13 @@ EAcceptance LLToolDragAndDrop::dad3dTextureObject( return dad3dApplyToObject(obj, face, mask, drop, DAD_TEXTURE); } +#if LL_MESH_ENABLED EAcceptance LLToolDragAndDrop::dad3dMeshObject( LLViewerObject* obj, S32 face, MASK mask, BOOL drop) { return dad3dApplyToObject(obj, face, mask, drop, DAD_MESH); } +#endif diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 596cc2ee88..ceeaa8c820 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -154,8 +154,10 @@ protected: MASK mask, BOOL drop); EAcceptance dad3dTextureObject(LLViewerObject* obj, S32 face, MASK mask, BOOL drop); +#if LL_MESH_ENABLED EAcceptance dad3dMeshObject(LLViewerObject* obj, S32 face, MASK mask, BOOL drop); +#endif // EAcceptance dad3dTextureSelf(LLViewerObject* obj, S32 face, // MASK mask, BOOL drop); EAcceptance dad3dWearItem(LLViewerObject* obj, S32 face, @@ -242,10 +244,12 @@ public: LLInventoryItem* item, ESource source, const LLUUID& src_id); +#if LL_MESH_ENABLED static void dropMesh(LLViewerObject* hit_obj, LLInventoryItem* item, ESource source, const LLUUID& src_id); +#endif //static void dropTextureOneFaceAvatar(LLVOAvatar* avatar,S32 hit_face, // LLInventoryItem* item) diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp index 4c088a72b7..370767002a 100644 --- a/indra/newview/llviewerassettype.cpp +++ b/indra/newview/llviewerassettype.cpp @@ -85,7 +85,9 @@ LLViewerAssetDictionary::LLViewerAssetDictionary() addEntry(LLViewerAssetType::AT_LINK, new ViewerAssetEntry(DAD_LINK)); addEntry(LLViewerAssetType::AT_LINK_FOLDER, new ViewerAssetEntry(DAD_LINK)); +#if LL_MESH_ENABLED addEntry(LLViewerAssetType::AT_MESH, new ViewerAssetEntry(DAD_MESH)); +#endif addEntry(LLViewerAssetType::AT_NONE, new ViewerAssetEntry(DAD_NONE)); }; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 525610f983..c953fb23e3 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -177,7 +177,9 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); +#if LL_MESH_ENABLED LLFloaterReg::add("import_collada", "floater_import_collada.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); +#endif LLFloaterReg::add("im_container", "floater_im_container.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("im_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); @@ -258,7 +260,9 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("upload_anim", "floater_animation_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "upload"); LLFloaterReg::add("upload_image", "floater_image_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "upload"); LLFloaterReg::add("upload_sound", "floater_sound_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "upload"); +#if LL_MESH_ENABLED LLFloaterReg::add("upload_model", "floater_model_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "upload"); +#endif LLFloaterReg::add("voice_controls", "floater_voice_controls.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("voice_effect", "floater_voice_effect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index dd65ca2d25..af4549f7e1 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -350,6 +350,7 @@ class LLFileUploadImage : public view_listener_t } }; +#if LL_MESH_ENABLED class LLFileUploadScene : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -376,6 +377,7 @@ class LLFileUploadModel : public view_listener_t return TRUE; } }; +#endif class LLFileUploadSound : public view_listener_t { @@ -1144,6 +1146,7 @@ void upload_new_resource( lldebugs << "Folder: " << gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(asset_type) : destination_folder_type) << llendl; lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl; +#if LL_MESH_ENABLED std::string url = gAgent.getRegion()->getCapability( "NewFileAgentInventory"); @@ -1171,8 +1174,8 @@ void upload_new_resource( asset_type)); } else +#endif { - llinfos << "NewAgentInventory capability not found, new agent inventory via asset system." << llendl; // check for adequate funds // TODO: do this check on the sim if (LLAssetType::AT_SOUND == asset_type || @@ -1217,6 +1220,7 @@ void upload_new_resource( } } +#if LL_MESH_ENABLED BOOL upload_new_variable_price_resource( const LLTransactionID &tid, LLAssetType::EType asset_type, @@ -1288,6 +1292,7 @@ BOOL upload_new_variable_price_resource( return FALSE; } } +#endif LLAssetID generate_asset_id_for_new_upload(const LLTransactionID& tid) { @@ -1358,8 +1363,10 @@ void init_menu_file() view_listener_t::addCommit(new LLFileUploadImage(), "File.UploadImage"); view_listener_t::addCommit(new LLFileUploadSound(), "File.UploadSound"); view_listener_t::addCommit(new LLFileUploadAnim(), "File.UploadAnim"); +#if LL_MESH_ENABLED view_listener_t::addCommit(new LLFileUploadModel(), "File.UploadModel"); view_listener_t::addCommit(new LLFileUploadScene(), "File.UploadScene"); +#endif view_listener_t::addCommit(new LLFileUploadBulk(), "File.UploadBulk"); view_listener_t::addCommit(new LLFileCloseWindow(), "File.CloseWindow"); view_listener_t::addCommit(new LLFileCloseAllWindows(), "File.CloseAllWindows"); diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index 08444551a9..bb7cfce862 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -74,6 +74,7 @@ void upload_new_resource( S32 expected_upload_cost, void *userdata); +#if LL_MESH_ENABLED // TODO* : Move all uploads to use this new function // since at some point, that upload path will be deprecated and no longer // used @@ -91,6 +92,7 @@ BOOL upload_new_variable_price_resource( U32 everyone_perms, const std::string& display_name, const LLSD& asset_resources); +#endif LLAssetID generate_asset_id_for_new_upload(const LLTransactionID& tid); void increase_new_upload_stats(LLAssetType::EType asset_type); diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index d35be8e1bf..697e8afa65 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -535,7 +535,9 @@ LLUIImagePtr LLEmbeddedItems::getItemImage(llwchar ext_char) const case LLAssetType::AT_BODYPART: img_name = "Inv_Skin"; break; case LLAssetType::AT_ANIMATION: img_name = "Inv_Animation"; break; case LLAssetType::AT_GESTURE: img_name = "Inv_Gesture"; break; +#if LL_MESH_ENABLED case LLAssetType::AT_MESH: img_name = "Inv_Mesh"; break; +#endif default: llassert(0); } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index fc4b590bf4..9f559331b0 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -591,8 +591,10 @@ public: if (gSavedSettings.getBOOL("DebugShowUploadCost")) { +#if LL_MESH_ENABLED addText(xpos, ypos, llformat(" Meshes: L$%d", gPipeline.mDebugMeshUploadCost)); ypos += y_inc/2; +#endif addText(xpos, ypos, llformat(" Sculpties: L$%d", gPipeline.mDebugSculptUploadCost)); ypos += y_inc/2; addText(xpos, ypos, llformat(" Textures: L$%d", gPipeline.mDebugTextureUploadCost)); @@ -602,6 +604,7 @@ public: ypos += y_inc; } +#if LL_MESH_ENABLED //temporary hack to give feedback on mesh upload progress if (!gMeshRepo.mUploads.empty()) { @@ -631,6 +634,7 @@ public: ypos += y_inc; } +#endif } void draw() diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index db9e0b88e1..d66aa567a8 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -926,6 +926,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool BOOL is404 = FALSE; +#if LL_MESH_ENABLED if (isSculpted()) { // if it's a mesh @@ -945,6 +946,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool } } } +#endif // Check if we need to change implementations bool is_flexible = (volume_params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE); @@ -989,10 +991,11 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool updateSculptTexture(); + if (isSculpted()) { updateSculptTexture(); - +#if LL_MESH_ENABLED // if it's a mesh if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) { @@ -1008,6 +1011,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool } } else // otherwise is sculptie +#endif { if (mSculptTexture.notNull()) { @@ -2659,12 +2663,13 @@ BOOL LLVOVolume::isMesh() const { LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); U8 sculpt_type = sculpt_params->getSculptType(); - +#if LL_MESH_ENABLED if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) // mesh is a mesh { return TRUE; } +#endif } return FALSE; @@ -3010,6 +3015,7 @@ F32 LLVOVolume::getBinRadius() F32 scale = 1.f; +#if LL_MESH_ENABLED if (isSculpted()) { LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); @@ -3031,6 +3037,7 @@ F32 LLVOVolume::getBinRadius() scale = 1.f/llmax(vert_count/1024.f, 1.f); } } +#endif const LLVector4a* ext = mDrawable->getSpatialExtents(); @@ -3513,9 +3520,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) drawablep->clearState(LLDrawable::HAS_ALPHA); +#if LL_MESH_ENABLED bool rigged = vobj->isAttachment() && vobj->isMesh() && gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID()); +#endif bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); @@ -3526,6 +3535,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) drawablep->updateFaceSize(i); LLFace* facep = drawablep->getFace(i); +#if LL_MESH_ENABLED if (rigged) { if (!facep->isState(LLFace::RIGGED)) @@ -3622,6 +3632,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) facep->clearState(LLFace::RIGGED); } } +#endif if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 583b3df0e5..c5c7277211 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2025,7 +2025,9 @@ void LLPipeline::rebuildPriorityGroups() assertInitialized(); +#if LL_MESH_ENABLED gMeshRepo.notifyLoadedMeshes(); +#endif // Iterate through all drawables on the priority build queue, for (LLSpatialGroup::sg_list_t::iterator iter = mGroupQ1.begin(); @@ -3859,6 +3861,7 @@ void LLPipeline::renderDebug() gPipeline.mDebugTextureUploadCost = textures.size() * 10; gPipeline.mDebugSculptUploadCost = sculpts.size()*10; +#if LL_MESH_ENABLED U32 mesh_cost = 0; for (std::set::iterator iter = meshes.begin(); iter != meshes.end(); ++iter) @@ -3867,6 +3870,7 @@ void LLPipeline::renderDebug() } gPipeline.mDebugMeshUploadCost = mesh_cost; +#endif } for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 4e8760947c..95f951b393 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -45,6 +45,7 @@ #include "llgl.h" #include "lldrawable.h" #include "llrendertarget.h" +#include "llmodel.h" //for LL_MESH_ENaBLED #include @@ -61,7 +62,10 @@ class LLCullResult; class LLVOAvatar; class LLGLSLShader; class LLCurlRequest; + +#if LL_MESH_ENABLED class LLMeshResponder; +#endif typedef enum e_avatar_skinning_method { @@ -465,7 +469,9 @@ public: S32 mDebugTextureUploadCost; S32 mDebugSculptUploadCost; +#if LL_MESH_ENABLED S32 mDebugMeshUploadCost; +#endif S32 mLightingChanges; S32 mGeometryChanges; @@ -712,13 +718,6 @@ public: protected: std::vector mSelectedFaces; - - typedef std::map > mesh_load_map; - mesh_load_map mLoadingMeshes[4]; - - typedef std::list mesh_response_list; - mesh_response_list mMeshResponseList; - LLPointer mFaceSelectImagep; U32 mLightMask; diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml index 8b431e9c54..b54bad98d0 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml @@ -160,7 +160,7 @@ layout="topleft" left="5" name="CustomGraphics Panel" - top="101" + top="76" width="485"> Low @@ -625,7 +625,7 @@ follows="left|top" height="12" layout="topleft" - left_delta="-260" + left="200" name="AvatarRenderingText" top_pad="8" width="128"> @@ -673,7 +673,7 @@ left="358" left_pad="-30" name="TerrainDetailText" - top="488" + top="226" width="155"> Terrain detail: -- cgit v1.3 From 46768c3c6c263ec27a80c854734ce0b61d29686f Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 12 Jul 2010 07:39:23 -0500 Subject: Merge? --- indra/llmath/llvolume.cpp | 186 ++++++++++++++++++++++--------------- indra/llrender/llvertexbuffer.cpp | 2 +- indra/newview/lldrawpoolavatar.cpp | 4 +- indra/newview/llface.cpp | 2 +- 4 files changed, 116 insertions(+), 78 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index a4022c842d..38944d3855 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -5245,6 +5245,10 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) mNumS = src.mNumS; mNumT = src.mNumT; + mExtents[0] = src.mExtents[0]; + mExtents[1] = src.mExtents[1]; + *mCenter = *src.mCenter; + mNumVertices = 0; mNumIndices = 0; @@ -5297,7 +5301,6 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) LLVector4a::memcpyNonAliased16((F32*) mIndices, (F32*) src.mIndices, idx_size); } - //delete return *this; } @@ -5535,88 +5538,100 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) S32 offset = 0; if (mTypeMask & TOP_MASK) + { offset = (max_t-1) * max_s; + } else + { offset = mBeginS; - - VertexData corners[4]; - VertexData baseVert; - for(int t = 0; t < 4; t++){ - corners[t].getPosition().load3( mesh[offset + (grid_size*t)].mPos.mV); - corners[t].mTexCoord.mV[0] = profile[grid_size*t].mV[0]+0.5f; - corners[t].mTexCoord.mV[1] = 0.5f - profile[grid_size*t].mV[1]; } { - LLVector4a lhs; - lhs.setSub(corners[1].getPosition(), corners[0].getPosition()); - LLVector4a rhs; - rhs.setSub(corners[2].getPosition(), corners[1].getPosition()); - baseVert.getNormal().setCross3(lhs, rhs); - baseVert.getNormal().normalize3fast(); - } + VertexData corners[4]; + VertexData baseVert; + for(S32 t = 0; t < 4; t++) + { + corners[t].getPosition().load3( mesh[offset + (grid_size*t)].mPos.mV); + corners[t].mTexCoord.mV[0] = profile[grid_size*t].mV[0]+0.5f; + corners[t].mTexCoord.mV[1] = 0.5f - profile[grid_size*t].mV[1]; + } - if(!(mTypeMask & TOP_MASK)){ - baseVert.getNormal().mul(-1.0f); - }else{ - //Swap the UVs on the U(X) axis for top face - LLVector2 swap; - swap = corners[0].mTexCoord; - corners[0].mTexCoord=corners[3].mTexCoord; - corners[3].mTexCoord=swap; - swap = corners[1].mTexCoord; - corners[1].mTexCoord=corners[2].mTexCoord; - corners[2].mTexCoord=swap; - } + { + LLVector4a lhs; + lhs.setSub(corners[1].getPosition(), corners[0].getPosition()); + LLVector4a rhs; + rhs.setSub(corners[2].getPosition(), corners[1].getPosition()); + baseVert.getNormal().setCross3(lhs, rhs); + baseVert.getNormal().normalize3fast(); + } - LLVector4a binormal; - - calc_binormal_from_triangle( binormal, - corners[0].getPosition(), corners[0].mTexCoord, - corners[1].getPosition(), corners[1].mTexCoord, - corners[2].getPosition(), corners[2].mTexCoord); - - binormal.normalize3fast(); + if(!(mTypeMask & TOP_MASK)) + { + baseVert.getNormal().mul(-1.0f); + } + else + { + //Swap the UVs on the U(X) axis for top face + LLVector2 swap; + swap = corners[0].mTexCoord; + corners[0].mTexCoord=corners[3].mTexCoord; + corners[3].mTexCoord=swap; + swap = corners[1].mTexCoord; + corners[1].mTexCoord=corners[2].mTexCoord; + corners[2].mTexCoord=swap; + } - S32 size = (grid_size+1)*(grid_size+1); - resizeVertices(size); - allocateBinormals(size); + LLVector4a binormal; + + calc_binormal_from_triangle( binormal, + corners[0].getPosition(), corners[0].mTexCoord, + corners[1].getPosition(), corners[1].mTexCoord, + corners[2].getPosition(), corners[2].mTexCoord); + + binormal.normalize3fast(); - LLVector4a* pos = (LLVector4a*) mPositions; - LLVector4a* norm = (LLVector4a*) mNormals; - LLVector4a* binorm = (LLVector4a*) mBinormals; - LLVector2* tc = (LLVector2*) mTexCoords; + S32 size = (grid_size+1)*(grid_size+1); + resizeVertices(size); + allocateBinormals(size); - for(int gx = 0;gxsetAdd(min, max); - mCenter->mul(0.5f); + mCenter->setAdd(min, max); + mCenter->mul(0.5f); + } if (!partial_build) { @@ -6249,73 +6264,96 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat llerrs << "Cannot append face -- 16-bit overflow will occur." << llendl; } - + if (face.mNumVertices == 0) + { + llerrs << "Cannot append empty face." << llendl; + } + + //allocate new buffer space LLVector4a* new_pos = (LLVector4a*) ll_aligned_malloc_16(new_count*16); LLVector4a* new_norm = (LLVector4a*) ll_aligned_malloc_16(new_count*16); LLVector2* new_tc = (LLVector2*) ll_aligned_malloc_16((new_count*8+0xF) & ~0xF); + if (mNumVertices > 0) - { + { //copy old buffers LLVector4a::memcpyNonAliased16((F32*) new_pos, (F32*) mPositions, mNumVertices*4); LLVector4a::memcpyNonAliased16((F32*) new_norm, (F32*) mNormals, mNumVertices*4); LLVector4a::memcpyNonAliased16((F32*) new_tc, (F32*) mTexCoords, mNumVertices*2); } + //free old buffer space ll_aligned_free_16(mPositions); ll_aligned_free_16(mNormals); ll_aligned_free_16(mTexCoords); + //point to new buffers mPositions = new_pos; mNormals = new_norm; mTexCoords = new_tc; mNumVertices = new_count; + //get destination address of appended face LLVector4a* dst_pos = mPositions+offset; LLVector2* dst_tc = mTexCoords+offset; LLVector4a* dst_norm = mNormals+offset; + //get source addresses of appended face const LLVector4a* src_pos = face.mPositions; const LLVector2* src_tc = face.mTexCoords; const LLVector4a* src_norm = face.mNormals; + //load aligned matrices LLMatrix4a mat, norm_mat; mat.loadu(mat_in); norm_mat.loadu(norm_mat_in); for (U32 i = 0; i < face.mNumVertices; ++i) { + //transform appended face position and store mat.affineTransform(src_pos[i], dst_pos[i]); + + //transform appended face normal and store norm_mat.rotate(src_norm[i], dst_norm[i]); dst_norm[i].normalize3fast(); + //copy appended face texture coordinate dst_tc[i] = src_tc[i]; if (offset == 0 && i == 0) - { + { //initialize bounding box mExtents[0] = mExtents[1] = dst_pos[i]; } else { + //stretch bounding box update_min_max(mExtents[0], mExtents[1], dst_pos[i]); } } new_count = mNumIndices + face.mNumIndices; + + //allocate new index buffer U16* new_indices = (U16*) ll_aligned_malloc_16((new_count*2+0xF) & ~0xF); if (mNumIndices > 0) - { - LLVector4a::memcpyNonAliased16((F32*) new_indices, (F32*) mIndices, llmax(mNumIndices/2, 1)); + { //copy old index buffer + LLVector4a::memcpyNonAliased16((F32*) new_indices, (F32*) mIndices, llmax(mNumIndices/2, 4)); } + //free old index buffer ll_aligned_free_16(mIndices); + + //point to new index buffer mIndices = new_indices; + + //get destination address into new index buffer U16* dst_idx = mIndices+mNumIndices; mNumIndices = new_count; for (U32 i = 0; i < face.mNumIndices; ++i) - { + { //copy indices, offsetting by old vertex count dst_idx[i] = face.mIndices[i]+offset; } } diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 514ca25aa0..1d02ca4f4c 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -267,7 +267,7 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of if (start >= (U32) mRequestedNumVerts || end >= (U32) mRequestedNumVerts) { - llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "]" << llendl; + llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "] vs " << mRequestedNumVerts << llendl; } llassert(mRequestedNumIndices >= 0); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 63ca17d62d..c7e77fd6ba 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1249,10 +1249,10 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSk { face->setGeomIndex(0); face->setIndicesIndex(0); - face->setSize(vol_face.mNumVertices, vol_face.mNumIndices); + face->setSize(vol_face.mNumVertices, vol_face.mNumIndices, true); face->mVertexBuffer = new LLVertexBuffer(data_mask, 0); - face->mVertexBuffer->allocateBuffer(vol_face.mNumVertices, vol_face.mNumIndices, true); + face->mVertexBuffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), true); U16 offset = 0; diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index c48106863e..8533f9710c 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1583,7 +1583,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_weights && vf.mWeights) { - LLVector4a::memcpyNonAliased16((F32*) weights, (F32*) vf.mWeights, num_vertices/4); + LLVector4a::memcpyNonAliased16((F32*) weights, (F32*) vf.mWeights, num_vertices*4); } if (rebuild_color) -- cgit v1.3 From ddd7a3ebb58fb56fe100b4fe2dc0e5e8076948d6 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 12 Aug 2010 11:40:54 -0500 Subject: Make rigged attachments respect "Show me in mouselook" option. --- indra/newview/lldrawpoolavatar.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index c7e77fd6ba..ef1d2ec1c5 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -38,6 +38,7 @@ #include "llvoavatar.h" #include "m3math.h" +#include "llagent.h" //for gAgent.needsRenderAvatar() #include "lldrawable.h" #include "lldrawpoolbump.h" #include "llface.h" @@ -1274,6 +1275,11 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSk void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { + if (avatar->isSelf() && !gAgent.needsRenderAvatar()) + { + return; + } + for (U32 i = 0; i < mRiggedFace[type].size(); ++i) { LLFace* face = mRiggedFace[type][i]; -- cgit v1.3 From 340a729d55983110a85cfc55f1ce0a952bfe15b4 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 12 Aug 2010 17:05:40 -0500 Subject: Vertex buffer cleanup, adding water shader to simple rigged attachments. Reviewed by Nyx. --- indra/llrender/llvertexbuffer.cpp | 232 +++++------------------------------- indra/llrender/llvertexbuffer.h | 20 ++-- indra/newview/lldrawpoolavatar.cpp | 32 +++-- indra/newview/llviewershadermgr.cpp | 25 ++++ indra/newview/llviewershadermgr.h | 5 + indra/newview/llvosurfacepatch.cpp | 22 ++-- indra/newview/llvovolume.cpp | 6 +- indra/newview/llvowlsky.cpp | 2 +- 8 files changed, 105 insertions(+), 239 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 9783435e2f..71620feed3 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -68,11 +68,8 @@ S32 LLVertexBuffer::sWeight4Loc = -1; std::vector LLVertexBuffer::sDeleteList; -#define LL_ALIGNED_VB 1 -#if LL_ALIGNED_VB - -S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] = +S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] = { sizeof(LLVector4), // TYPE_VERTEX, sizeof(LLVector4), // TYPE_NORMAL, @@ -87,25 +84,6 @@ S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] = sizeof(LLVector4), // TYPE_CLOTHWEIGHT, }; -#else - -S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] = -{ - sizeof(LLVector3), // TYPE_VERTEX, - sizeof(LLVector3), // TYPE_NORMAL, - sizeof(LLVector2), // TYPE_TEXCOORD0, - sizeof(LLVector2), // TYPE_TEXCOORD1, - sizeof(LLVector2), // TYPE_TEXCOORD2, - sizeof(LLVector2), // TYPE_TEXCOORD3, - sizeof(LLColor4U), // TYPE_COLOR, - sizeof(LLVector3), // TYPE_BINORMAL, - sizeof(F32), // TYPE_WEIGHT, - sizeof(LLVector4), // TYPE_WEIGHT4, - sizeof(LLVector4), // TYPE_CLOTHWEIGHT, -}; - -#endif - U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] = { GL_TRIANGLES, @@ -460,19 +438,22 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : mUsage = 0; } - S32 stride = calcStride(typemask, mOffsets); + //zero out offsets + for (U32 i = 0; i < TYPE_MAX; i++) + { + mOffsets[i] = 0; + } mTypeMask = typemask; - mStride = stride; + mSize = 0; mAlignedOffset = 0; mAlignedIndexOffset = 0; sCount++; } -#if LL_ALIGNED_VB //static -S32 LLVertexBuffer::calcStride(const U32& typemask, S32* offsets, S32 num_vertices) +S32 LLVertexBuffer::calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices) { S32 offset = 0; for (S32 i=0; i struct VertexBufferStrider { typedef LLStrider strider_t; @@ -1051,7 +1015,7 @@ template struct VertexBufferStrider } else if (vbo.hasDataType(type)) { - S32 stride = LLVertexBuffer::sTypeOffsets[type]; + S32 stride = LLVertexBuffer::sTypeSize[type]; strider = (T*)(vbo.getMappedData() + vbo.getOffset(type)+index*stride); strider.setStride(stride); return TRUE; @@ -1064,45 +1028,6 @@ template struct VertexBufferStrider } }; -#else - -template struct VertexBufferStrider -{ - typedef LLStrider strider_t; - static bool get(LLVertexBuffer& vbo, - strider_t& strider, - S32 index) - { - if (vbo.mapBuffer() == NULL) - { - llwarns << "mapBuffer failed!" << llendl; - return FALSE; - } - - if (type == LLVertexBuffer::TYPE_INDEX) - { - S32 stride = sizeof(T); - strider = (T*)(vbo.getMappedIndices() + index*stride); - strider.setStride(0); - return TRUE; - } - else if (vbo.hasDataType(type)) - { - S32 stride = vbo.getStride(); - strider = (T*)(vbo.getMappedData() + vbo.getOffset(type) + index*stride); - strider.setStride(stride); - return TRUE; - } - else - { - llerrs << "VertexBufferStrider could not find valid vertex data." << llendl; - } - return FALSE; - } -}; - -#endif - bool LLVertexBuffer::getVertexStrider(LLStrider& strider, S32 index) { return VertexBufferStrider::get(*this, strider, index); @@ -1154,25 +1079,6 @@ bool LLVertexBuffer::getClothWeightStrider(LLStrider& strider, S32 in return VertexBufferStrider::get(*this, strider, index); } -void LLVertexBuffer::setStride(S32 type, S32 new_stride) -{ - LLMemType mt2(LLMemType::MTYPE_VERTEX_SET_STRIDE); - if (mNumVerts) - { - llerrs << "LLVertexBuffer::setOffset called with mNumVerts = " << mNumVerts << llendl; - } - // This code assumes that setStride() will only be called once per VBO per type. - S32 delta = new_stride - sTypeOffsets[type]; - for (S32 i=type+1; i buffer_list_t; static BOOL sEnableVBOs; - static S32 sTypeOffsets[TYPE_MAX]; + static S32 sTypeSize[TYPE_MAX]; static U32 sGLMode[LLRender::NUM_MODES]; static U32 sGLRenderBuffer; static U32 sGLRenderIndices; diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index ef1d2ec1c5..1788a3da3d 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -814,17 +814,25 @@ void LLDrawPoolAvatar::endSkinned() #if LL_MESH_ENABLED void LLDrawPoolAvatar::beginRiggedSimple() { - sVertexProgram = &gSkinnedObjectSimpleProgram; + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectSimpleWaterProgram; + } + else + { + sVertexProgram = &gSkinnedObjectSimpleProgram; + } + sDiffuseChannel = 0; - gSkinnedObjectSimpleProgram.bind(); - LLVertexBuffer::sWeight4Loc = gSkinnedObjectSimpleProgram.getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); + sVertexProgram->bind(); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } void LLDrawPoolAvatar::endRiggedSimple() { - sVertexProgram = NULL; LLVertexBuffer::unbind(); - gSkinnedObjectSimpleProgram.unbind(); + sVertexProgram->unbind(); + sVertexProgram = NULL; LLVertexBuffer::sWeight4Loc = -1; } @@ -1596,25 +1604,25 @@ void LLVertexBufferAvatar::setupVertexBuffer(U32 data_mask) const { if (sRenderingSkinned) { - U8* base = useVBOs() ? NULL : mMappedData; + U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; - glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_VERTEX], (void*)(base + 0)); - glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL])); - glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); + glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_VERTEX], (void*)(base + 0)); + glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL])); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); set_vertex_weights(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT], - LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_WEIGHT], (F32*)(base + mOffsets[TYPE_WEIGHT])); + LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_WEIGHT], (F32*)(base + mOffsets[TYPE_WEIGHT])); if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_BUMP) { set_binormals(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::BINORMAL], - LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_BINORMAL], (LLVector3*)(base + mOffsets[TYPE_BINORMAL])); + LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_BINORMAL], (LLVector3*)(base + mOffsets[TYPE_BINORMAL])); } if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH) { set_vertex_clothing_weights(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_CLOTHING], - LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_CLOTHWEIGHT], (LLVector4*)(base + mOffsets[TYPE_CLOTHWEIGHT])); + LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_CLOTHWEIGHT], (LLVector4*)(base + mOffsets[TYPE_CLOTHWEIGHT])); } } else diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 49eeffe228..e887766492 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -83,6 +83,11 @@ LLGLSLShader gSkinnedObjectFullbrightProgram; LLGLSLShader gSkinnedObjectFullbrightShinyProgram; LLGLSLShader gSkinnedObjectShinySimpleProgram; +LLGLSLShader gSkinnedObjectSimpleWaterProgram; +//LLGLSLShader gSkinnedObjectFullbrightProgram; +//LLGLSLShader gSkinnedObjectFullbrightShinyProgram; +//LLGLSLShader gSkinnedObjectShinySimpleProgram; + //environment shaders LLGLSLShader gTerrainProgram; LLGLSLShader gTerrainWaterProgram; @@ -159,6 +164,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gObjectFullbrightProgram); mShaderList.push_back(&gObjectFullbrightShinyProgram); mShaderList.push_back(&gSkinnedObjectSimpleProgram); + mShaderList.push_back(&gSkinnedObjectSimpleWaterProgram); mShaderList.push_back(&gSkinnedObjectFullbrightProgram); mShaderList.push_back(&gSkinnedObjectFullbrightShinyProgram); mShaderList.push_back(&gSkinnedObjectShinySimpleProgram); @@ -570,6 +576,7 @@ void LLViewerShaderMgr::unloadShaders() gObjectShinyWaterProgram.unload(); gSkinnedObjectSimpleProgram.unload(); + gSkinnedObjectSimpleWaterProgram.unload(); gSkinnedObjectFullbrightProgram.unload(); gSkinnedObjectFullbrightShinyProgram.unload(); gSkinnedObjectShinySimpleProgram.unload(); @@ -1299,6 +1306,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightProgram.unload(); gObjectFullbrightWaterProgram.unload(); gSkinnedObjectSimpleProgram.unload(); + gSkinnedObjectSimpleWaterProgram.unload(); gSkinnedObjectFullbrightProgram.unload(); gSkinnedObjectFullbrightShinyProgram.unload(); gSkinnedObjectShinySimpleProgram.unload(); @@ -1428,6 +1436,23 @@ BOOL LLViewerShaderMgr::loadShadersObject() success = gSkinnedObjectSimpleProgram.createShader(NULL, NULL); } + if (success) + { + gSkinnedObjectSimpleWaterProgram.mName = "Skinned Simple Water Shader"; + gSkinnedObjectSimpleWaterProgram.mFeatures.calculatesLighting = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasGamma = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasAtmospherics = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasLighting = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasWaterFog = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectSimpleWaterProgram.mShaderFiles.clear(); + gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectSimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectSimpleWaterProgram.createShader(NULL, NULL); + } + if (success) { gSkinnedObjectFullbrightProgram.mName = "Skinned Fullbright Shader"; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index da16a38427..99787f3c0a 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -319,6 +319,11 @@ extern LLGLSLShader gSkinnedObjectFullbrightProgram; extern LLGLSLShader gSkinnedObjectFullbrightShinyProgram; extern LLGLSLShader gSkinnedObjectShinySimpleProgram; +extern LLGLSLShader gSkinnedObjectSimpleWaterProgram; +//extern LLGLSLShader gSkinnedObjectFullbrightProgram; +//extern LLGLSLShader gSkinnedObjectFullbrightShinyProgram; +//extern LLGLSLShader gSkinnedObjectShinySimpleProgram; + //environment shaders extern LLGLSLShader gTerrainProgram; extern LLGLSLShader gTerrainWaterProgram; diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 02e7e7e60f..63f662c5a1 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -77,58 +77,58 @@ public: if (data_mask & MAP_NORMAL) { - glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeOffsets[TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL])); + glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL])); } if (data_mask & MAP_TEXCOORD3) { //substitute tex coord 0 for tex coord 3 glClientActiveTextureARB(GL_TEXTURE3_ARB); - glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeOffsets[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD2) { //substitute tex coord 0 for tex coord 2 glClientActiveTextureARB(GL_TEXTURE2_ARB); - glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeOffsets[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD1) { glClientActiveTextureARB(GL_TEXTURE1_ARB); - glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeOffsets[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1])); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_BINORMAL) { glClientActiveTextureARB(GL_TEXTURE2_ARB); - glTexCoordPointer(3,GL_FLOAT, LLVertexBuffer::sTypeOffsets[TYPE_BINORMAL], (void*)(base + mOffsets[TYPE_BINORMAL])); + glTexCoordPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_BINORMAL], (void*)(base + mOffsets[TYPE_BINORMAL])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD0) { - glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeOffsets[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); } if (data_mask & MAP_COLOR) { - glColorPointer(4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeOffsets[TYPE_COLOR], (void*)(base + mOffsets[TYPE_COLOR])); + glColorPointer(4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeSize[TYPE_COLOR], (void*)(base + mOffsets[TYPE_COLOR])); } if (data_mask & MAP_WEIGHT) { - glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, LLVertexBuffer::sTypeOffsets[TYPE_WEIGHT], (void*)(base + mOffsets[TYPE_WEIGHT])); + glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], (void*)(base + mOffsets[TYPE_WEIGHT])); } if (data_mask & MAP_WEIGHT4 && sWeight4Loc != -1) { - glVertexAttribPointerARB(sWeight4Loc, 4, GL_FLOAT, FALSE, LLVertexBuffer::sTypeOffsets[TYPE_WEIGHT4], (void*)(base+mOffsets[TYPE_WEIGHT4])); + glVertexAttribPointerARB(sWeight4Loc, 4, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], (void*)(base+mOffsets[TYPE_WEIGHT4])); } if (data_mask & MAP_CLOTHWEIGHT) { - glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, LLVertexBuffer::sTypeOffsets[TYPE_CLOTHWEIGHT], (void*)(base + mOffsets[TYPE_CLOTHWEIGHT])); + glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], (void*)(base + mOffsets[TYPE_CLOTHWEIGHT])); } if (data_mask & MAP_VERTEX) { - glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeOffsets[TYPE_VERTEX], (void*)(base + 0)); + glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0)); } } }; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index b69fd3f90b..6fa97b6688 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3494,8 +3494,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) std::vector alpha_faces; U32 useage = group->mSpatialPartition->mBufferUsage; - U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcStride(group->mSpatialPartition->mVertexDataMask); - U32 max_total = (gSavedSettings.getS32("RenderMaxNodeSize")*1024)/LLVertexBuffer::calcStride(group->mSpatialPartition->mVertexDataMask); + U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); + U32 max_total = (gSavedSettings.getS32("RenderMaxNodeSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); max_vertices = llmin(max_vertices, (U32) 65535); U32 cur_total = 0; @@ -3894,7 +3894,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector& faces, BOOL distance_sort) { //calculate maximum number of vertices to store in a single buffer - U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcStride(group->mSpatialPartition->mVertexDataMask); + U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); max_vertices = llmin(max_vertices, (U32) 65535); if (!distance_sort) diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index 1749ccef94..9398bf425e 100644 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -338,7 +338,7 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable) { 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::calcStride(data_mask); + const U32 max_verts = max_buffer_bytes / LLVertexBuffer::calcVertexSize(data_mask); const U32 total_stacks = getNumStacks(); -- cgit v1.3 From 62943202a7c4334ce7b7be96f8f64133444ee925 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 13 Aug 2010 14:42:07 -0500 Subject: Make rigged attachments respect under water rendering. Reviewed by Nyx. --- indra/llrender/llglslshader.cpp | 12 +++- indra/newview/lldrawpoolavatar.cpp | 70 ++++++++++++++++++++--- indra/newview/llviewershadermgr.cpp | 110 ++++++++++++++++++++++++++++-------- indra/newview/llviewershadermgr.h | 6 +- 4 files changed, 162 insertions(+), 36 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 9256e3959c..f59bac8c3c 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -709,7 +709,15 @@ GLint LLGLSLShader::getUniformLocation(const string& uniform) std::map::iterator iter = mUniformMap.find(uniform); if (iter != mUniformMap.end()) { - llassert(iter->second == glGetUniformLocationARB(mProgramObject, uniform.c_str())); + if (gDebugGL) + { + stop_glerror(); + if (iter->second != glGetUniformLocationARB(mProgramObject, uniform.c_str())) + { + llerrs << "Uniform does not match." << llendl; + } + stop_glerror(); + } return iter->second; } } @@ -900,7 +908,9 @@ void LLGLSLShader::uniformMatrix4fv(const string& uniform, U32 count, GLboolean if (location >= 0) { + stop_glerror(); glUniformMatrix4fvARB(location, count, transpose, v); + stop_glerror(); } } diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 1788a3da3d..af082eea3e 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -838,7 +838,14 @@ void LLDrawPoolAvatar::endRiggedSimple() void LLDrawPoolAvatar::beginRiggedAlpha() { - sVertexProgram = &gSkinnedObjectSimpleProgram; + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectSimpleWaterProgram; + } + else + { + sVertexProgram = &gSkinnedObjectSimpleProgram; + } sDiffuseChannel = 0; sVertexProgram->bind(); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); @@ -855,7 +862,14 @@ void LLDrawPoolAvatar::endRiggedAlpha() void LLDrawPoolAvatar::beginRiggedFullbrightAlpha() { - sVertexProgram = &gSkinnedObjectFullbrightProgram; + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectFullbrightWaterProgram; + } + else + { + sVertexProgram = &gSkinnedObjectFullbrightProgram; + } sDiffuseChannel = 0; sVertexProgram->bind(); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); @@ -871,7 +885,14 @@ void LLDrawPoolAvatar::endRiggedFullbrightAlpha() void LLDrawPoolAvatar::beginRiggedGlow() { - sVertexProgram = &gSkinnedObjectFullbrightProgram; + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectFullbrightWaterProgram; + } + else + { + sVertexProgram = &gSkinnedObjectFullbrightProgram; + } sDiffuseChannel = 0; sVertexProgram->bind(); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); @@ -887,23 +908,37 @@ void LLDrawPoolAvatar::endRiggedGlow() void LLDrawPoolAvatar::beginRiggedFullbright() { - sVertexProgram = &gSkinnedObjectFullbrightProgram; + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectFullbrightWaterProgram; + } + else + { + sVertexProgram = &gSkinnedObjectFullbrightProgram; + } sDiffuseChannel = 0; - gSkinnedObjectFullbrightProgram.bind(); + sVertexProgram->bind(); LLVertexBuffer::sWeight4Loc = gSkinnedObjectFullbrightProgram.getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } void LLDrawPoolAvatar::endRiggedFullbright() { - sVertexProgram = NULL; LLVertexBuffer::unbind(); - gSkinnedObjectFullbrightProgram.unbind(); + sVertexProgram->unbind(); + sVertexProgram = NULL; LLVertexBuffer::sWeight4Loc = -1; } void LLDrawPoolAvatar::beginRiggedShinySimple() { - sVertexProgram = &gSkinnedObjectShinySimpleProgram; + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectShinySimpleWaterProgram; + } + else + { + sVertexProgram = &gSkinnedObjectShinySimpleProgram; + } sVertexProgram->bind(); LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); @@ -920,7 +955,14 @@ void LLDrawPoolAvatar::endRiggedShinySimple() void LLDrawPoolAvatar::beginRiggedFullbrightShiny() { - sVertexProgram = &gSkinnedObjectFullbrightShinyProgram; + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectFullbrightShinyWaterProgram; + } + else + { + sVertexProgram = &gSkinnedObjectFullbrightShinyProgram; + } sVertexProgram->bind(); LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); @@ -1288,6 +1330,8 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) return; } + stop_glerror(); + for (U32 i = 0; i < mRiggedFace[type].size(); ++i) { LLFace* face = mRiggedFace[type][i]; @@ -1324,9 +1368,13 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) continue; } + stop_glerror(); + const LLVolumeFace& vol_face = volume->getVolumeFace(te); updateRiggedFaceVertexBuffer(face, skin, volume, vol_face); + stop_glerror(); + U32 data_mask = rigged_data_mask[type]; LLVertexBuffer* buff = face->mVertexBuffer; @@ -1345,6 +1393,8 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) } } + stop_glerror(); + LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv("matrixPalette", skin->mJointNames.size(), FALSE, @@ -1354,6 +1404,8 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) FALSE, (GLfloat*) mat[0].mMatrix); + stop_glerror(); + buff->setBuffer(data_mask); U16 start = face->getGeomStart(); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index e887766492..20e4333209 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -84,9 +84,9 @@ LLGLSLShader gSkinnedObjectFullbrightShinyProgram; LLGLSLShader gSkinnedObjectShinySimpleProgram; LLGLSLShader gSkinnedObjectSimpleWaterProgram; -//LLGLSLShader gSkinnedObjectFullbrightProgram; -//LLGLSLShader gSkinnedObjectFullbrightShinyProgram; -//LLGLSLShader gSkinnedObjectShinySimpleProgram; +LLGLSLShader gSkinnedObjectFullbrightWaterProgram; +LLGLSLShader gSkinnedObjectFullbrightShinyWaterProgram; +LLGLSLShader gSkinnedObjectShinySimpleWaterProgram; //environment shaders LLGLSLShader gTerrainProgram; @@ -164,10 +164,13 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gObjectFullbrightProgram); mShaderList.push_back(&gObjectFullbrightShinyProgram); mShaderList.push_back(&gSkinnedObjectSimpleProgram); - mShaderList.push_back(&gSkinnedObjectSimpleWaterProgram); mShaderList.push_back(&gSkinnedObjectFullbrightProgram); mShaderList.push_back(&gSkinnedObjectFullbrightShinyProgram); mShaderList.push_back(&gSkinnedObjectShinySimpleProgram); + mShaderList.push_back(&gSkinnedObjectSimpleWaterProgram); + mShaderList.push_back(&gSkinnedObjectFullbrightWaterProgram); + mShaderList.push_back(&gSkinnedObjectFullbrightShinyWaterProgram); + mShaderList.push_back(&gSkinnedObjectShinySimpleWaterProgram); mShaderList.push_back(&gTerrainProgram); mShaderList.push_back(&gTerrainWaterProgram); mShaderList.push_back(&gObjectSimpleWaterProgram); @@ -576,11 +579,15 @@ void LLViewerShaderMgr::unloadShaders() gObjectShinyWaterProgram.unload(); gSkinnedObjectSimpleProgram.unload(); - gSkinnedObjectSimpleWaterProgram.unload(); gSkinnedObjectFullbrightProgram.unload(); gSkinnedObjectFullbrightShinyProgram.unload(); gSkinnedObjectShinySimpleProgram.unload(); + gSkinnedObjectSimpleWaterProgram.unload(); + gSkinnedObjectFullbrightWaterProgram.unload(); + gSkinnedObjectFullbrightShinyWaterProgram.unload(); + gSkinnedObjectShinySimpleWaterProgram.unload(); + gWaterProgram.unload(); gUnderWaterProgram.unload(); @@ -1306,10 +1313,13 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightProgram.unload(); gObjectFullbrightWaterProgram.unload(); gSkinnedObjectSimpleProgram.unload(); - gSkinnedObjectSimpleWaterProgram.unload(); gSkinnedObjectFullbrightProgram.unload(); gSkinnedObjectFullbrightShinyProgram.unload(); gSkinnedObjectShinySimpleProgram.unload(); + gSkinnedObjectSimpleWaterProgram.unload(); + gSkinnedObjectFullbrightWaterProgram.unload(); + gSkinnedObjectFullbrightShinyWaterProgram.unload(); + gSkinnedObjectShinySimpleWaterProgram.unload(); return FALSE; } @@ -1436,23 +1446,6 @@ BOOL LLViewerShaderMgr::loadShadersObject() success = gSkinnedObjectSimpleProgram.createShader(NULL, NULL); } - if (success) - { - gSkinnedObjectSimpleWaterProgram.mName = "Skinned Simple Water Shader"; - gSkinnedObjectSimpleWaterProgram.mFeatures.calculatesLighting = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.hasGamma = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.hasAtmospherics = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.hasLighting = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.hasWaterFog = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectSimpleWaterProgram.mShaderFiles.clear(); - gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectSimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectSimpleWaterProgram.createShader(NULL, NULL); - } - if (success) { gSkinnedObjectFullbrightProgram.mName = "Skinned Fullbright Shader"; @@ -1500,6 +1493,77 @@ BOOL LLViewerShaderMgr::loadShadersObject() success = gSkinnedObjectShinySimpleProgram.createShader(NULL, &mShinyUniforms); } + if (success) + { + gSkinnedObjectSimpleWaterProgram.mName = "Skinned Simple Water Shader"; + gSkinnedObjectSimpleWaterProgram.mFeatures.calculatesLighting = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasGamma = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasAtmospherics = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasLighting = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasWaterFog = true; + gSkinnedObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectSimpleWaterProgram.mShaderFiles.clear(); + gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectSimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectSimpleWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gSkinnedObjectFullbrightWaterProgram.mName = "Skinned Fullbright Water Shader"; + gSkinnedObjectFullbrightWaterProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectFullbrightWaterProgram.mFeatures.hasGamma = true; + gSkinnedObjectFullbrightWaterProgram.mFeatures.hasTransport = true; + gSkinnedObjectFullbrightWaterProgram.mFeatures.isFullbright = true; + gSkinnedObjectFullbrightWaterProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectFullbrightWaterProgram.mFeatures.hasWaterFog = true; + gSkinnedObjectFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + gSkinnedObjectFullbrightWaterProgram.mShaderFiles.clear(); + gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectFullbrightWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectFullbrightWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gSkinnedObjectFullbrightShinyWaterProgram.mName = "Skinned Fullbright Shiny Water Shader"; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasGamma = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasTransport = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.isShiny = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.isFullbright = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasWaterFog = true; + gSkinnedObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.clear(); + gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectFullbrightShinyWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectFullbrightShinyWaterProgram.createShader(NULL, &mShinyUniforms); + } + + if (success) + { + gSkinnedObjectShinySimpleWaterProgram.mName = "Skinned Shiny Simple Water Shader"; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.calculatesLighting = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasGamma = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasAtmospherics = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.isShiny = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasWaterFog = true; + gSkinnedObjectShinySimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.clear(); + gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectShinySimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectShinySimpleWaterProgram.createShader(NULL, &mShinyUniforms); + } + if( !success ) { mVertexShaderLevel[SHADER_OBJECT] = 0; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 99787f3c0a..b6fa86081c 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -320,9 +320,9 @@ extern LLGLSLShader gSkinnedObjectFullbrightShinyProgram; extern LLGLSLShader gSkinnedObjectShinySimpleProgram; extern LLGLSLShader gSkinnedObjectSimpleWaterProgram; -//extern LLGLSLShader gSkinnedObjectFullbrightProgram; -//extern LLGLSLShader gSkinnedObjectFullbrightShinyProgram; -//extern LLGLSLShader gSkinnedObjectShinySimpleProgram; +extern LLGLSLShader gSkinnedObjectFullbrightWaterProgram; +extern LLGLSLShader gSkinnedObjectFullbrightShinyWaterProgram; +extern LLGLSLShader gSkinnedObjectShinySimpleWaterProgram; //environment shaders extern LLGLSLShader gTerrainProgram; -- cgit v1.3 From 2fea1d5d33ec1b41a3cfa4307a1bfa58d8014f88 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 19 Aug 2010 12:25:15 -0500 Subject: Integrate SIMD API from oreh/server-trunk-oreh --- indra/cmake/00-Common.cmake | 1 + indra/llcharacter/llkeyframemotion.cpp | 2 +- indra/llmath/CMakeLists.txt | 246 ++-- indra/llmath/llcamera.cpp | 2 +- indra/llmath/llmath.h | 1034 +++++++------- indra/llmath/lloctree.h | 19 +- indra/llmath/llquantize.h | 310 +++-- indra/llmath/llquaternion.cpp | 1921 +++++++++++++------------- indra/llmath/llquaternion.h | 1184 ++++++++-------- indra/llmath/llvolume.cpp | 123 +- indra/llmath/tests/v2math_test.cpp | 6 +- indra/llmath/tests/v3color_test.cpp | 6 +- indra/llmath/tests/v3dmath_test.cpp | 2 +- indra/llmath/tests/v3math_test.cpp | 4 +- indra/llmath/tests/v4color_test.cpp | 4 +- indra/llmath/tests/v4coloru_test.cpp | 2 +- indra/llmath/tests/v4math_test.cpp | 4 +- indra/llmath/v2math.cpp | 2 +- indra/llmath/v2math.h | 8 +- indra/llmath/v3color.h | 10 +- indra/llmath/v3dmath.h | 10 +- indra/llmath/v3math.h | 10 +- indra/llmath/v4color.h | 8 +- indra/llmath/v4coloru.h | 4 +- indra/llmath/v4math.h | 8 +- indra/llmessage/llsdmessagebuilder.cpp | 1 + indra/llmessage/lltemplatemessagebuilder.cpp | 1 + indra/llmessage/lltemplatemessagereader.cpp | 1 + indra/llrender/llrender.cpp | 4 +- indra/newview/llagent.cpp | 2 +- indra/newview/lldrawable.cpp | 10 +- indra/newview/lldrawpoolavatar.cpp | 190 ++- indra/newview/lldrawpoolavatar.h | 3 +- indra/newview/llface.cpp | 29 +- indra/newview/llface.h | 3 +- indra/newview/llflexibleobject.cpp | 2 +- indra/newview/llhudicon.cpp | 2 +- indra/newview/llpanelnearbymedia.cpp | 2 +- indra/newview/llpanelprimmediacontrols.cpp | 4 +- indra/newview/llselectmgr.cpp | 6 +- indra/newview/llspatialpartition.cpp | 44 +- indra/newview/llviewercamera.cpp | 2 +- indra/newview/llviewerjointmesh.cpp | 10 +- indra/newview/llviewerjoystick.cpp | 2 +- indra/newview/llviewermedia.cpp | 2 +- indra/newview/llviewerobject.cpp | 2 +- indra/newview/llviewerpartsim.cpp | 4 +- indra/newview/llviewertexture.cpp | 2 +- indra/newview/llvoavatar.cpp | 22 +- indra/newview/llvoavatar.h | 3 + indra/newview/llvograss.cpp | 2 +- indra/newview/llvosurfacepatch.cpp | 4 +- indra/newview/llvotextbubble.cpp | 4 +- indra/newview/llvotree.cpp | 6 +- indra/newview/llvovolume.cpp | 16 +- indra/newview/llworld.cpp | 4 +- indra/newview/pipeline.cpp | 14 +- 57 files changed, 2731 insertions(+), 2602 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 2c7bb77758..f10a61e1e7 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -68,6 +68,7 @@ if (WINDOWS) add_definitions( /Zc:wchar_t- + /arch:SSE2 ) endif (MSVC80 OR MSVC90) diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index 7bc9e97eb1..bce272082e 100644 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -1151,7 +1151,7 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8 constraint->mPositions[joint_num] = new_pos; } constraint->mFixupDistanceRMS *= 1.f / (constraint->mTotalLength * (F32)(shared_data->mChainLength - 1)); - constraint->mFixupDistanceRMS = fsqrtf(constraint->mFixupDistanceRMS); + constraint->mFixupDistanceRMS = (F32) sqrt(constraint->mFixupDistanceRMS); //reset old joint rots for (joint_num = 0; joint_num <= shared_data->mChainLength; joint_num++) diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt index dda07133d5..8d85765eb8 100644 --- a/indra/llmath/CMakeLists.txt +++ b/indra/llmath/CMakeLists.txt @@ -1,118 +1,128 @@ -# -*- cmake -*- - -project(llmath) - -include(00-Common) -include(LLCommon) - -include_directories( - ${LLCOMMON_INCLUDE_DIRS} - ) - -set(llmath_SOURCE_FILES - llbbox.cpp - llbboxlocal.cpp - llcamera.cpp - llcoordframe.cpp - llline.cpp - llmodularmath.cpp - llperlin.cpp - llquaternion.cpp - llrect.cpp - llsphere.cpp - llvolume.cpp - llvolumemgr.cpp - llvolumeoctree.cpp - llsdutil_math.cpp - m3math.cpp - m4math.cpp - raytrace.cpp - v2math.cpp - v3color.cpp - v3dmath.cpp - v3math.cpp - v4color.cpp - v4coloru.cpp - v4math.cpp - xform.cpp - ) - -set(llmath_HEADER_FILES - CMakeLists.txt - - camera.h - coordframe.h - llbbox.h - llbboxlocal.h - llcamera.h - llcoord.h - llcoordframe.h - llinterp.h - llline.h - llmath.h - llmodularmath.h - lloctree.h - llperlin.h - llplane.h - llquantize.h - llquaternion.h - llrect.h - llsphere.h - lltreenode.h - llv4math.h - llv4matrix3.h - llv4matrix4.h - llv4vector3.h - llvector4a.h - llmatrix4a.h - llvolume.h - llvolumemgr.h - llvolumeoctree.h - llsdutil_math.h - m3math.h - m4math.h - raytrace.h - v2math.h - v3color.h - v3dmath.h - v3math.h - v4color.h - v4coloru.h - v4math.h - xform.h - ) - -set_source_files_properties(${llmath_HEADER_FILES} - PROPERTIES HEADER_FILE_ONLY TRUE) - -list(APPEND llmath_SOURCE_FILES ${llmath_HEADER_FILES}) - -add_library (llmath ${llmath_SOURCE_FILES}) - -# Add tests -if (LL_TESTS) - include(LLAddBuildTest) - # UNIT TESTS - SET(llmath_TEST_SOURCE_FILES - llbboxlocal.cpp - llmodularmath.cpp - llrect.cpp - v2math.cpp - v3color.cpp - v4color.cpp - v4coloru.cpp - ) - LL_ADD_PROJECT_UNIT_TESTS(llmath "${llmath_TEST_SOURCE_FILES}") - - # INTEGRATION TESTS - set(test_libs llmath llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) - # TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests. - LL_ADD_INTEGRATION_TEST(llbbox llbbox.cpp "${test_libs}") - LL_ADD_INTEGRATION_TEST(llquaternion llquaternion.cpp "${test_libs}") - LL_ADD_INTEGRATION_TEST(mathmisc "" "${test_libs}") - LL_ADD_INTEGRATION_TEST(m3math "" "${test_libs}") - LL_ADD_INTEGRATION_TEST(v3dmath v3dmath.cpp "${test_libs}") - LL_ADD_INTEGRATION_TEST(v3math v3math.cpp "${test_libs}") - LL_ADD_INTEGRATION_TEST(v4math v4math.cpp "${test_libs}") - LL_ADD_INTEGRATION_TEST(xform xform.cpp "${test_libs}") -endif (LL_TESTS) +# -*- cmake -*- + +project(llmath) + +include(00-Common) +include(LLCommon) + +include_directories( + ${LLCOMMON_INCLUDE_DIRS} + ) + +set(llmath_SOURCE_FILES + llbbox.cpp + llbboxlocal.cpp + llcamera.cpp + llcoordframe.cpp + llline.cpp + llmatrix3a.cpp + llmodularmath.cpp + llperlin.cpp + llquaternion.cpp + llrect.cpp + llsphere.cpp + llvector4a.cpp + llvolume.cpp + llvolumemgr.cpp + llvolumeoctree.cpp + llsdutil_math.cpp + m3math.cpp + m4math.cpp + raytrace.cpp + v2math.cpp + v3color.cpp + v3dmath.cpp + v3math.cpp + v4color.cpp + v4coloru.cpp + v4math.cpp + xform.cpp + ) + +set(llmath_HEADER_FILES + CMakeLists.txt + + camera.h + coordframe.h + llbbox.h + llbboxlocal.h + llcamera.h + llcoord.h + llcoordframe.h + llinterp.h + llline.h + llmath.h + llmatrix3a.h + llmatrix3a.inl + llmodularmath.h + lloctree.h + llperlin.h + llplane.h + llquantize.h + llquaternion.h + llquaternion2.h + llquaternion2.inl + llrect.h + llsimdmath.h + llsimdtypes.h + llsimdtypes.inl + llsphere.h + lltreenode.h + llvector4a.h + llvector4a.inl + llvector4logical.h + llv4math.h + llv4matrix3.h + llv4matrix4.h + llv4vector3.h + llvolume.h + llvolumemgr.h + llvolumeoctree.h + llsdutil_math.h + m3math.h + m4math.h + raytrace.h + v2math.h + v3color.h + v3dmath.h + v3math.h + v4color.h + v4coloru.h + v4math.h + xform.h + ) + +set_source_files_properties(${llmath_HEADER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +list(APPEND llmath_SOURCE_FILES ${llmath_HEADER_FILES}) + +add_library (llmath ${llmath_SOURCE_FILES}) + +# Add tests +if (LL_TESTS) + include(LLAddBuildTest) + # UNIT TESTS + SET(llmath_TEST_SOURCE_FILES + llbboxlocal.cpp + llmodularmath.cpp + llrect.cpp + v2math.cpp + v3color.cpp + v4color.cpp + v4coloru.cpp + ) + LL_ADD_PROJECT_UNIT_TESTS(llmath "${llmath_TEST_SOURCE_FILES}") + + # INTEGRATION TESTS + set(test_libs llmath llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) + # TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests. + LL_ADD_INTEGRATION_TEST(llbbox llbbox.cpp "${test_libs}") + LL_ADD_INTEGRATION_TEST(llquaternion llquaternion.cpp "${test_libs}") + LL_ADD_INTEGRATION_TEST(mathmisc "" "${test_libs}") + LL_ADD_INTEGRATION_TEST(m3math "" "${test_libs}") + LL_ADD_INTEGRATION_TEST(v3dmath v3dmath.cpp "${test_libs}") + LL_ADD_INTEGRATION_TEST(v3math v3math.cpp "${test_libs}") + LL_ADD_INTEGRATION_TEST(v4math v4math.cpp "${test_libs}") + LL_ADD_INTEGRATION_TEST(xform xform.cpp "${test_libs}") +endif (LL_TESTS) diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp index 6b56e4870e..beb5c48624 100644 --- a/indra/llmath/llcamera.cpp +++ b/indra/llmath/llcamera.cpp @@ -77,7 +77,7 @@ const LLCamera& LLCamera::operator=(const LLCamera& rhs) { memcpy(this, &rhs, sizeof(LLCamera)); alignPlanes(); - LLVector4a::memcpyNonAliased16((F32*) mAgentPlanes, (F32*) rhs.mAgentPlanes, 4*7); + LLVector4a::memcpyNonAliased16((F32*) mAgentPlanes, (F32*) rhs.mAgentPlanes, 4*7*sizeof(F32)); return *this; } diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h index c3c15e1374..742bbc4751 100644 --- a/indra/llmath/llmath.h +++ b/indra/llmath/llmath.h @@ -1,525 +1,509 @@ -/** - * @file llmath.h - * @brief Useful math constants and macros. - * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LLMATH_H -#define LLMATH_H - -#include -#include -#include -#include "lldefs.h" -//#include "llstl.h" // *TODO: Remove when LLString is gone -//#include "llstring.h" // *TODO: Remove when LLString is gone -// lltut.h uses is_approx_equal_fraction(). This was moved to its own header -// file in llcommon so we can use lltut.h for llcommon tests without making -// llcommon depend on llmath. -#include "is_approx_equal_fraction.h" - -// work around for Windows & older gcc non-standard function names. -#if LL_WINDOWS -#include -#define llisnan(val) _isnan(val) -#define llfinite(val) _finite(val) -#elif (LL_LINUX && __GNUC__ <= 2) -#define llisnan(val) isnan(val) -#define llfinite(val) isfinite(val) -#elif LL_SOLARIS -#define llisnan(val) isnan(val) -#define llfinite(val) (val <= std::numeric_limits::max()) -#else -#define llisnan(val) std::isnan(val) -#define llfinite(val) std::isfinite(val) -#endif - -// Single Precision Floating Point Routines -#ifndef sqrtf -#define sqrtf(x) ((F32)sqrt((F64)(x))) -#endif -#ifndef fsqrtf -#define fsqrtf(x) sqrtf(x) -#endif - -#ifndef cosf -#define cosf(x) ((F32)cos((F64)(x))) -#endif -#ifndef sinf -#define sinf(x) ((F32)sin((F64)(x))) -#endif -#ifndef tanf -#define tanf(x) ((F32)tan((F64)(x))) -#endif -#ifndef acosf -#define acosf(x) ((F32)acos((F64)(x))) -#endif - -#ifndef powf -#define powf(x,y) ((F32)pow((F64)(x),(F64)(y))) -#endif -#ifndef expf -#define expf(x) ((F32)exp((F64)(x))) -#endif - -const F32 GRAVITY = -9.8f; - -// mathematical constants -const F32 F_PI = 3.1415926535897932384626433832795f; -const F32 F_TWO_PI = 6.283185307179586476925286766559f; -const F32 F_PI_BY_TWO = 1.5707963267948966192313216916398f; -const F32 F_SQRT_TWO_PI = 2.506628274631000502415765284811f; -const F32 F_E = 2.71828182845904523536f; -const F32 F_SQRT2 = 1.4142135623730950488016887242097f; -const F32 F_SQRT3 = 1.73205080756888288657986402541f; -const F32 OO_SQRT2 = 0.7071067811865475244008443621049f; -const F32 DEG_TO_RAD = 0.017453292519943295769236907684886f; -const F32 RAD_TO_DEG = 57.295779513082320876798154814105f; -const F32 F_APPROXIMATELY_ZERO = 0.00001f; -const F32 F_LN2 = 0.69314718056f; -const F32 OO_LN2 = 1.4426950408889634073599246810019f; - -const F32 F_ALMOST_ZERO = 0.0001f; -const F32 F_ALMOST_ONE = 1.0f - F_ALMOST_ZERO; - -// BUG: Eliminate in favor of F_APPROXIMATELY_ZERO above? -const F32 FP_MAG_THRESHOLD = 0.0000001f; - -// TODO: Replace with logic like is_approx_equal -inline BOOL is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < F_APPROXIMATELY_ZERO); } - -// These functions work by interpreting sign+exp+mantissa as an unsigned -// integer. -// For example: -// x = 1 00000010 00000000000000000000000 -// y = 1 00000001 11111111111111111111111 -// -// interpreted as ints = -// x = 10000001000000000000000000000000 -// y = 10000000111111111111111111111111 -// which is clearly a different of 1 in the least significant bit -// Values with the same exponent can be trivially shown to work. -// -// WARNING: Denormals of opposite sign do not work -// x = 1 00000000 00000000000000000000001 -// y = 0 00000000 00000000000000000000001 -// Although these values differ by 2 in the LSB, the sign bit makes -// the int comparison fail. -// -// WARNING: NaNs can compare equal -// There is no special treatment of exceptional values like NaNs -// -// WARNING: Infinity is comparable with F32_MAX and negative -// infinity is comparable with F32_MIN - -inline BOOL is_approx_equal(F32 x, F32 y) -{ - const S32 COMPARE_MANTISSA_UP_TO_BIT = 0x02; - return (std::abs((S32) ((U32&)x - (U32&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); -} - -inline BOOL is_approx_equal(F64 x, F64 y) -{ - const S64 COMPARE_MANTISSA_UP_TO_BIT = 0x02; - return (std::abs((S32) ((U64&)x - (U64&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); -} - -inline S32 llabs(const S32 a) -{ - return S32(std::labs(a)); -} - -inline F32 llabs(const F32 a) -{ - return F32(std::fabs(a)); -} - -inline F64 llabs(const F64 a) -{ - return F64(std::fabs(a)); -} - -inline S32 lltrunc( F32 f ) -{ -#if LL_WINDOWS && !defined( __INTEL_COMPILER ) - // Avoids changing the floating point control word. - // Add or subtract 0.5 - epsilon and then round - const static U32 zpfp[] = { 0xBEFFFFFF, 0x3EFFFFFF }; - S32 result; - __asm { - fld f - mov eax, f - shr eax, 29 - and eax, 4 - fadd dword ptr [zpfp + eax] - fistp result - } - return result; -#else - return (S32)f; -#endif -} - -inline S32 lltrunc( F64 f ) -{ - return (S32)f; -} - -inline S32 llfloor( F32 f ) -{ -#if LL_WINDOWS && !defined( __INTEL_COMPILER ) - // Avoids changing the floating point control word. - // Accurate (unlike Stereopsis version) for all values between S32_MIN and S32_MAX and slightly faster than Stereopsis version. - // Add -(0.5 - epsilon) and then round - const U32 zpfp = 0xBEFFFFFF; - S32 result; - __asm { - fld f - fadd dword ptr [zpfp] - fistp result - } - return result; -#else - return (S32)floorf(f); -#endif -} - - -inline S32 llceil( F32 f ) -{ - // This could probably be optimized, but this works. - return (S32)ceil(f); -} - - -#ifndef BOGUS_ROUND -// Use this round. Does an arithmetic round (0.5 always rounds up) -inline S32 llround(const F32 val) -{ - return llfloor(val + 0.5f); -} - -#else // BOGUS_ROUND -// Old llround implementation - does banker's round (toward nearest even in the case of a 0.5. -// Not using this because we don't have a consistent implementation on both platforms, use -// llfloor(val + 0.5f), which is consistent on all platforms. -inline S32 llround(const F32 val) -{ - #if LL_WINDOWS - // Note: assumes that the floating point control word is set to rounding mode (the default) - S32 ret_val; - _asm fld val - _asm fistp ret_val; - return ret_val; - #elif LL_LINUX - // Note: assumes that the floating point control word is set - // to rounding mode (the default) - S32 ret_val; - __asm__ __volatile__( "flds %1 \n\t" - "fistpl %0 \n\t" - : "=m" (ret_val) - : "m" (val) ); - return ret_val; - #else - return llfloor(val + 0.5f); - #endif -} - -// A fast arithmentic round on intel, from Laurent de Soras http://ldesoras.free.fr -inline int round_int(double x) -{ - const float round_to_nearest = 0.5f; - int i; - __asm - { - fld x - fadd st, st (0) - fadd round_to_nearest - fistp i - sar i, 1 - } - return (i); -} -#endif // BOGUS_ROUND - -inline F32 llround( F32 val, F32 nearest ) -{ - return F32(floor(val * (1.0f / nearest) + 0.5f)) * nearest; -} - -inline F64 llround( F64 val, F64 nearest ) -{ - return F64(floor(val * (1.0 / nearest) + 0.5)) * nearest; -} - -// these provide minimum peak error -// -// avg error = -0.013049 -// peak error = -31.4 dB -// RMS error = -28.1 dB - -const F32 FAST_MAG_ALPHA = 0.960433870103f; -const F32 FAST_MAG_BETA = 0.397824734759f; - -// these provide minimum RMS error -// -// avg error = 0.000003 -// peak error = -32.6 dB -// RMS error = -25.7 dB -// -//const F32 FAST_MAG_ALPHA = 0.948059448969f; -//const F32 FAST_MAG_BETA = 0.392699081699f; - -inline F32 fastMagnitude(F32 a, F32 b) -{ - a = (a > 0) ? a : -a; - b = (b > 0) ? b : -b; - return(FAST_MAG_ALPHA * llmax(a,b) + FAST_MAG_BETA * llmin(a,b)); -} - - - -//////////////////// -// -// Fast F32/S32 conversions -// -// Culled from www.stereopsis.com/FPU.html - -const F64 LL_DOUBLE_TO_FIX_MAGIC = 68719476736.0*1.5; //2^36 * 1.5, (52-_shiftamt=36) uses limited precisicion to floor -const S32 LL_SHIFT_AMOUNT = 16; //16.16 fixed point representation, - -// Endian dependent code -#ifdef LL_LITTLE_ENDIAN - #define LL_EXP_INDEX 1 - #define LL_MAN_INDEX 0 -#else - #define LL_EXP_INDEX 0 - #define LL_MAN_INDEX 1 -#endif - -/* Deprecated: use llround(), lltrunc(), or llfloor() instead -// ================================================================================================ -// Real2Int -// ================================================================================================ -inline S32 F64toS32(F64 val) -{ - val = val + LL_DOUBLE_TO_FIX_MAGIC; - return ((S32*)&val)[LL_MAN_INDEX] >> LL_SHIFT_AMOUNT; -} - -// ================================================================================================ -// Real2Int -// ================================================================================================ -inline S32 F32toS32(F32 val) -{ - return F64toS32 ((F64)val); -} -*/ - -//////////////////////////////////////////////// -// -// Fast exp and log -// - -// Implementation of fast exp() approximation (from a paper by Nicol N. Schraudolph -// http://www.inf.ethz.ch/~schraudo/pubs/exp.pdf -static union -{ - double d; - struct - { -#ifdef LL_LITTLE_ENDIAN - S32 j, i; -#else - S32 i, j; -#endif - } n; -} LLECO; // not sure what the name means - -#define LL_EXP_A (1048576 * OO_LN2) // use 1512775 for integer -#define LL_EXP_C (60801) // this value of C good for -4 < y < 4 - -#define LL_FAST_EXP(y) (LLECO.n.i = llround(F32(LL_EXP_A*(y))) + (1072693248 - LL_EXP_C), LLECO.d) - - - -inline F32 llfastpow(const F32 x, const F32 y) -{ - return (F32)(LL_FAST_EXP(y * log(x))); -} - - -inline F32 snap_to_sig_figs(F32 foo, S32 sig_figs) -{ - // compute the power of ten - F32 bar = 1.f; - for (S32 i = 0; i < sig_figs; i++) - { - bar *= 10.f; - } - - foo = (F32)llround(foo * bar); - - // shift back - foo /= bar; - return foo; -} - -inline F32 lerp(F32 a, F32 b, F32 u) -{ - return a + ((b - a) * u); -} - -inline F32 lerp2d(F32 x00, F32 x01, F32 x10, F32 x11, F32 u, F32 v) -{ - F32 a = x00 + (x01-x00)*u; - F32 b = x10 + (x11-x10)*u; - F32 r = a + (b-a)*v; - return r; -} - -inline F32 ramp(F32 x, F32 a, F32 b) -{ - return (a == b) ? 0.0f : ((a - x) / (a - b)); -} - -inline F32 rescale(F32 x, F32 x1, F32 x2, F32 y1, F32 y2) -{ - return lerp(y1, y2, ramp(x, x1, x2)); -} - -inline F32 clamp_rescale(F32 x, F32 x1, F32 x2, F32 y1, F32 y2) -{ - if (y1 < y2) - { - return llclamp(rescale(x,x1,x2,y1,y2),y1,y2); - } - else - { - return llclamp(rescale(x,x1,x2,y1,y2),y2,y1); - } -} - - -inline F32 cubic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 ) -{ - if (x <= x0) - return s0; - - if (x >= x1) - return s1; - - F32 f = (x - x0) / (x1 - x0); - - return s0 + (s1 - s0) * (f * f) * (3.0f - 2.0f * f); -} - -inline F32 cubic_step( F32 x ) -{ - x = llclampf(x); - - return (x * x) * (3.0f - 2.0f * x); -} - -inline F32 quadratic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 ) -{ - if (x <= x0) - return s0; - - if (x >= x1) - return s1; - - F32 f = (x - x0) / (x1 - x0); - F32 f_squared = f * f; - - return (s0 * (1.f - f_squared)) + ((s1 - s0) * f_squared); -} - -inline F32 llsimple_angle(F32 angle) -{ - while(angle <= -F_PI) - angle += F_TWO_PI; - while(angle > F_PI) - angle -= F_TWO_PI; - return angle; -} - -//SDK - Renamed this to get_lower_power_two, since this is what this actually does. -inline U32 get_lower_power_two(U32 val, U32 max_power_two) -{ - if(!max_power_two) - { - max_power_two = 1 << 31 ; - } - if(max_power_two & (max_power_two - 1)) - { - return 0 ; - } - - for(; val < max_power_two ; max_power_two >>= 1) ; - - return max_power_two ; -} - -// calculate next highest power of two, limited by max_power_two -// This is taken from a brilliant little code snipped on http://acius2.blogspot.com/2007/11/calculating-next-power-of-2.html -// Basically we convert the binary to a solid string of 1's with the same -// number of digits, then add one. We subtract 1 initially to handle -// the case where the number passed in is actually a power of two. -// WARNING: this only works with 32 bit ints. -inline U32 get_next_power_two(U32 val, U32 max_power_two) -{ - if(!max_power_two) - { - max_power_two = 1 << 31 ; - } - - if(val >= max_power_two) - { - return max_power_two; - } - - val--; - val = (val >> 1) | val; - val = (val >> 2) | val; - val = (val >> 4) | val; - val = (val >> 8) | val; - val = (val >> 16) | val; - val++; - - return val; -} - -//get the gaussian value given the linear distance from axis x and guassian value o -inline F32 llgaussian(F32 x, F32 o) -{ - return 1.f/(F_SQRT_TWO_PI*o)*powf(F_E, -(x*x)/(2*o*o)); -} - -#endif +/** + * @file llmath.h + * @brief Useful math constants and macros. + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LLMATH_H +#define LLMATH_H + +#include +#include +#include "lldefs.h" +//#include "llstl.h" // *TODO: Remove when LLString is gone +//#include "llstring.h" // *TODO: Remove when LLString is gone +// lltut.h uses is_approx_equal_fraction(). This was moved to its own header +// file in llcommon so we can use lltut.h for llcommon tests without making +// llcommon depend on llmath. +#include "is_approx_equal_fraction.h" + +// work around for Windows & older gcc non-standard function names. +#if LL_WINDOWS +#include +#define llisnan(val) _isnan(val) +#define llfinite(val) _finite(val) +#elif (LL_LINUX && __GNUC__ <= 2) +#define llisnan(val) isnan(val) +#define llfinite(val) isfinite(val) +#elif LL_SOLARIS +#define llisnan(val) isnan(val) +#define llfinite(val) (val <= std::numeric_limits::max()) +#else +#define llisnan(val) std::isnan(val) +#define llfinite(val) std::isfinite(val) +#endif + +// Single Precision Floating Point Routines +// (There used to be more defined here, but they appeared to be redundant and +// were breaking some other includes. Removed by Falcon, reviewed by Andrew, 11/25/09) +/*#ifndef tanf +#define tanf(x) ((F32)tan((F64)(x))) +#endif*/ + +const F32 GRAVITY = -9.8f; + +// mathematical constants +const F32 F_PI = 3.1415926535897932384626433832795f; +const F32 F_TWO_PI = 6.283185307179586476925286766559f; +const F32 F_PI_BY_TWO = 1.5707963267948966192313216916398f; +const F32 F_SQRT_TWO_PI = 2.506628274631000502415765284811f; +const F32 F_E = 2.71828182845904523536f; +const F32 F_SQRT2 = 1.4142135623730950488016887242097f; +const F32 F_SQRT3 = 1.73205080756888288657986402541f; +const F32 OO_SQRT2 = 0.7071067811865475244008443621049f; +const F32 DEG_TO_RAD = 0.017453292519943295769236907684886f; +const F32 RAD_TO_DEG = 57.295779513082320876798154814105f; +const F32 F_APPROXIMATELY_ZERO = 0.00001f; +const F32 F_LN2 = 0.69314718056f; +const F32 OO_LN2 = 1.4426950408889634073599246810019f; + +const F32 F_ALMOST_ZERO = 0.0001f; +const F32 F_ALMOST_ONE = 1.0f - F_ALMOST_ZERO; + +// BUG: Eliminate in favor of F_APPROXIMATELY_ZERO above? +const F32 FP_MAG_THRESHOLD = 0.0000001f; + +// TODO: Replace with logic like is_approx_equal +inline BOOL is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < F_APPROXIMATELY_ZERO); } + +// These functions work by interpreting sign+exp+mantissa as an unsigned +// integer. +// For example: +// x = 1 00000010 00000000000000000000000 +// y = 1 00000001 11111111111111111111111 +// +// interpreted as ints = +// x = 10000001000000000000000000000000 +// y = 10000000111111111111111111111111 +// which is clearly a different of 1 in the least significant bit +// Values with the same exponent can be trivially shown to work. +// +// WARNING: Denormals of opposite sign do not work +// x = 1 00000000 00000000000000000000001 +// y = 0 00000000 00000000000000000000001 +// Although these values differ by 2 in the LSB, the sign bit makes +// the int comparison fail. +// +// WARNING: NaNs can compare equal +// There is no special treatment of exceptional values like NaNs +// +// WARNING: Infinity is comparable with F32_MAX and negative +// infinity is comparable with F32_MIN + +inline BOOL is_approx_equal(F32 x, F32 y) +{ + const S32 COMPARE_MANTISSA_UP_TO_BIT = 0x02; + return (std::abs((S32) ((U32&)x - (U32&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); +} + +inline BOOL is_approx_equal(F64 x, F64 y) +{ + const S64 COMPARE_MANTISSA_UP_TO_BIT = 0x02; + return (std::abs((S32) ((U64&)x - (U64&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); +} + +inline S32 llabs(const S32 a) +{ + return S32(std::labs(a)); +} + +inline F32 llabs(const F32 a) +{ + return F32(std::fabs(a)); +} + +inline F64 llabs(const F64 a) +{ + return F64(std::fabs(a)); +} + +inline S32 lltrunc( F32 f ) +{ +#if LL_WINDOWS && !defined( __INTEL_COMPILER ) + // Avoids changing the floating point control word. + // Add or subtract 0.5 - epsilon and then round + const static U32 zpfp[] = { 0xBEFFFFFF, 0x3EFFFFFF }; + S32 result; + __asm { + fld f + mov eax, f + shr eax, 29 + and eax, 4 + fadd dword ptr [zpfp + eax] + fistp result + } + return result; +#else + return (S32)f; +#endif +} + +inline S32 lltrunc( F64 f ) +{ + return (S32)f; +} + +inline S32 llfloor( F32 f ) +{ +#if LL_WINDOWS && !defined( __INTEL_COMPILER ) + // Avoids changing the floating point control word. + // Accurate (unlike Stereopsis version) for all values between S32_MIN and S32_MAX and slightly faster than Stereopsis version. + // Add -(0.5 - epsilon) and then round + const U32 zpfp = 0xBEFFFFFF; + S32 result; + __asm { + fld f + fadd dword ptr [zpfp] + fistp result + } + return result; +#else + return (S32)floor(f); +#endif +} + + +inline S32 llceil( F32 f ) +{ + // This could probably be optimized, but this works. + return (S32)ceil(f); +} + + +#ifndef BOGUS_ROUND +// Use this round. Does an arithmetic round (0.5 always rounds up) +inline S32 llround(const F32 val) +{ + return llfloor(val + 0.5f); +} + +#else // BOGUS_ROUND +// Old llround implementation - does banker's round (toward nearest even in the case of a 0.5. +// Not using this because we don't have a consistent implementation on both platforms, use +// llfloor(val + 0.5f), which is consistent on all platforms. +inline S32 llround(const F32 val) +{ + #if LL_WINDOWS + // Note: assumes that the floating point control word is set to rounding mode (the default) + S32 ret_val; + _asm fld val + _asm fistp ret_val; + return ret_val; + #elif LL_LINUX + // Note: assumes that the floating point control word is set + // to rounding mode (the default) + S32 ret_val; + __asm__ __volatile__( "flds %1 \n\t" + "fistpl %0 \n\t" + : "=m" (ret_val) + : "m" (val) ); + return ret_val; + #else + return llfloor(val + 0.5f); + #endif +} + +// A fast arithmentic round on intel, from Laurent de Soras http://ldesoras.free.fr +inline int round_int(double x) +{ + const float round_to_nearest = 0.5f; + int i; + __asm + { + fld x + fadd st, st (0) + fadd round_to_nearest + fistp i + sar i, 1 + } + return (i); +} +#endif // BOGUS_ROUND + +inline F32 llround( F32 val, F32 nearest ) +{ + return F32(floor(val * (1.0f / nearest) + 0.5f)) * nearest; +} + +inline F64 llround( F64 val, F64 nearest ) +{ + return F64(floor(val * (1.0 / nearest) + 0.5)) * nearest; +} + +// these provide minimum peak error +// +// avg error = -0.013049 +// peak error = -31.4 dB +// RMS error = -28.1 dB + +const F32 FAST_MAG_ALPHA = 0.960433870103f; +const F32 FAST_MAG_BETA = 0.397824734759f; + +// these provide minimum RMS error +// +// avg error = 0.000003 +// peak error = -32.6 dB +// RMS error = -25.7 dB +// +//const F32 FAST_MAG_ALPHA = 0.948059448969f; +//const F32 FAST_MAG_BETA = 0.392699081699f; + +inline F32 fastMagnitude(F32 a, F32 b) +{ + a = (a > 0) ? a : -a; + b = (b > 0) ? b : -b; + return(FAST_MAG_ALPHA * llmax(a,b) + FAST_MAG_BETA * llmin(a,b)); +} + + + +//////////////////// +// +// Fast F32/S32 conversions +// +// Culled from www.stereopsis.com/FPU.html + +const F64 LL_DOUBLE_TO_FIX_MAGIC = 68719476736.0*1.5; //2^36 * 1.5, (52-_shiftamt=36) uses limited precisicion to floor +const S32 LL_SHIFT_AMOUNT = 16; //16.16 fixed point representation, + +// Endian dependent code +#ifdef LL_LITTLE_ENDIAN + #define LL_EXP_INDEX 1 + #define LL_MAN_INDEX 0 +#else + #define LL_EXP_INDEX 0 + #define LL_MAN_INDEX 1 +#endif + +/* Deprecated: use llround(), lltrunc(), or llfloor() instead +// ================================================================================================ +// Real2Int +// ================================================================================================ +inline S32 F64toS32(F64 val) +{ + val = val + LL_DOUBLE_TO_FIX_MAGIC; + return ((S32*)&val)[LL_MAN_INDEX] >> LL_SHIFT_AMOUNT; +} + +// ================================================================================================ +// Real2Int +// ================================================================================================ +inline S32 F32toS32(F32 val) +{ + return F64toS32 ((F64)val); +} +*/ + +//////////////////////////////////////////////// +// +// Fast exp and log +// + +// Implementation of fast exp() approximation (from a paper by Nicol N. Schraudolph +// http://www.inf.ethz.ch/~schraudo/pubs/exp.pdf +static union +{ + double d; + struct + { +#ifdef LL_LITTLE_ENDIAN + S32 j, i; +#else + S32 i, j; +#endif + } n; +} LLECO; // not sure what the name means + +#define LL_EXP_A (1048576 * OO_LN2) // use 1512775 for integer +#define LL_EXP_C (60801) // this value of C good for -4 < y < 4 + +#define LL_FAST_EXP(y) (LLECO.n.i = llround(F32(LL_EXP_A*(y))) + (1072693248 - LL_EXP_C), LLECO.d) + + + +inline F32 llfastpow(const F32 x, const F32 y) +{ + return (F32)(LL_FAST_EXP(y * log(x))); +} + + +inline F32 snap_to_sig_figs(F32 foo, S32 sig_figs) +{ + // compute the power of ten + F32 bar = 1.f; + for (S32 i = 0; i < sig_figs; i++) + { + bar *= 10.f; + } + + //F32 new_foo = (F32)llround(foo * bar); + // the llround() implementation sucks. Don't us it. + + F32 sign = (foo > 0.f) ? 1.f : -1.f; + F32 new_foo = F32( S64(foo * bar + sign * 0.5f)); + new_foo /= bar; + + return new_foo; +} + +inline F32 lerp(F32 a, F32 b, F32 u) +{ + return a + ((b - a) * u); +} + +inline F32 lerp2d(F32 x00, F32 x01, F32 x10, F32 x11, F32 u, F32 v) +{ + F32 a = x00 + (x01-x00)*u; + F32 b = x10 + (x11-x10)*u; + F32 r = a + (b-a)*v; + return r; +} + +inline F32 ramp(F32 x, F32 a, F32 b) +{ + return (a == b) ? 0.0f : ((a - x) / (a - b)); +} + +inline F32 rescale(F32 x, F32 x1, F32 x2, F32 y1, F32 y2) +{ + return lerp(y1, y2, ramp(x, x1, x2)); +} + +inline F32 clamp_rescale(F32 x, F32 x1, F32 x2, F32 y1, F32 y2) +{ + if (y1 < y2) + { + return llclamp(rescale(x,x1,x2,y1,y2),y1,y2); + } + else + { + return llclamp(rescale(x,x1,x2,y1,y2),y2,y1); + } +} + + +inline F32 cubic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 ) +{ + if (x <= x0) + return s0; + + if (x >= x1) + return s1; + + F32 f = (x - x0) / (x1 - x0); + + return s0 + (s1 - s0) * (f * f) * (3.0f - 2.0f * f); +} + +inline F32 cubic_step( F32 x ) +{ + x = llclampf(x); + + return (x * x) * (3.0f - 2.0f * x); +} + +inline F32 quadratic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 ) +{ + if (x <= x0) + return s0; + + if (x >= x1) + return s1; + + F32 f = (x - x0) / (x1 - x0); + F32 f_squared = f * f; + + return (s0 * (1.f - f_squared)) + ((s1 - s0) * f_squared); +} + +inline F32 llsimple_angle(F32 angle) +{ + while(angle <= -F_PI) + angle += F_TWO_PI; + while(angle > F_PI) + angle -= F_TWO_PI; + return angle; +} + +//SDK - Renamed this to get_lower_power_two, since this is what this actually does. +inline U32 get_lower_power_two(U32 val, U32 max_power_two) +{ + if(!max_power_two) + { + max_power_two = 1 << 31 ; + } + if(max_power_two & (max_power_two - 1)) + { + return 0 ; + } + + for(; val < max_power_two ; max_power_two >>= 1) ; + + return max_power_two ; +} + +// calculate next highest power of two, limited by max_power_two +// This is taken from a brilliant little code snipped on http://acius2.blogspot.com/2007/11/calculating-next-power-of-2.html +// Basically we convert the binary to a solid string of 1's with the same +// number of digits, then add one. We subtract 1 initially to handle +// the case where the number passed in is actually a power of two. +// WARNING: this only works with 32 bit ints. +inline U32 get_next_power_two(U32 val, U32 max_power_two) +{ + if(!max_power_two) + { + max_power_two = 1 << 31 ; + } + + if(val >= max_power_two) + { + return max_power_two; + } + + val--; + val = (val >> 1) | val; + val = (val >> 2) | val; + val = (val >> 4) | val; + val = (val >> 8) | val; + val = (val >> 16) | val; + val++; + + return val; +} + +//get the gaussian value given the linear distance from axis x and guassian value o +inline F32 llgaussian(F32 x, F32 o) +{ + return 1.f/(F_SQRT_TWO_PI*o)*powf(F_E, -(x*x)/(2*o*o)); +} + +// Include simd math header +#include "llsimdmath.h" + +#endif diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index 59828ae565..432e9fbcd8 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -142,7 +142,7 @@ public: S32 getOctant(const LLVector4a& pos) const //get the octant pos is in { - return pos.greaterThan4(mD[CENTER]).getComparisonMask() & 0x7; + return pos.greaterThan(mD[CENTER]).getGatheredBits() & 0x7; } inline bool isInside(const LLVector4a& pos, const F32& rad) const @@ -157,13 +157,13 @@ public: bool isInside(const LLVector4a& pos) const { - S32 gt = pos.greaterThan4(mD[MAX]).getComparisonMask() & 0x7; + S32 gt = pos.greaterThan(mD[MAX]).getGatheredBits() & 0x7; if (gt) { return false; } - S32 lt = pos.lessEqual4(mD[MIN]).getComparisonMask() & 0x7; + S32 lt = pos.lessEqual(mD[MIN]).getGatheredBits() & 0x7; if (lt) { return false; @@ -206,13 +206,13 @@ public: { const LLVector4a& pos = data->getPositionGroup(); - LLVector4a gt = pos.greaterThan4(center); + LLVector4a gt = pos.greaterThan(center); LLVector4a up; - up.mQ = _mm_and_ps(size.mQ, gt.mQ); + up = _mm_and_ps(size, gt); LLVector4a down; - down.mQ = _mm_andnot_ps(gt.mQ, size.mQ); + down = _mm_andnot_ps(gt, size); center.add(up); center.sub(down); @@ -326,9 +326,8 @@ public: LLVector4a val; val.setSub(center, getCenter()); val.setAbs(val); - LLVector4a app_zero; - app_zero.mQ = F_APPROXIMATELY_ZERO_4A; - S32 lt = val.lessThan4(app_zero).getComparisonMask() & 0x7; + + S32 lt = val.lessThan(LLVector4a::getEpsilon()).getGatheredBits() & 0x7; if( lt == 0x7 ) { @@ -642,7 +641,7 @@ public: LLVector4a val; val.setSub(v, BaseType::mD[BaseType::CENTER]); val.setAbs(val); - S32 lt = val.lessThan4(MAX_MAG).getComparisonMask() & 0x7; + S32 lt = val.lessThan(MAX_MAG).getGatheredBits() & 0x7; if (lt != 0x7) { diff --git a/indra/llmath/llquantize.h b/indra/llmath/llquantize.h index 2192427f07..000d8a060f 100644 --- a/indra/llmath/llquantize.h +++ b/indra/llmath/llquantize.h @@ -1,152 +1,158 @@ -/** - * @file llquantize.h - * @brief useful routines for quantizing floats to various length ints - * and back out again - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LLQUANTIZE_H -#define LL_LLQUANTIZE_H - -const U16 U16MAX = 65535; -const F32 OOU16MAX = 1.f/(F32)(U16MAX); - -const U8 U8MAX = 255; -const F32 OOU8MAX = 1.f/(F32)(U8MAX); - -const U8 FIRSTVALIDCHAR = 54; -const U8 MAXSTRINGVAL = U8MAX - FIRSTVALIDCHAR; //we don't allow newline or null - - -inline U16 F32_to_U16_ROUND(F32 val, F32 lower, F32 upper) -{ - val = llclamp(val, lower, upper); - // make sure that the value is positive and normalized to <0, 1> - val -= lower; - val /= (upper - lower); - - // round the value. Sreturn the U16 - return (U16)(llround(val*U16MAX)); -} - - -inline U16 F32_to_U16(F32 val, F32 lower, F32 upper) -{ - val = llclamp(val, lower, upper); - // make sure that the value is positive and normalized to <0, 1> - val -= lower; - val /= (upper - lower); - - // return the U16 - return (U16)(llfloor(val*U16MAX)); -} - -inline F32 U16_to_F32(U16 ival, F32 lower, F32 upper) -{ - F32 val = ival*OOU16MAX; - F32 delta = (upper - lower); - val *= delta; - val += lower; - - F32 max_error = delta*OOU16MAX; - - // make sure that zero's come through as zero - if (fabsf(val) < max_error) - val = 0.f; - - return val; -} - - -inline U8 F32_to_U8_ROUND(F32 val, F32 lower, F32 upper) -{ - val = llclamp(val, lower, upper); - // make sure that the value is positive and normalized to <0, 1> - val -= lower; - val /= (upper - lower); - - // return the rounded U8 - return (U8)(llround(val*U8MAX)); -} - - -inline U8 F32_to_U8(F32 val, F32 lower, F32 upper) -{ - val = llclamp(val, lower, upper); - // make sure that the value is positive and normalized to <0, 1> - val -= lower; - val /= (upper - lower); - - // return the U8 - return (U8)(llfloor(val*U8MAX)); -} - -inline F32 U8_to_F32(U8 ival, F32 lower, F32 upper) -{ - F32 val = ival*OOU8MAX; - F32 delta = (upper - lower); - val *= delta; - val += lower; - - F32 max_error = delta*OOU8MAX; - - // make sure that zero's come through as zero - if (fabsf(val) < max_error) - val = 0.f; - - return val; -} - -inline U8 F32_TO_STRING(F32 val, F32 lower, F32 upper) -{ - val = llclamp(val, lower, upper); //[lower, upper] - // make sure that the value is positive and normalized to <0, 1> - val -= lower; //[0, upper-lower] - val /= (upper - lower); //[0,1] - val = val * MAXSTRINGVAL; //[0, MAXSTRINGVAL] - val = floor(val + 0.5f); //[0, MAXSTRINGVAL] - - U8 stringVal = (U8)(val) + FIRSTVALIDCHAR; //[FIRSTVALIDCHAR, MAXSTRINGVAL + FIRSTVALIDCHAR] - return stringVal; -} - -inline F32 STRING_TO_F32(U8 ival, F32 lower, F32 upper) -{ - // remove empty space left for NULL, newline, etc. - ival -= FIRSTVALIDCHAR; //[0, MAXSTRINGVAL] - - F32 val = (F32)ival * (1.f / (F32)MAXSTRINGVAL); //[0, 1] - F32 delta = (upper - lower); - val *= delta; //[0, upper - lower] - val += lower; //[lower, upper] - - return val; -} - -#endif +/** + * @file llquantize.h + * @brief useful routines for quantizing floats to various length ints + * and back out again + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLQUANTIZE_H +#define LL_LLQUANTIZE_H + +const U16 U16MAX = 65535; +LL_ALIGN_16( const F32 F_U16MAX_4A[4] ) = { 65535.f, 65535.f, 65535.f, 65535.f }; + +const F32 OOU16MAX = 1.f/(F32)(U16MAX); +LL_ALIGN_16( const F32 F_OOU16MAX_4A[4] ) = { OOU16MAX, OOU16MAX, OOU16MAX, OOU16MAX }; + +const U8 U8MAX = 255; +LL_ALIGN_16( const F32 F_U8MAX_4A[4] ) = { 255.f, 255.f, 255.f, 255.f }; + +const F32 OOU8MAX = 1.f/(F32)(U8MAX); +LL_ALIGN_16( const F32 F_OOU8MAX_4A[4] ) = { OOU8MAX, OOU8MAX, OOU8MAX, OOU8MAX }; + +const U8 FIRSTVALIDCHAR = 54; +const U8 MAXSTRINGVAL = U8MAX - FIRSTVALIDCHAR; //we don't allow newline or null + + +inline U16 F32_to_U16_ROUND(F32 val, F32 lower, F32 upper) +{ + val = llclamp(val, lower, upper); + // make sure that the value is positive and normalized to <0, 1> + val -= lower; + val /= (upper - lower); + + // round the value. Sreturn the U16 + return (U16)(llround(val*U16MAX)); +} + + +inline U16 F32_to_U16(F32 val, F32 lower, F32 upper) +{ + val = llclamp(val, lower, upper); + // make sure that the value is positive and normalized to <0, 1> + val -= lower; + val /= (upper - lower); + + // return the U16 + return (U16)(llfloor(val*U16MAX)); +} + +inline F32 U16_to_F32(U16 ival, F32 lower, F32 upper) +{ + F32 val = ival*OOU16MAX; + F32 delta = (upper - lower); + val *= delta; + val += lower; + + F32 max_error = delta*OOU16MAX; + + // make sure that zero's come through as zero + if (fabsf(val) < max_error) + val = 0.f; + + return val; +} + + +inline U8 F32_to_U8_ROUND(F32 val, F32 lower, F32 upper) +{ + val = llclamp(val, lower, upper); + // make sure that the value is positive and normalized to <0, 1> + val -= lower; + val /= (upper - lower); + + // return the rounded U8 + return (U8)(llround(val*U8MAX)); +} + + +inline U8 F32_to_U8(F32 val, F32 lower, F32 upper) +{ + val = llclamp(val, lower, upper); + // make sure that the value is positive and normalized to <0, 1> + val -= lower; + val /= (upper - lower); + + // return the U8 + return (U8)(llfloor(val*U8MAX)); +} + +inline F32 U8_to_F32(U8 ival, F32 lower, F32 upper) +{ + F32 val = ival*OOU8MAX; + F32 delta = (upper - lower); + val *= delta; + val += lower; + + F32 max_error = delta*OOU8MAX; + + // make sure that zero's come through as zero + if (fabsf(val) < max_error) + val = 0.f; + + return val; +} + +inline U8 F32_TO_STRING(F32 val, F32 lower, F32 upper) +{ + val = llclamp(val, lower, upper); //[lower, upper] + // make sure that the value is positive and normalized to <0, 1> + val -= lower; //[0, upper-lower] + val /= (upper - lower); //[0,1] + val = val * MAXSTRINGVAL; //[0, MAXSTRINGVAL] + val = floor(val + 0.5f); //[0, MAXSTRINGVAL] + + U8 stringVal = (U8)(val) + FIRSTVALIDCHAR; //[FIRSTVALIDCHAR, MAXSTRINGVAL + FIRSTVALIDCHAR] + return stringVal; +} + +inline F32 STRING_TO_F32(U8 ival, F32 lower, F32 upper) +{ + // remove empty space left for NULL, newline, etc. + ival -= FIRSTVALIDCHAR; //[0, MAXSTRINGVAL] + + F32 val = (F32)ival * (1.f / (F32)MAXSTRINGVAL); //[0, 1] + F32 delta = (upper - lower); + val *= delta; //[0, upper - lower] + val += lower; //[lower, upper] + + return val; +} + +#endif diff --git a/indra/llmath/llquaternion.cpp b/indra/llmath/llquaternion.cpp index fdcc19d657..efdc10e2c6 100644 --- a/indra/llmath/llquaternion.cpp +++ b/indra/llmath/llquaternion.cpp @@ -1,960 +1,961 @@ -/** - * @file llquaternion.cpp - * @brief LLQuaternion class implementation. - * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llquaternion.h" - -#include "llmath.h" // for F_PI -//#include "vmath.h" -#include "v3math.h" -#include "v3dmath.h" -#include "v4math.h" -#include "m4math.h" -#include "m3math.h" -#include "llquantize.h" - -// WARNING: Don't use this for global const definitions! using this -// at the top of a *.cpp file might not give you what you think. -const LLQuaternion LLQuaternion::DEFAULT; - -// Constructors - -LLQuaternion::LLQuaternion(const LLMatrix4 &mat) -{ - *this = mat.quaternion(); - normalize(); -} - -LLQuaternion::LLQuaternion(const LLMatrix3 &mat) -{ - *this = mat.quaternion(); - normalize(); -} - -LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec) -{ - LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); - v.normalize(); - - F32 c, s; - c = cosf(angle*0.5f); - s = sinf(angle*0.5f); - - mQ[VX] = v.mV[VX] * s; - mQ[VY] = v.mV[VY] * s; - mQ[VZ] = v.mV[VZ] * s; - mQ[VW] = c; - normalize(); -} - -LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec) -{ - LLVector3 v(vec); - v.normalize(); - - F32 c, s; - c = cosf(angle*0.5f); - s = sinf(angle*0.5f); - - mQ[VX] = v.mV[VX] * s; - mQ[VY] = v.mV[VY] * s; - mQ[VZ] = v.mV[VZ] * s; - mQ[VW] = c; - normalize(); -} - -LLQuaternion::LLQuaternion(const LLVector3 &x_axis, - const LLVector3 &y_axis, - const LLVector3 &z_axis) -{ - LLMatrix3 mat; - mat.setRows(x_axis, y_axis, z_axis); - *this = mat.quaternion(); - normalize(); -} - -// Quatizations -void LLQuaternion::quantize16(F32 lower, F32 upper) -{ - F32 x = mQ[VX]; - F32 y = mQ[VY]; - F32 z = mQ[VZ]; - F32 s = mQ[VS]; - - x = U16_to_F32(F32_to_U16_ROUND(x, lower, upper), lower, upper); - y = U16_to_F32(F32_to_U16_ROUND(y, lower, upper), lower, upper); - z = U16_to_F32(F32_to_U16_ROUND(z, lower, upper), lower, upper); - s = U16_to_F32(F32_to_U16_ROUND(s, lower, upper), lower, upper); - - mQ[VX] = x; - mQ[VY] = y; - mQ[VZ] = z; - mQ[VS] = s; - - normalize(); -} - -void LLQuaternion::quantize8(F32 lower, F32 upper) -{ - mQ[VX] = U8_to_F32(F32_to_U8_ROUND(mQ[VX], lower, upper), lower, upper); - mQ[VY] = U8_to_F32(F32_to_U8_ROUND(mQ[VY], lower, upper), lower, upper); - mQ[VZ] = U8_to_F32(F32_to_U8_ROUND(mQ[VZ], lower, upper), lower, upper); - mQ[VS] = U8_to_F32(F32_to_U8_ROUND(mQ[VS], lower, upper), lower, upper); - - normalize(); -} - -// LLVector3 Magnitude and Normalization Functions - - -// Set LLQuaternion routines - -const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, F32 x, F32 y, F32 z) -{ - LLVector3 vec(x, y, z); - vec.normalize(); - - angle *= 0.5f; - F32 c, s; - c = cosf(angle); - s = sinf(angle); - - mQ[VX] = vec.mV[VX]*s; - mQ[VY] = vec.mV[VY]*s; - mQ[VZ] = vec.mV[VZ]*s; - mQ[VW] = c; - - normalize(); - return (*this); -} - -const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, const LLVector3 &vec) -{ - LLVector3 v(vec); - v.normalize(); - - angle *= 0.5f; - F32 c, s; - c = cosf(angle); - s = sinf(angle); - - mQ[VX] = v.mV[VX]*s; - mQ[VY] = v.mV[VY]*s; - mQ[VZ] = v.mV[VZ]*s; - mQ[VW] = c; - - normalize(); - return (*this); -} - -const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, const LLVector4 &vec) -{ - LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); - v.normalize(); - - F32 c, s; - c = cosf(angle*0.5f); - s = sinf(angle*0.5f); - - mQ[VX] = v.mV[VX]*s; - mQ[VY] = v.mV[VY]*s; - mQ[VZ] = v.mV[VZ]*s; - mQ[VW] = c; - - normalize(); - return (*this); -} - -const LLQuaternion& LLQuaternion::setEulerAngles(F32 roll, F32 pitch, F32 yaw) -{ - LLMatrix3 rot_mat(roll, pitch, yaw); - rot_mat.orthogonalize(); - *this = rot_mat.quaternion(); - - normalize(); - return (*this); -} - -// deprecated -const LLQuaternion& LLQuaternion::set(const LLMatrix3 &mat) -{ - *this = mat.quaternion(); - normalize(); - return (*this); -} - -// deprecated -const LLQuaternion& LLQuaternion::set(const LLMatrix4 &mat) -{ - *this = mat.quaternion(); - normalize(); - return (*this); -} - -// deprecated -const LLQuaternion& LLQuaternion::setQuat(F32 angle, F32 x, F32 y, F32 z) -{ - LLVector3 vec(x, y, z); - vec.normalize(); - - angle *= 0.5f; - F32 c, s; - c = cosf(angle); - s = sinf(angle); - - mQ[VX] = vec.mV[VX]*s; - mQ[VY] = vec.mV[VY]*s; - mQ[VZ] = vec.mV[VZ]*s; - mQ[VW] = c; - - normalize(); - return (*this); -} - -// deprecated -const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector3 &vec) -{ - LLVector3 v(vec); - v.normalize(); - - angle *= 0.5f; - F32 c, s; - c = cosf(angle); - s = sinf(angle); - - mQ[VX] = v.mV[VX]*s; - mQ[VY] = v.mV[VY]*s; - mQ[VZ] = v.mV[VZ]*s; - mQ[VW] = c; - - normalize(); - return (*this); -} - -const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector4 &vec) -{ - LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); - v.normalize(); - - F32 c, s; - c = cosf(angle*0.5f); - s = sinf(angle*0.5f); - - mQ[VX] = v.mV[VX]*s; - mQ[VY] = v.mV[VY]*s; - mQ[VZ] = v.mV[VZ]*s; - mQ[VW] = c; - - normalize(); - return (*this); -} - -const LLQuaternion& LLQuaternion::setQuat(F32 roll, F32 pitch, F32 yaw) -{ - LLMatrix3 rot_mat(roll, pitch, yaw); - rot_mat.orthogonalize(); - *this = rot_mat.quaternion(); - - normalize(); - return (*this); -} - -const LLQuaternion& LLQuaternion::setQuat(const LLMatrix3 &mat) -{ - *this = mat.quaternion(); - normalize(); - return (*this); -} - -const LLQuaternion& LLQuaternion::setQuat(const LLMatrix4 &mat) -{ - *this = mat.quaternion(); - normalize(); - return (*this); -//#if 1 -// // NOTE: LLQuaternion's are actually inverted with respect to -// // the matrices, so this code also assumes inverted quaternions -// // (-x, -y, -z, w). The result is that roll,pitch,yaw are applied -// // in reverse order (yaw,pitch,roll). -// F64 cosX = cos(roll); -// F64 cosY = cos(pitch); -// F64 cosZ = cos(yaw); -// -// F64 sinX = sin(roll); -// F64 sinY = sin(pitch); -// F64 sinZ = sin(yaw); -// -// mQ[VW] = (F32)sqrt(cosY*cosZ - sinX*sinY*sinZ + cosX*cosZ + cosX*cosY + 1.0)*.5; -// if (fabs(mQ[VW]) < F_APPROXIMATELY_ZERO) -// { -// // null rotation, any axis will do -// mQ[VX] = 0.0f; -// mQ[VY] = 1.0f; -// mQ[VZ] = 0.0f; -// } -// else -// { -// F32 inv_s = 1.0f / (4.0f * mQ[VW]); -// mQ[VX] = (F32)-(-sinX*cosY - cosX*sinY*sinZ - sinX*cosZ) * inv_s; -// mQ[VY] = (F32)-(-cosX*sinY*cosZ + sinX*sinZ - sinY) * inv_s; -// mQ[VZ] = (F32)-(-cosY*sinZ - sinX*sinY*cosZ - cosX*sinZ) * inv_s; -// } -// -//#else // This only works on a certain subset of roll/pitch/yaw -// -// F64 cosX = cosf(roll/2.0); -// F64 cosY = cosf(pitch/2.0); -// F64 cosZ = cosf(yaw/2.0); -// -// F64 sinX = sinf(roll/2.0); -// F64 sinY = sinf(pitch/2.0); -// F64 sinZ = sinf(yaw/2.0); -// -// mQ[VW] = (F32)(cosX*cosY*cosZ + sinX*sinY*sinZ); -// mQ[VX] = (F32)(sinX*cosY*cosZ - cosX*sinY*sinZ); -// mQ[VY] = (F32)(cosX*sinY*cosZ + sinX*cosY*sinZ); -// mQ[VZ] = (F32)(cosX*cosY*sinZ - sinX*sinY*cosZ); -//#endif -// -// normalize(); -// return (*this); -} - -// SJB: This code is correct for a logicly stored (non-transposed) matrix; -// Our matrices are stored transposed, OpenGL style, so this generates the -// INVERSE matrix, or the CORRECT matrix form an INVERSE quaternion. -// Because we use similar logic in LLMatrix3::quaternion(), -// we are internally consistant so everything works OK :) -LLMatrix3 LLQuaternion::getMatrix3(void) const -{ - LLMatrix3 mat; - F32 xx, xy, xz, xw, yy, yz, yw, zz, zw; - - xx = mQ[VX] * mQ[VX]; - xy = mQ[VX] * mQ[VY]; - xz = mQ[VX] * mQ[VZ]; - xw = mQ[VX] * mQ[VW]; - - yy = mQ[VY] * mQ[VY]; - yz = mQ[VY] * mQ[VZ]; - yw = mQ[VY] * mQ[VW]; - - zz = mQ[VZ] * mQ[VZ]; - zw = mQ[VZ] * mQ[VW]; - - mat.mMatrix[0][0] = 1.f - 2.f * ( yy + zz ); - mat.mMatrix[0][1] = 2.f * ( xy + zw ); - mat.mMatrix[0][2] = 2.f * ( xz - yw ); - - mat.mMatrix[1][0] = 2.f * ( xy - zw ); - mat.mMatrix[1][1] = 1.f - 2.f * ( xx + zz ); - mat.mMatrix[1][2] = 2.f * ( yz + xw ); - - mat.mMatrix[2][0] = 2.f * ( xz + yw ); - mat.mMatrix[2][1] = 2.f * ( yz - xw ); - mat.mMatrix[2][2] = 1.f - 2.f * ( xx + yy ); - - return mat; -} - -LLMatrix4 LLQuaternion::getMatrix4(void) const -{ - LLMatrix4 mat; - F32 xx, xy, xz, xw, yy, yz, yw, zz, zw; - - xx = mQ[VX] * mQ[VX]; - xy = mQ[VX] * mQ[VY]; - xz = mQ[VX] * mQ[VZ]; - xw = mQ[VX] * mQ[VW]; - - yy = mQ[VY] * mQ[VY]; - yz = mQ[VY] * mQ[VZ]; - yw = mQ[VY] * mQ[VW]; - - zz = mQ[VZ] * mQ[VZ]; - zw = mQ[VZ] * mQ[VW]; - - mat.mMatrix[0][0] = 1.f - 2.f * ( yy + zz ); - mat.mMatrix[0][1] = 2.f * ( xy + zw ); - mat.mMatrix[0][2] = 2.f * ( xz - yw ); - - mat.mMatrix[1][0] = 2.f * ( xy - zw ); - mat.mMatrix[1][1] = 1.f - 2.f * ( xx + zz ); - mat.mMatrix[1][2] = 2.f * ( yz + xw ); - - mat.mMatrix[2][0] = 2.f * ( xz + yw ); - mat.mMatrix[2][1] = 2.f * ( yz - xw ); - mat.mMatrix[2][2] = 1.f - 2.f * ( xx + yy ); - - // TODO -- should we set the translation portion to zero? - - return mat; -} - - - - -// Other useful methods - - -// calculate the shortest rotation from a to b -void LLQuaternion::shortestArc(const LLVector3 &a, const LLVector3 &b) -{ - // Make a local copy of both vectors. - LLVector3 vec_a = a; - LLVector3 vec_b = b; - - // Make sure neither vector is zero length. Also normalize - // the vectors while we are at it. - F32 vec_a_mag = vec_a.normalize(); - F32 vec_b_mag = vec_b.normalize(); - if (vec_a_mag < F_APPROXIMATELY_ZERO || - vec_b_mag < F_APPROXIMATELY_ZERO) - { - // Can't calculate a rotation from this. - // Just return ZERO_ROTATION instead. - loadIdentity(); - return; - } - - // Create an axis to rotate around, and the cos of the angle to rotate. - LLVector3 axis = vec_a % vec_b; - F32 cos_theta = vec_a * vec_b; - - // Check the angle between the vectors to see if they are parallel or anti-parallel. - if (cos_theta > 1.0 - F_APPROXIMATELY_ZERO) - { - // a and b are parallel. No rotation is necessary. - loadIdentity(); - } - else if (cos_theta < -1.0 + F_APPROXIMATELY_ZERO) - { - // a and b are anti-parallel. - // Rotate 180 degrees around some orthogonal axis. - // Find the projection of the x-axis onto a, and try - // using the vector between the projection and the x-axis - // as the orthogonal axis. - LLVector3 proj = vec_a.mV[VX] / (vec_a * vec_a) * vec_a; - LLVector3 ortho_axis(1.f, 0.f, 0.f); - ortho_axis -= proj; - - // Turn this into an orthonormal axis. - F32 ortho_length = ortho_axis.normalize(); - // If the axis' length is 0, then our guess at an orthogonal axis - // was wrong (a is parallel to the x-axis). - if (ortho_length < F_APPROXIMATELY_ZERO) - { - // Use the z-axis instead. - ortho_axis.setVec(0.f, 0.f, 1.f); - } - - // Construct a quaternion from this orthonormal axis. - mQ[VX] = ortho_axis.mV[VX]; - mQ[VY] = ortho_axis.mV[VY]; - mQ[VZ] = ortho_axis.mV[VZ]; - mQ[VW] = 0.f; - } - else - { - // a and b are NOT parallel or anti-parallel. - // Return the rotation between these vectors. - F32 theta = (F32)acos(cos_theta); - - setAngleAxis(theta, axis); - } -} - -// constrains rotation to a cone angle specified in radians -const LLQuaternion &LLQuaternion::constrain(F32 radians) -{ - const F32 cos_angle_lim = cosf( radians/2 ); // mQ[VW] limit - const F32 sin_angle_lim = sinf( radians/2 ); // rotation axis length limit - - if (mQ[VW] < 0.f) - { - mQ[VX] *= -1.f; - mQ[VY] *= -1.f; - mQ[VZ] *= -1.f; - mQ[VW] *= -1.f; - } - - // if rotation angle is greater than limit (cos is less than limit) - if( mQ[VW] < cos_angle_lim ) - { - mQ[VW] = cos_angle_lim; - F32 axis_len = sqrtf( mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] ); // sin(theta/2) - F32 axis_mult_fact = sin_angle_lim / axis_len; - mQ[VX] *= axis_mult_fact; - mQ[VY] *= axis_mult_fact; - mQ[VZ] *= axis_mult_fact; - } - - return *this; -} - -// Operators - -std::ostream& operator<<(std::ostream &s, const LLQuaternion &a) -{ - s << "{ " - << a.mQ[VX] << ", " << a.mQ[VY] << ", " << a.mQ[VZ] << ", " << a.mQ[VW] - << " }"; - return s; -} - - -// Does NOT renormalize the result -LLQuaternion operator*(const LLQuaternion &a, const LLQuaternion &b) -{ -// LLQuaternion::mMultCount++; - - LLQuaternion q( - b.mQ[3] * a.mQ[0] + b.mQ[0] * a.mQ[3] + b.mQ[1] * a.mQ[2] - b.mQ[2] * a.mQ[1], - b.mQ[3] * a.mQ[1] + b.mQ[1] * a.mQ[3] + b.mQ[2] * a.mQ[0] - b.mQ[0] * a.mQ[2], - b.mQ[3] * a.mQ[2] + b.mQ[2] * a.mQ[3] + b.mQ[0] * a.mQ[1] - b.mQ[1] * a.mQ[0], - b.mQ[3] * a.mQ[3] - b.mQ[0] * a.mQ[0] - b.mQ[1] * a.mQ[1] - b.mQ[2] * a.mQ[2] - ); - return q; -} - -/* -LLMatrix4 operator*(const LLMatrix4 &m, const LLQuaternion &q) -{ - LLMatrix4 qmat(q); - return (m*qmat); -} -*/ - - - -LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) -{ - F32 rw = - rot.mQ[VX] * a.mV[VX] - rot.mQ[VY] * a.mV[VY] - rot.mQ[VZ] * a.mV[VZ]; - F32 rx = rot.mQ[VW] * a.mV[VX] + rot.mQ[VY] * a.mV[VZ] - rot.mQ[VZ] * a.mV[VY]; - F32 ry = rot.mQ[VW] * a.mV[VY] + rot.mQ[VZ] * a.mV[VX] - rot.mQ[VX] * a.mV[VZ]; - F32 rz = rot.mQ[VW] * a.mV[VZ] + rot.mQ[VX] * a.mV[VY] - rot.mQ[VY] * a.mV[VX]; - - F32 nx = - rw * rot.mQ[VX] + rx * rot.mQ[VW] - ry * rot.mQ[VZ] + rz * rot.mQ[VY]; - F32 ny = - rw * rot.mQ[VY] + ry * rot.mQ[VW] - rz * rot.mQ[VX] + rx * rot.mQ[VZ]; - F32 nz = - rw * rot.mQ[VZ] + rz * rot.mQ[VW] - rx * rot.mQ[VY] + ry * rot.mQ[VX]; - - return LLVector4(nx, ny, nz, a.mV[VW]); -} - -LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) -{ - F32 rw = - rot.mQ[VX] * a.mV[VX] - rot.mQ[VY] * a.mV[VY] - rot.mQ[VZ] * a.mV[VZ]; - F32 rx = rot.mQ[VW] * a.mV[VX] + rot.mQ[VY] * a.mV[VZ] - rot.mQ[VZ] * a.mV[VY]; - F32 ry = rot.mQ[VW] * a.mV[VY] + rot.mQ[VZ] * a.mV[VX] - rot.mQ[VX] * a.mV[VZ]; - F32 rz = rot.mQ[VW] * a.mV[VZ] + rot.mQ[VX] * a.mV[VY] - rot.mQ[VY] * a.mV[VX]; - - F32 nx = - rw * rot.mQ[VX] + rx * rot.mQ[VW] - ry * rot.mQ[VZ] + rz * rot.mQ[VY]; - F32 ny = - rw * rot.mQ[VY] + ry * rot.mQ[VW] - rz * rot.mQ[VX] + rx * rot.mQ[VZ]; - F32 nz = - rw * rot.mQ[VZ] + rz * rot.mQ[VW] - rx * rot.mQ[VY] + ry * rot.mQ[VX]; - - return LLVector3(nx, ny, nz); -} - -LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) -{ - F64 rw = - rot.mQ[VX] * a.mdV[VX] - rot.mQ[VY] * a.mdV[VY] - rot.mQ[VZ] * a.mdV[VZ]; - F64 rx = rot.mQ[VW] * a.mdV[VX] + rot.mQ[VY] * a.mdV[VZ] - rot.mQ[VZ] * a.mdV[VY]; - F64 ry = rot.mQ[VW] * a.mdV[VY] + rot.mQ[VZ] * a.mdV[VX] - rot.mQ[VX] * a.mdV[VZ]; - F64 rz = rot.mQ[VW] * a.mdV[VZ] + rot.mQ[VX] * a.mdV[VY] - rot.mQ[VY] * a.mdV[VX]; - - F64 nx = - rw * rot.mQ[VX] + rx * rot.mQ[VW] - ry * rot.mQ[VZ] + rz * rot.mQ[VY]; - F64 ny = - rw * rot.mQ[VY] + ry * rot.mQ[VW] - rz * rot.mQ[VX] + rx * rot.mQ[VZ]; - F64 nz = - rw * rot.mQ[VZ] + rz * rot.mQ[VW] - rx * rot.mQ[VY] + ry * rot.mQ[VX]; - - return LLVector3d(nx, ny, nz); -} - -F32 dot(const LLQuaternion &a, const LLQuaternion &b) -{ - return a.mQ[VX] * b.mQ[VX] + - a.mQ[VY] * b.mQ[VY] + - a.mQ[VZ] * b.mQ[VZ] + - a.mQ[VW] * b.mQ[VW]; -} - -// DEMO HACK: This lerp is probably inocrrect now due intermediate normalization -// it should look more like the lerp below -#if 0 -// linear interpolation -LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) -{ - LLQuaternion r; - r = t * (q - p) + p; - r.normalize(); - return r; -} -#endif - -// lerp from identity to q -LLQuaternion lerp(F32 t, const LLQuaternion &q) -{ - LLQuaternion r; - r.mQ[VX] = t * q.mQ[VX]; - r.mQ[VY] = t * q.mQ[VY]; - r.mQ[VZ] = t * q.mQ[VZ]; - r.mQ[VW] = t * (q.mQ[VZ] - 1.f) + 1.f; - r.normalize(); - return r; -} - -LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) -{ - LLQuaternion r; - F32 inv_t; - - inv_t = 1.f - t; - - r.mQ[VX] = t * q.mQ[VX] + (inv_t * p.mQ[VX]); - r.mQ[VY] = t * q.mQ[VY] + (inv_t * p.mQ[VY]); - r.mQ[VZ] = t * q.mQ[VZ] + (inv_t * p.mQ[VZ]); - r.mQ[VW] = t * q.mQ[VW] + (inv_t * p.mQ[VW]); - r.normalize(); - return r; -} - - -// spherical linear interpolation -LLQuaternion slerp( F32 u, const LLQuaternion &a, const LLQuaternion &b ) -{ - // cosine theta = dot product of a and b - F32 cos_t = a.mQ[0]*b.mQ[0] + a.mQ[1]*b.mQ[1] + a.mQ[2]*b.mQ[2] + a.mQ[3]*b.mQ[3]; - - // if b is on opposite hemisphere from a, use -a instead - int bflip; - if (cos_t < 0.0f) - { - cos_t = -cos_t; - bflip = TRUE; - } - else - bflip = FALSE; - - // if B is (within precision limits) the same as A, - // just linear interpolate between A and B. - F32 alpha; // interpolant - F32 beta; // 1 - interpolant - if (1.0f - cos_t < 0.00001f) - { - beta = 1.0f - u; - alpha = u; - } - else - { - F32 theta = acosf(cos_t); - F32 sin_t = sinf(theta); - beta = sinf(theta - u*theta) / sin_t; - alpha = sinf(u*theta) / sin_t; - } - - if (bflip) - beta = -beta; - - // interpolate - LLQuaternion ret; - ret.mQ[0] = beta*a.mQ[0] + alpha*b.mQ[0]; - ret.mQ[1] = beta*a.mQ[1] + alpha*b.mQ[1]; - ret.mQ[2] = beta*a.mQ[2] + alpha*b.mQ[2]; - ret.mQ[3] = beta*a.mQ[3] + alpha*b.mQ[3]; - - return ret; -} - -// lerp whenever possible -LLQuaternion nlerp(F32 t, const LLQuaternion &a, const LLQuaternion &b) -{ - if (dot(a, b) < 0.f) - { - return slerp(t, a, b); - } - else - { - return lerp(t, a, b); - } -} - -LLQuaternion nlerp(F32 t, const LLQuaternion &q) -{ - if (q.mQ[VW] < 0.f) - { - return slerp(t, q); - } - else - { - return lerp(t, q); - } -} - -// slerp from identity quaternion to another quaternion -LLQuaternion slerp(F32 t, const LLQuaternion &q) -{ - F32 c = q.mQ[VW]; - if (1.0f == t || 1.0f == c) - { - // the trivial cases - return q; - } - - LLQuaternion r; - F32 s, angle, stq, stp; - - s = (F32) sqrt(1.f - c*c); - - if (c < 0.0f) - { - // when c < 0.0 then theta > PI/2 - // since quat and -quat are the same rotation we invert one of - // p or q to reduce unecessary spins - // A equivalent way to do it is to convert acos(c) as if it had - // been negative, and to negate stp - angle = (F32) acos(-c); - stp = -(F32) sin(angle * (1.f - t)); - stq = (F32) sin(angle * t); - } - else - { - angle = (F32) acos(c); - stp = (F32) sin(angle * (1.f - t)); - stq = (F32) sin(angle * t); - } - - r.mQ[VX] = (q.mQ[VX] * stq) / s; - r.mQ[VY] = (q.mQ[VY] * stq) / s; - r.mQ[VZ] = (q.mQ[VZ] * stq) / s; - r.mQ[VW] = (stp + q.mQ[VW] * stq) / s; - - return r; -} - -LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) -{ - LLQuaternion xQ( xRot*DEG_TO_RAD, LLVector3(1.0f, 0.0f, 0.0f) ); - LLQuaternion yQ( yRot*DEG_TO_RAD, LLVector3(0.0f, 1.0f, 0.0f) ); - LLQuaternion zQ( zRot*DEG_TO_RAD, LLVector3(0.0f, 0.0f, 1.0f) ); - LLQuaternion ret; - switch( order ) - { - case LLQuaternion::XYZ: - ret = xQ * yQ * zQ; - break; - case LLQuaternion::YZX: - ret = yQ * zQ * xQ; - break; - case LLQuaternion::ZXY: - ret = zQ * xQ * yQ; - break; - case LLQuaternion::XZY: - ret = xQ * zQ * yQ; - break; - case LLQuaternion::YXZ: - ret = yQ * xQ * zQ; - break; - case LLQuaternion::ZYX: - ret = zQ * yQ * xQ; - break; - } - return ret; -} - -const char *OrderToString( const LLQuaternion::Order order ) -{ - const char *p = NULL; - switch( order ) - { - default: - case LLQuaternion::XYZ: - p = "XYZ"; - break; - case LLQuaternion::YZX: - p = "YZX"; - break; - case LLQuaternion::ZXY: - p = "ZXY"; - break; - case LLQuaternion::XZY: - p = "XZY"; - break; - case LLQuaternion::YXZ: - p = "YXZ"; - break; - case LLQuaternion::ZYX: - p = "ZYX"; - break; - } - return p; -} - -LLQuaternion::Order StringToOrder( const char *str ) -{ - if (strncmp(str, "XYZ", 3)==0 || strncmp(str, "xyz", 3)==0) - return LLQuaternion::XYZ; - - if (strncmp(str, "YZX", 3)==0 || strncmp(str, "yzx", 3)==0) - return LLQuaternion::YZX; - - if (strncmp(str, "ZXY", 3)==0 || strncmp(str, "zxy", 3)==0) - return LLQuaternion::ZXY; - - if (strncmp(str, "XZY", 3)==0 || strncmp(str, "xzy", 3)==0) - return LLQuaternion::XZY; - - if (strncmp(str, "YXZ", 3)==0 || strncmp(str, "yxz", 3)==0) - return LLQuaternion::YXZ; - - if (strncmp(str, "ZYX", 3)==0 || strncmp(str, "zyx", 3)==0) - return LLQuaternion::ZYX; - - return LLQuaternion::XYZ; -} - -void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const -{ - F32 cos_a = mQ[VW]; - if (cos_a > 1.0f) cos_a = 1.0f; - if (cos_a < -1.0f) cos_a = -1.0f; - - F32 sin_a = (F32) sqrt( 1.0f - cos_a * cos_a ); - - if ( fabs( sin_a ) < 0.0005f ) - sin_a = 1.0f; - else - sin_a = 1.f/sin_a; - - F32 temp_angle = 2.0f * (F32) acos( cos_a ); - if (temp_angle > F_PI) - { - // The (angle,axis) pair should never have angles outside [PI, -PI] - // since we want the _shortest_ (angle,axis) solution. - // Since acos is defined for [0, PI], and we multiply by 2.0, we - // can push the angle outside the acceptible range. - // When this happens we set the angle to the other portion of a - // full 2PI rotation, and negate the axis, which reverses the - // direction of the rotation (by the right-hand rule). - *angle = 2.f * F_PI - temp_angle; - vec.mV[VX] = - mQ[VX] * sin_a; - vec.mV[VY] = - mQ[VY] * sin_a; - vec.mV[VZ] = - mQ[VZ] * sin_a; - } - else - { - *angle = temp_angle; - vec.mV[VX] = mQ[VX] * sin_a; - vec.mV[VY] = mQ[VY] * sin_a; - vec.mV[VZ] = mQ[VZ] * sin_a; - } -} - - -// quaternion does not need to be normalized -void LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const -{ - LLMatrix3 rot_mat(*this); - rot_mat.orthogonalize(); - rot_mat.getEulerAngles(roll, pitch, yaw); - -// // NOTE: LLQuaternion's are actually inverted with respect to -// // the matrices, so this code also assumes inverted quaternions -// // (-x, -y, -z, w). The result is that roll,pitch,yaw are applied -// // in reverse order (yaw,pitch,roll). -// F32 x = -mQ[VX], y = -mQ[VY], z = -mQ[VZ], w = mQ[VW]; -// F64 m20 = 2.0*(x*z-y*w); -// if (1.0f - fabsf(m20) < F_APPROXIMATELY_ZERO) -// { -// *roll = 0.0f; -// *pitch = (F32)asin(m20); -// *yaw = (F32)atan2(2.0*(x*y-z*w), 1.0 - 2.0*(x*x+z*z)); -// } -// else -// { -// *roll = (F32)atan2(-2.0*(y*z+x*w), 1.0-2.0*(x*x+y*y)); -// *pitch = (F32)asin(m20); -// *yaw = (F32)atan2(-2.0*(x*y+z*w), 1.0-2.0*(y*y+z*z)); -// } -} - -// Saves space by using the fact that our quaternions are normalized -LLVector3 LLQuaternion::packToVector3() const -{ - if( mQ[VW] >= 0 ) - { - return LLVector3( mQ[VX], mQ[VY], mQ[VZ] ); - } - else - { - return LLVector3( -mQ[VX], -mQ[VY], -mQ[VZ] ); - } -} - -// Saves space by using the fact that our quaternions are normalized -void LLQuaternion::unpackFromVector3( const LLVector3& vec ) -{ - mQ[VX] = vec.mV[VX]; - mQ[VY] = vec.mV[VY]; - mQ[VZ] = vec.mV[VZ]; - F32 t = 1.f - vec.magVecSquared(); - if( t > 0 ) - { - mQ[VW] = sqrt( t ); - } - else - { - // Need this to avoid trying to find the square root of a negative number due - // to floating point error. - mQ[VW] = 0; - } -} - -BOOL LLQuaternion::parseQuat(const std::string& buf, LLQuaternion* value) -{ - if( buf.empty() || value == NULL) - { - return FALSE; - } - - LLQuaternion quat; - S32 count = sscanf( buf.c_str(), "%f %f %f %f", quat.mQ + 0, quat.mQ + 1, quat.mQ + 2, quat.mQ + 3 ); - if( 4 == count ) - { - value->set( quat ); - return TRUE; - } - - return FALSE; -} - - -// End +/** + * @file llquaternion.cpp + * @brief LLQuaternion class implementation. + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llmath.h" // for F_PI + +#include "llquaternion.h" + +//#include "vmath.h" +#include "v3math.h" +#include "v3dmath.h" +#include "v4math.h" +#include "m4math.h" +#include "m3math.h" +#include "llquantize.h" + +// WARNING: Don't use this for global const definitions! using this +// at the top of a *.cpp file might not give you what you think. +const LLQuaternion LLQuaternion::DEFAULT; + +// Constructors + +LLQuaternion::LLQuaternion(const LLMatrix4 &mat) +{ + *this = mat.quaternion(); + normalize(); +} + +LLQuaternion::LLQuaternion(const LLMatrix3 &mat) +{ + *this = mat.quaternion(); + normalize(); +} + +LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec) +{ + LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); + v.normalize(); + + F32 c, s; + c = cosf(angle*0.5f); + s = sinf(angle*0.5f); + + mQ[VX] = v.mV[VX] * s; + mQ[VY] = v.mV[VY] * s; + mQ[VZ] = v.mV[VZ] * s; + mQ[VW] = c; + normalize(); +} + +LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec) +{ + LLVector3 v(vec); + v.normalize(); + + F32 c, s; + c = cosf(angle*0.5f); + s = sinf(angle*0.5f); + + mQ[VX] = v.mV[VX] * s; + mQ[VY] = v.mV[VY] * s; + mQ[VZ] = v.mV[VZ] * s; + mQ[VW] = c; + normalize(); +} + +LLQuaternion::LLQuaternion(const LLVector3 &x_axis, + const LLVector3 &y_axis, + const LLVector3 &z_axis) +{ + LLMatrix3 mat; + mat.setRows(x_axis, y_axis, z_axis); + *this = mat.quaternion(); + normalize(); +} + +// Quatizations +void LLQuaternion::quantize16(F32 lower, F32 upper) +{ + F32 x = mQ[VX]; + F32 y = mQ[VY]; + F32 z = mQ[VZ]; + F32 s = mQ[VS]; + + x = U16_to_F32(F32_to_U16_ROUND(x, lower, upper), lower, upper); + y = U16_to_F32(F32_to_U16_ROUND(y, lower, upper), lower, upper); + z = U16_to_F32(F32_to_U16_ROUND(z, lower, upper), lower, upper); + s = U16_to_F32(F32_to_U16_ROUND(s, lower, upper), lower, upper); + + mQ[VX] = x; + mQ[VY] = y; + mQ[VZ] = z; + mQ[VS] = s; + + normalize(); +} + +void LLQuaternion::quantize8(F32 lower, F32 upper) +{ + mQ[VX] = U8_to_F32(F32_to_U8_ROUND(mQ[VX], lower, upper), lower, upper); + mQ[VY] = U8_to_F32(F32_to_U8_ROUND(mQ[VY], lower, upper), lower, upper); + mQ[VZ] = U8_to_F32(F32_to_U8_ROUND(mQ[VZ], lower, upper), lower, upper); + mQ[VS] = U8_to_F32(F32_to_U8_ROUND(mQ[VS], lower, upper), lower, upper); + + normalize(); +} + +// LLVector3 Magnitude and Normalization Functions + + +// Set LLQuaternion routines + +const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, F32 x, F32 y, F32 z) +{ + LLVector3 vec(x, y, z); + vec.normalize(); + + angle *= 0.5f; + F32 c, s; + c = cosf(angle); + s = sinf(angle); + + mQ[VX] = vec.mV[VX]*s; + mQ[VY] = vec.mV[VY]*s; + mQ[VZ] = vec.mV[VZ]*s; + mQ[VW] = c; + + normalize(); + return (*this); +} + +const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, const LLVector3 &vec) +{ + LLVector3 v(vec); + v.normalize(); + + angle *= 0.5f; + F32 c, s; + c = cosf(angle); + s = sinf(angle); + + mQ[VX] = v.mV[VX]*s; + mQ[VY] = v.mV[VY]*s; + mQ[VZ] = v.mV[VZ]*s; + mQ[VW] = c; + + normalize(); + return (*this); +} + +const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, const LLVector4 &vec) +{ + LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); + v.normalize(); + + F32 c, s; + c = cosf(angle*0.5f); + s = sinf(angle*0.5f); + + mQ[VX] = v.mV[VX]*s; + mQ[VY] = v.mV[VY]*s; + mQ[VZ] = v.mV[VZ]*s; + mQ[VW] = c; + + normalize(); + return (*this); +} + +const LLQuaternion& LLQuaternion::setEulerAngles(F32 roll, F32 pitch, F32 yaw) +{ + LLMatrix3 rot_mat(roll, pitch, yaw); + rot_mat.orthogonalize(); + *this = rot_mat.quaternion(); + + normalize(); + return (*this); +} + +// deprecated +const LLQuaternion& LLQuaternion::set(const LLMatrix3 &mat) +{ + *this = mat.quaternion(); + normalize(); + return (*this); +} + +// deprecated +const LLQuaternion& LLQuaternion::set(const LLMatrix4 &mat) +{ + *this = mat.quaternion(); + normalize(); + return (*this); +} + +// deprecated +const LLQuaternion& LLQuaternion::setQuat(F32 angle, F32 x, F32 y, F32 z) +{ + LLVector3 vec(x, y, z); + vec.normalize(); + + angle *= 0.5f; + F32 c, s; + c = cosf(angle); + s = sinf(angle); + + mQ[VX] = vec.mV[VX]*s; + mQ[VY] = vec.mV[VY]*s; + mQ[VZ] = vec.mV[VZ]*s; + mQ[VW] = c; + + normalize(); + return (*this); +} + +// deprecated +const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector3 &vec) +{ + LLVector3 v(vec); + v.normalize(); + + angle *= 0.5f; + F32 c, s; + c = cosf(angle); + s = sinf(angle); + + mQ[VX] = v.mV[VX]*s; + mQ[VY] = v.mV[VY]*s; + mQ[VZ] = v.mV[VZ]*s; + mQ[VW] = c; + + normalize(); + return (*this); +} + +const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector4 &vec) +{ + LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); + v.normalize(); + + F32 c, s; + c = cosf(angle*0.5f); + s = sinf(angle*0.5f); + + mQ[VX] = v.mV[VX]*s; + mQ[VY] = v.mV[VY]*s; + mQ[VZ] = v.mV[VZ]*s; + mQ[VW] = c; + + normalize(); + return (*this); +} + +const LLQuaternion& LLQuaternion::setQuat(F32 roll, F32 pitch, F32 yaw) +{ + LLMatrix3 rot_mat(roll, pitch, yaw); + rot_mat.orthogonalize(); + *this = rot_mat.quaternion(); + + normalize(); + return (*this); +} + +const LLQuaternion& LLQuaternion::setQuat(const LLMatrix3 &mat) +{ + *this = mat.quaternion(); + normalize(); + return (*this); +} + +const LLQuaternion& LLQuaternion::setQuat(const LLMatrix4 &mat) +{ + *this = mat.quaternion(); + normalize(); + return (*this); +//#if 1 +// // NOTE: LLQuaternion's are actually inverted with respect to +// // the matrices, so this code also assumes inverted quaternions +// // (-x, -y, -z, w). The result is that roll,pitch,yaw are applied +// // in reverse order (yaw,pitch,roll). +// F64 cosX = cos(roll); +// F64 cosY = cos(pitch); +// F64 cosZ = cos(yaw); +// +// F64 sinX = sin(roll); +// F64 sinY = sin(pitch); +// F64 sinZ = sin(yaw); +// +// mQ[VW] = (F32)sqrt(cosY*cosZ - sinX*sinY*sinZ + cosX*cosZ + cosX*cosY + 1.0)*.5; +// if (fabs(mQ[VW]) < F_APPROXIMATELY_ZERO) +// { +// // null rotation, any axis will do +// mQ[VX] = 0.0f; +// mQ[VY] = 1.0f; +// mQ[VZ] = 0.0f; +// } +// else +// { +// F32 inv_s = 1.0f / (4.0f * mQ[VW]); +// mQ[VX] = (F32)-(-sinX*cosY - cosX*sinY*sinZ - sinX*cosZ) * inv_s; +// mQ[VY] = (F32)-(-cosX*sinY*cosZ + sinX*sinZ - sinY) * inv_s; +// mQ[VZ] = (F32)-(-cosY*sinZ - sinX*sinY*cosZ - cosX*sinZ) * inv_s; +// } +// +//#else // This only works on a certain subset of roll/pitch/yaw +// +// F64 cosX = cosf(roll/2.0); +// F64 cosY = cosf(pitch/2.0); +// F64 cosZ = cosf(yaw/2.0); +// +// F64 sinX = sinf(roll/2.0); +// F64 sinY = sinf(pitch/2.0); +// F64 sinZ = sinf(yaw/2.0); +// +// mQ[VW] = (F32)(cosX*cosY*cosZ + sinX*sinY*sinZ); +// mQ[VX] = (F32)(sinX*cosY*cosZ - cosX*sinY*sinZ); +// mQ[VY] = (F32)(cosX*sinY*cosZ + sinX*cosY*sinZ); +// mQ[VZ] = (F32)(cosX*cosY*sinZ - sinX*sinY*cosZ); +//#endif +// +// normalize(); +// return (*this); +} + +// SJB: This code is correct for a logicly stored (non-transposed) matrix; +// Our matrices are stored transposed, OpenGL style, so this generates the +// INVERSE matrix, or the CORRECT matrix form an INVERSE quaternion. +// Because we use similar logic in LLMatrix3::quaternion(), +// we are internally consistant so everything works OK :) +LLMatrix3 LLQuaternion::getMatrix3(void) const +{ + LLMatrix3 mat; + F32 xx, xy, xz, xw, yy, yz, yw, zz, zw; + + xx = mQ[VX] * mQ[VX]; + xy = mQ[VX] * mQ[VY]; + xz = mQ[VX] * mQ[VZ]; + xw = mQ[VX] * mQ[VW]; + + yy = mQ[VY] * mQ[VY]; + yz = mQ[VY] * mQ[VZ]; + yw = mQ[VY] * mQ[VW]; + + zz = mQ[VZ] * mQ[VZ]; + zw = mQ[VZ] * mQ[VW]; + + mat.mMatrix[0][0] = 1.f - 2.f * ( yy + zz ); + mat.mMatrix[0][1] = 2.f * ( xy + zw ); + mat.mMatrix[0][2] = 2.f * ( xz - yw ); + + mat.mMatrix[1][0] = 2.f * ( xy - zw ); + mat.mMatrix[1][1] = 1.f - 2.f * ( xx + zz ); + mat.mMatrix[1][2] = 2.f * ( yz + xw ); + + mat.mMatrix[2][0] = 2.f * ( xz + yw ); + mat.mMatrix[2][1] = 2.f * ( yz - xw ); + mat.mMatrix[2][2] = 1.f - 2.f * ( xx + yy ); + + return mat; +} + +LLMatrix4 LLQuaternion::getMatrix4(void) const +{ + LLMatrix4 mat; + F32 xx, xy, xz, xw, yy, yz, yw, zz, zw; + + xx = mQ[VX] * mQ[VX]; + xy = mQ[VX] * mQ[VY]; + xz = mQ[VX] * mQ[VZ]; + xw = mQ[VX] * mQ[VW]; + + yy = mQ[VY] * mQ[VY]; + yz = mQ[VY] * mQ[VZ]; + yw = mQ[VY] * mQ[VW]; + + zz = mQ[VZ] * mQ[VZ]; + zw = mQ[VZ] * mQ[VW]; + + mat.mMatrix[0][0] = 1.f - 2.f * ( yy + zz ); + mat.mMatrix[0][1] = 2.f * ( xy + zw ); + mat.mMatrix[0][2] = 2.f * ( xz - yw ); + + mat.mMatrix[1][0] = 2.f * ( xy - zw ); + mat.mMatrix[1][1] = 1.f - 2.f * ( xx + zz ); + mat.mMatrix[1][2] = 2.f * ( yz + xw ); + + mat.mMatrix[2][0] = 2.f * ( xz + yw ); + mat.mMatrix[2][1] = 2.f * ( yz - xw ); + mat.mMatrix[2][2] = 1.f - 2.f * ( xx + yy ); + + // TODO -- should we set the translation portion to zero? + + return mat; +} + + + + +// Other useful methods + + +// calculate the shortest rotation from a to b +void LLQuaternion::shortestArc(const LLVector3 &a, const LLVector3 &b) +{ + // Make a local copy of both vectors. + LLVector3 vec_a = a; + LLVector3 vec_b = b; + + // Make sure neither vector is zero length. Also normalize + // the vectors while we are at it. + F32 vec_a_mag = vec_a.normalize(); + F32 vec_b_mag = vec_b.normalize(); + if (vec_a_mag < F_APPROXIMATELY_ZERO || + vec_b_mag < F_APPROXIMATELY_ZERO) + { + // Can't calculate a rotation from this. + // Just return ZERO_ROTATION instead. + loadIdentity(); + return; + } + + // Create an axis to rotate around, and the cos of the angle to rotate. + LLVector3 axis = vec_a % vec_b; + F32 cos_theta = vec_a * vec_b; + + // Check the angle between the vectors to see if they are parallel or anti-parallel. + if (cos_theta > 1.0 - F_APPROXIMATELY_ZERO) + { + // a and b are parallel. No rotation is necessary. + loadIdentity(); + } + else if (cos_theta < -1.0 + F_APPROXIMATELY_ZERO) + { + // a and b are anti-parallel. + // Rotate 180 degrees around some orthogonal axis. + // Find the projection of the x-axis onto a, and try + // using the vector between the projection and the x-axis + // as the orthogonal axis. + LLVector3 proj = vec_a.mV[VX] / (vec_a * vec_a) * vec_a; + LLVector3 ortho_axis(1.f, 0.f, 0.f); + ortho_axis -= proj; + + // Turn this into an orthonormal axis. + F32 ortho_length = ortho_axis.normalize(); + // If the axis' length is 0, then our guess at an orthogonal axis + // was wrong (a is parallel to the x-axis). + if (ortho_length < F_APPROXIMATELY_ZERO) + { + // Use the z-axis instead. + ortho_axis.setVec(0.f, 0.f, 1.f); + } + + // Construct a quaternion from this orthonormal axis. + mQ[VX] = ortho_axis.mV[VX]; + mQ[VY] = ortho_axis.mV[VY]; + mQ[VZ] = ortho_axis.mV[VZ]; + mQ[VW] = 0.f; + } + else + { + // a and b are NOT parallel or anti-parallel. + // Return the rotation between these vectors. + F32 theta = (F32)acos(cos_theta); + + setAngleAxis(theta, axis); + } +} + +// constrains rotation to a cone angle specified in radians +const LLQuaternion &LLQuaternion::constrain(F32 radians) +{ + const F32 cos_angle_lim = cosf( radians/2 ); // mQ[VW] limit + const F32 sin_angle_lim = sinf( radians/2 ); // rotation axis length limit + + if (mQ[VW] < 0.f) + { + mQ[VX] *= -1.f; + mQ[VY] *= -1.f; + mQ[VZ] *= -1.f; + mQ[VW] *= -1.f; + } + + // if rotation angle is greater than limit (cos is less than limit) + if( mQ[VW] < cos_angle_lim ) + { + mQ[VW] = cos_angle_lim; + F32 axis_len = sqrtf( mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] ); // sin(theta/2) + F32 axis_mult_fact = sin_angle_lim / axis_len; + mQ[VX] *= axis_mult_fact; + mQ[VY] *= axis_mult_fact; + mQ[VZ] *= axis_mult_fact; + } + + return *this; +} + +// Operators + +std::ostream& operator<<(std::ostream &s, const LLQuaternion &a) +{ + s << "{ " + << a.mQ[VX] << ", " << a.mQ[VY] << ", " << a.mQ[VZ] << ", " << a.mQ[VW] + << " }"; + return s; +} + + +// Does NOT renormalize the result +LLQuaternion operator*(const LLQuaternion &a, const LLQuaternion &b) +{ +// LLQuaternion::mMultCount++; + + LLQuaternion q( + b.mQ[3] * a.mQ[0] + b.mQ[0] * a.mQ[3] + b.mQ[1] * a.mQ[2] - b.mQ[2] * a.mQ[1], + b.mQ[3] * a.mQ[1] + b.mQ[1] * a.mQ[3] + b.mQ[2] * a.mQ[0] - b.mQ[0] * a.mQ[2], + b.mQ[3] * a.mQ[2] + b.mQ[2] * a.mQ[3] + b.mQ[0] * a.mQ[1] - b.mQ[1] * a.mQ[0], + b.mQ[3] * a.mQ[3] - b.mQ[0] * a.mQ[0] - b.mQ[1] * a.mQ[1] - b.mQ[2] * a.mQ[2] + ); + return q; +} + +/* +LLMatrix4 operator*(const LLMatrix4 &m, const LLQuaternion &q) +{ + LLMatrix4 qmat(q); + return (m*qmat); +} +*/ + + + +LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) +{ + F32 rw = - rot.mQ[VX] * a.mV[VX] - rot.mQ[VY] * a.mV[VY] - rot.mQ[VZ] * a.mV[VZ]; + F32 rx = rot.mQ[VW] * a.mV[VX] + rot.mQ[VY] * a.mV[VZ] - rot.mQ[VZ] * a.mV[VY]; + F32 ry = rot.mQ[VW] * a.mV[VY] + rot.mQ[VZ] * a.mV[VX] - rot.mQ[VX] * a.mV[VZ]; + F32 rz = rot.mQ[VW] * a.mV[VZ] + rot.mQ[VX] * a.mV[VY] - rot.mQ[VY] * a.mV[VX]; + + F32 nx = - rw * rot.mQ[VX] + rx * rot.mQ[VW] - ry * rot.mQ[VZ] + rz * rot.mQ[VY]; + F32 ny = - rw * rot.mQ[VY] + ry * rot.mQ[VW] - rz * rot.mQ[VX] + rx * rot.mQ[VZ]; + F32 nz = - rw * rot.mQ[VZ] + rz * rot.mQ[VW] - rx * rot.mQ[VY] + ry * rot.mQ[VX]; + + return LLVector4(nx, ny, nz, a.mV[VW]); +} + +LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) +{ + F32 rw = - rot.mQ[VX] * a.mV[VX] - rot.mQ[VY] * a.mV[VY] - rot.mQ[VZ] * a.mV[VZ]; + F32 rx = rot.mQ[VW] * a.mV[VX] + rot.mQ[VY] * a.mV[VZ] - rot.mQ[VZ] * a.mV[VY]; + F32 ry = rot.mQ[VW] * a.mV[VY] + rot.mQ[VZ] * a.mV[VX] - rot.mQ[VX] * a.mV[VZ]; + F32 rz = rot.mQ[VW] * a.mV[VZ] + rot.mQ[VX] * a.mV[VY] - rot.mQ[VY] * a.mV[VX]; + + F32 nx = - rw * rot.mQ[VX] + rx * rot.mQ[VW] - ry * rot.mQ[VZ] + rz * rot.mQ[VY]; + F32 ny = - rw * rot.mQ[VY] + ry * rot.mQ[VW] - rz * rot.mQ[VX] + rx * rot.mQ[VZ]; + F32 nz = - rw * rot.mQ[VZ] + rz * rot.mQ[VW] - rx * rot.mQ[VY] + ry * rot.mQ[VX]; + + return LLVector3(nx, ny, nz); +} + +LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) +{ + F64 rw = - rot.mQ[VX] * a.mdV[VX] - rot.mQ[VY] * a.mdV[VY] - rot.mQ[VZ] * a.mdV[VZ]; + F64 rx = rot.mQ[VW] * a.mdV[VX] + rot.mQ[VY] * a.mdV[VZ] - rot.mQ[VZ] * a.mdV[VY]; + F64 ry = rot.mQ[VW] * a.mdV[VY] + rot.mQ[VZ] * a.mdV[VX] - rot.mQ[VX] * a.mdV[VZ]; + F64 rz = rot.mQ[VW] * a.mdV[VZ] + rot.mQ[VX] * a.mdV[VY] - rot.mQ[VY] * a.mdV[VX]; + + F64 nx = - rw * rot.mQ[VX] + rx * rot.mQ[VW] - ry * rot.mQ[VZ] + rz * rot.mQ[VY]; + F64 ny = - rw * rot.mQ[VY] + ry * rot.mQ[VW] - rz * rot.mQ[VX] + rx * rot.mQ[VZ]; + F64 nz = - rw * rot.mQ[VZ] + rz * rot.mQ[VW] - rx * rot.mQ[VY] + ry * rot.mQ[VX]; + + return LLVector3d(nx, ny, nz); +} + +F32 dot(const LLQuaternion &a, const LLQuaternion &b) +{ + return a.mQ[VX] * b.mQ[VX] + + a.mQ[VY] * b.mQ[VY] + + a.mQ[VZ] * b.mQ[VZ] + + a.mQ[VW] * b.mQ[VW]; +} + +// DEMO HACK: This lerp is probably inocrrect now due intermediate normalization +// it should look more like the lerp below +#if 0 +// linear interpolation +LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) +{ + LLQuaternion r; + r = t * (q - p) + p; + r.normalize(); + return r; +} +#endif + +// lerp from identity to q +LLQuaternion lerp(F32 t, const LLQuaternion &q) +{ + LLQuaternion r; + r.mQ[VX] = t * q.mQ[VX]; + r.mQ[VY] = t * q.mQ[VY]; + r.mQ[VZ] = t * q.mQ[VZ]; + r.mQ[VW] = t * (q.mQ[VZ] - 1.f) + 1.f; + r.normalize(); + return r; +} + +LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) +{ + LLQuaternion r; + F32 inv_t; + + inv_t = 1.f - t; + + r.mQ[VX] = t * q.mQ[VX] + (inv_t * p.mQ[VX]); + r.mQ[VY] = t * q.mQ[VY] + (inv_t * p.mQ[VY]); + r.mQ[VZ] = t * q.mQ[VZ] + (inv_t * p.mQ[VZ]); + r.mQ[VW] = t * q.mQ[VW] + (inv_t * p.mQ[VW]); + r.normalize(); + return r; +} + + +// spherical linear interpolation +LLQuaternion slerp( F32 u, const LLQuaternion &a, const LLQuaternion &b ) +{ + // cosine theta = dot product of a and b + F32 cos_t = a.mQ[0]*b.mQ[0] + a.mQ[1]*b.mQ[1] + a.mQ[2]*b.mQ[2] + a.mQ[3]*b.mQ[3]; + + // if b is on opposite hemisphere from a, use -a instead + int bflip; + if (cos_t < 0.0f) + { + cos_t = -cos_t; + bflip = TRUE; + } + else + bflip = FALSE; + + // if B is (within precision limits) the same as A, + // just linear interpolate between A and B. + F32 alpha; // interpolant + F32 beta; // 1 - interpolant + if (1.0f - cos_t < 0.00001f) + { + beta = 1.0f - u; + alpha = u; + } + else + { + F32 theta = acosf(cos_t); + F32 sin_t = sinf(theta); + beta = sinf(theta - u*theta) / sin_t; + alpha = sinf(u*theta) / sin_t; + } + + if (bflip) + beta = -beta; + + // interpolate + LLQuaternion ret; + ret.mQ[0] = beta*a.mQ[0] + alpha*b.mQ[0]; + ret.mQ[1] = beta*a.mQ[1] + alpha*b.mQ[1]; + ret.mQ[2] = beta*a.mQ[2] + alpha*b.mQ[2]; + ret.mQ[3] = beta*a.mQ[3] + alpha*b.mQ[3]; + + return ret; +} + +// lerp whenever possible +LLQuaternion nlerp(F32 t, const LLQuaternion &a, const LLQuaternion &b) +{ + if (dot(a, b) < 0.f) + { + return slerp(t, a, b); + } + else + { + return lerp(t, a, b); + } +} + +LLQuaternion nlerp(F32 t, const LLQuaternion &q) +{ + if (q.mQ[VW] < 0.f) + { + return slerp(t, q); + } + else + { + return lerp(t, q); + } +} + +// slerp from identity quaternion to another quaternion +LLQuaternion slerp(F32 t, const LLQuaternion &q) +{ + F32 c = q.mQ[VW]; + if (1.0f == t || 1.0f == c) + { + // the trivial cases + return q; + } + + LLQuaternion r; + F32 s, angle, stq, stp; + + s = (F32) sqrt(1.f - c*c); + + if (c < 0.0f) + { + // when c < 0.0 then theta > PI/2 + // since quat and -quat are the same rotation we invert one of + // p or q to reduce unecessary spins + // A equivalent way to do it is to convert acos(c) as if it had + // been negative, and to negate stp + angle = (F32) acos(-c); + stp = -(F32) sin(angle * (1.f - t)); + stq = (F32) sin(angle * t); + } + else + { + angle = (F32) acos(c); + stp = (F32) sin(angle * (1.f - t)); + stq = (F32) sin(angle * t); + } + + r.mQ[VX] = (q.mQ[VX] * stq) / s; + r.mQ[VY] = (q.mQ[VY] * stq) / s; + r.mQ[VZ] = (q.mQ[VZ] * stq) / s; + r.mQ[VW] = (stp + q.mQ[VW] * stq) / s; + + return r; +} + +LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) +{ + LLQuaternion xQ( xRot*DEG_TO_RAD, LLVector3(1.0f, 0.0f, 0.0f) ); + LLQuaternion yQ( yRot*DEG_TO_RAD, LLVector3(0.0f, 1.0f, 0.0f) ); + LLQuaternion zQ( zRot*DEG_TO_RAD, LLVector3(0.0f, 0.0f, 1.0f) ); + LLQuaternion ret; + switch( order ) + { + case LLQuaternion::XYZ: + ret = xQ * yQ * zQ; + break; + case LLQuaternion::YZX: + ret = yQ * zQ * xQ; + break; + case LLQuaternion::ZXY: + ret = zQ * xQ * yQ; + break; + case LLQuaternion::XZY: + ret = xQ * zQ * yQ; + break; + case LLQuaternion::YXZ: + ret = yQ * xQ * zQ; + break; + case LLQuaternion::ZYX: + ret = zQ * yQ * xQ; + break; + } + return ret; +} + +const char *OrderToString( const LLQuaternion::Order order ) +{ + const char *p = NULL; + switch( order ) + { + default: + case LLQuaternion::XYZ: + p = "XYZ"; + break; + case LLQuaternion::YZX: + p = "YZX"; + break; + case LLQuaternion::ZXY: + p = "ZXY"; + break; + case LLQuaternion::XZY: + p = "XZY"; + break; + case LLQuaternion::YXZ: + p = "YXZ"; + break; + case LLQuaternion::ZYX: + p = "ZYX"; + break; + } + return p; +} + +LLQuaternion::Order StringToOrder( const char *str ) +{ + if (strncmp(str, "XYZ", 3)==0 || strncmp(str, "xyz", 3)==0) + return LLQuaternion::XYZ; + + if (strncmp(str, "YZX", 3)==0 || strncmp(str, "yzx", 3)==0) + return LLQuaternion::YZX; + + if (strncmp(str, "ZXY", 3)==0 || strncmp(str, "zxy", 3)==0) + return LLQuaternion::ZXY; + + if (strncmp(str, "XZY", 3)==0 || strncmp(str, "xzy", 3)==0) + return LLQuaternion::XZY; + + if (strncmp(str, "YXZ", 3)==0 || strncmp(str, "yxz", 3)==0) + return LLQuaternion::YXZ; + + if (strncmp(str, "ZYX", 3)==0 || strncmp(str, "zyx", 3)==0) + return LLQuaternion::ZYX; + + return LLQuaternion::XYZ; +} + +void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const +{ + F32 cos_a = mQ[VW]; + if (cos_a > 1.0f) cos_a = 1.0f; + if (cos_a < -1.0f) cos_a = -1.0f; + + F32 sin_a = (F32) sqrt( 1.0f - cos_a * cos_a ); + + if ( fabs( sin_a ) < 0.0005f ) + sin_a = 1.0f; + else + sin_a = 1.f/sin_a; + + F32 temp_angle = 2.0f * (F32) acos( cos_a ); + if (temp_angle > F_PI) + { + // The (angle,axis) pair should never have angles outside [PI, -PI] + // since we want the _shortest_ (angle,axis) solution. + // Since acos is defined for [0, PI], and we multiply by 2.0, we + // can push the angle outside the acceptible range. + // When this happens we set the angle to the other portion of a + // full 2PI rotation, and negate the axis, which reverses the + // direction of the rotation (by the right-hand rule). + *angle = 2.f * F_PI - temp_angle; + vec.mV[VX] = - mQ[VX] * sin_a; + vec.mV[VY] = - mQ[VY] * sin_a; + vec.mV[VZ] = - mQ[VZ] * sin_a; + } + else + { + *angle = temp_angle; + vec.mV[VX] = mQ[VX] * sin_a; + vec.mV[VY] = mQ[VY] * sin_a; + vec.mV[VZ] = mQ[VZ] * sin_a; + } +} + + +// quaternion does not need to be normalized +void LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const +{ + LLMatrix3 rot_mat(*this); + rot_mat.orthogonalize(); + rot_mat.getEulerAngles(roll, pitch, yaw); + +// // NOTE: LLQuaternion's are actually inverted with respect to +// // the matrices, so this code also assumes inverted quaternions +// // (-x, -y, -z, w). The result is that roll,pitch,yaw are applied +// // in reverse order (yaw,pitch,roll). +// F32 x = -mQ[VX], y = -mQ[VY], z = -mQ[VZ], w = mQ[VW]; +// F64 m20 = 2.0*(x*z-y*w); +// if (1.0f - fabsf(m20) < F_APPROXIMATELY_ZERO) +// { +// *roll = 0.0f; +// *pitch = (F32)asin(m20); +// *yaw = (F32)atan2(2.0*(x*y-z*w), 1.0 - 2.0*(x*x+z*z)); +// } +// else +// { +// *roll = (F32)atan2(-2.0*(y*z+x*w), 1.0-2.0*(x*x+y*y)); +// *pitch = (F32)asin(m20); +// *yaw = (F32)atan2(-2.0*(x*y+z*w), 1.0-2.0*(y*y+z*z)); +// } +} + +// Saves space by using the fact that our quaternions are normalized +LLVector3 LLQuaternion::packToVector3() const +{ + if( mQ[VW] >= 0 ) + { + return LLVector3( mQ[VX], mQ[VY], mQ[VZ] ); + } + else + { + return LLVector3( -mQ[VX], -mQ[VY], -mQ[VZ] ); + } +} + +// Saves space by using the fact that our quaternions are normalized +void LLQuaternion::unpackFromVector3( const LLVector3& vec ) +{ + mQ[VX] = vec.mV[VX]; + mQ[VY] = vec.mV[VY]; + mQ[VZ] = vec.mV[VZ]; + F32 t = 1.f - vec.magVecSquared(); + if( t > 0 ) + { + mQ[VW] = sqrt( t ); + } + else + { + // Need this to avoid trying to find the square root of a negative number due + // to floating point error. + mQ[VW] = 0; + } +} + +BOOL LLQuaternion::parseQuat(const std::string& buf, LLQuaternion* value) +{ + if( buf.empty() || value == NULL) + { + return FALSE; + } + + LLQuaternion quat; + S32 count = sscanf( buf.c_str(), "%f %f %f %f", quat.mQ + 0, quat.mQ + 1, quat.mQ + 2, quat.mQ + 3 ); + if( 4 == count ) + { + value->set( quat ); + return TRUE; + } + + return FALSE; +} + + +// End diff --git a/indra/llmath/llquaternion.h b/indra/llmath/llquaternion.h index 0769f29f23..bbd4326483 100644 --- a/indra/llmath/llquaternion.h +++ b/indra/llmath/llquaternion.h @@ -1,590 +1,594 @@ -/** - * @file llquaternion.h - * @brief LLQuaternion class header file. - * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LLQUATERNION_H -#define LLQUATERNION_H - -#include "llmath.h" - -class LLVector4; -class LLVector3; -class LLVector3d; -class LLMatrix4; -class LLMatrix3; - -// NOTA BENE: Quaternion code is written assuming Unit Quaternions!!!! -// Moreover, it is written assuming that all vectors and matricies -// passed as arguments are normalized and unitary respectively. -// VERY VERY VERY VERY BAD THINGS will happen if these assumptions fail. - -static const U32 LENGTHOFQUAT = 4; - -class LLQuaternion -{ -public: - F32 mQ[LENGTHOFQUAT]; - - static const LLQuaternion DEFAULT; - - LLQuaternion(); // Initializes Quaternion to (0,0,0,1) - explicit LLQuaternion(const LLMatrix4 &mat); // Initializes Quaternion from Matrix4 - explicit LLQuaternion(const LLMatrix3 &mat); // Initializes Quaternion from Matrix3 - LLQuaternion(F32 x, F32 y, F32 z, F32 w); // Initializes Quaternion to normalize(x, y, z, w) - LLQuaternion(F32 angle, const LLVector4 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec) - LLQuaternion(F32 angle, const LLVector3 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec) - LLQuaternion(const F32 *q); // Initializes Quaternion to normalize(x, y, z, w) - LLQuaternion(const LLVector3 &x_axis, - const LLVector3 &y_axis, - const LLVector3 &z_axis); // Initializes Quaternion from Matrix3 = [x_axis ; y_axis ; z_axis] - - BOOL isIdentity() const; - BOOL isNotIdentity() const; - BOOL isFinite() const; // checks to see if all values of LLQuaternion are finite - void quantize16(F32 lower, F32 upper); // changes the vector to reflect quatization - void quantize8(F32 lower, F32 upper); // changes the vector to reflect quatization - void loadIdentity(); // Loads the quaternion that represents the identity rotation - - const LLQuaternion& set(F32 x, F32 y, F32 z, F32 w); // Sets Quaternion to normalize(x, y, z, w) - const LLQuaternion& set(const LLQuaternion &quat); // Copies Quaternion - const LLQuaternion& set(const F32 *q); // Sets Quaternion to normalize(quat[VX], quat[VY], quat[VZ], quat[VW]) - const LLQuaternion& set(const LLMatrix3 &mat); // Sets Quaternion to mat2quat(mat) - const LLQuaternion& set(const LLMatrix4 &mat); // Sets Quaternion to mat2quat(mat) - - const LLQuaternion& setAngleAxis(F32 angle, F32 x, F32 y, F32 z); // Sets Quaternion to axis_angle2quat(angle, x, y, z) - const LLQuaternion& setAngleAxis(F32 angle, const LLVector3 &vec); // Sets Quaternion to axis_angle2quat(angle, vec) - const LLQuaternion& setAngleAxis(F32 angle, const LLVector4 &vec); // Sets Quaternion to axis_angle2quat(angle, vec) - const LLQuaternion& setEulerAngles(F32 roll, F32 pitch, F32 yaw); // Sets Quaternion to euler2quat(pitch, yaw, roll) - - const LLQuaternion& setQuatInit(F32 x, F32 y, F32 z, F32 w); // deprecated - const LLQuaternion& setQuat(const LLQuaternion &quat); // deprecated - const LLQuaternion& setQuat(const F32 *q); // deprecated - const LLQuaternion& setQuat(const LLMatrix3 &mat); // deprecated - const LLQuaternion& setQuat(const LLMatrix4 &mat); // deprecated - const LLQuaternion& setQuat(F32 angle, F32 x, F32 y, F32 z); // deprecated - const LLQuaternion& setQuat(F32 angle, const LLVector3 &vec); // deprecated - const LLQuaternion& setQuat(F32 angle, const LLVector4 &vec); // deprecated - const LLQuaternion& setQuat(F32 roll, F32 pitch, F32 yaw); // deprecated - - LLMatrix4 getMatrix4(void) const; // Returns the Matrix4 equivalent of Quaternion - LLMatrix3 getMatrix3(void) const; // Returns the Matrix3 equivalent of Quaternion - void getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const; // returns rotation in radians about axis x,y,z - void getAngleAxis(F32* angle, LLVector3 &vec) const; - void getEulerAngles(F32 *roll, F32* pitch, F32 *yaw) const; - - F32 normalize(); // Normalizes Quaternion and returns magnitude - F32 normQuat(); // deprecated - - const LLQuaternion& conjugate(void); // Conjugates Quaternion and returns result - const LLQuaternion& conjQuat(void); // deprecated - - // Other useful methods - const LLQuaternion& transpose(); // transpose (same as conjugate) - const LLQuaternion& transQuat(); // deprecated - - void shortestArc(const LLVector3 &a, const LLVector3 &b); // shortest rotation from a to b - const LLQuaternion& constrain(F32 radians); // constrains rotation to a cone angle specified in radians - - // Standard operators - friend std::ostream& operator<<(std::ostream &s, const LLQuaternion &a); // Prints a - friend LLQuaternion operator+(const LLQuaternion &a, const LLQuaternion &b); // Addition - friend LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b); // Subtraction - friend LLQuaternion operator-(const LLQuaternion &a); // Negation - friend LLQuaternion operator*(F32 a, const LLQuaternion &q); // Scale - friend LLQuaternion operator*(const LLQuaternion &q, F32 b); // Scale - friend LLQuaternion operator*(const LLQuaternion &a, const LLQuaternion &b); // Returns a * b - friend LLQuaternion operator~(const LLQuaternion &a); // Returns a* (Conjugate of a) - bool operator==(const LLQuaternion &b) const; // Returns a == b - bool operator!=(const LLQuaternion &b) const; // Returns a != b - - friend const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b); // Returns a * b - - friend LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot); // Rotates a by rot - friend LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot); // Rotates a by rot - friend LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot); // Rotates a by rot - - // Non-standard operators - friend F32 dot(const LLQuaternion &a, const LLQuaternion &b); - friend LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q); // linear interpolation (t = 0 to 1) from p to q - friend LLQuaternion lerp(F32 t, const LLQuaternion &q); // linear interpolation (t = 0 to 1) from identity to q - friend LLQuaternion slerp(F32 t, const LLQuaternion &p, const LLQuaternion &q); // spherical linear interpolation from p to q - friend LLQuaternion slerp(F32 t, const LLQuaternion &q); // spherical linear interpolation from identity to q - friend LLQuaternion nlerp(F32 t, const LLQuaternion &p, const LLQuaternion &q); // normalized linear interpolation from p to q - friend LLQuaternion nlerp(F32 t, const LLQuaternion &q); // normalized linear interpolation from p to q - - LLVector3 packToVector3() const; // Saves space by using the fact that our quaternions are normalized - void unpackFromVector3(const LLVector3& vec); // Saves space by using the fact that our quaternions are normalized - - enum Order { - XYZ = 0, - YZX = 1, - ZXY = 2, - XZY = 3, - YXZ = 4, - ZYX = 5 - }; - // Creates a quaternions from maya's rotation representation, - // which is 3 rotations (in DEGREES) in the specified order - friend LLQuaternion mayaQ(F32 x, F32 y, F32 z, Order order); - - // Conversions between Order and strings like "xyz" or "ZYX" - friend const char *OrderToString( const Order order ); - friend Order StringToOrder( const char *str ); - - static BOOL parseQuat(const std::string& buf, LLQuaternion* value); - - // For debugging, only - //static U32 mMultCount; -}; - -// checker -inline BOOL LLQuaternion::isFinite() const -{ - return (llfinite(mQ[VX]) && llfinite(mQ[VY]) && llfinite(mQ[VZ]) && llfinite(mQ[VS])); -} - -inline BOOL LLQuaternion::isIdentity() const -{ - return - ( mQ[VX] == 0.f ) && - ( mQ[VY] == 0.f ) && - ( mQ[VZ] == 0.f ) && - ( mQ[VS] == 1.f ); -} - -inline BOOL LLQuaternion::isNotIdentity() const -{ - return - ( mQ[VX] != 0.f ) || - ( mQ[VY] != 0.f ) || - ( mQ[VZ] != 0.f ) || - ( mQ[VS] != 1.f ); -} - - - -inline LLQuaternion::LLQuaternion(void) -{ - mQ[VX] = 0.f; - mQ[VY] = 0.f; - mQ[VZ] = 0.f; - mQ[VS] = 1.f; -} - -inline LLQuaternion::LLQuaternion(F32 x, F32 y, F32 z, F32 w) -{ - mQ[VX] = x; - mQ[VY] = y; - mQ[VZ] = z; - mQ[VS] = w; - - //RN: don't normalize this case as its used mainly for temporaries during calculations - //normalize(); - /* - F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); - mag -= 1.f; - mag = fabs(mag); - llassert(mag < 10.f*FP_MAG_THRESHOLD); - */ -} - -inline LLQuaternion::LLQuaternion(const F32 *q) -{ - mQ[VX] = q[VX]; - mQ[VY] = q[VY]; - mQ[VZ] = q[VZ]; - mQ[VS] = q[VW]; - - normalize(); - /* - F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); - mag -= 1.f; - mag = fabs(mag); - llassert(mag < FP_MAG_THRESHOLD); - */ -} - - -inline void LLQuaternion::loadIdentity() -{ - mQ[VX] = 0.0f; - mQ[VY] = 0.0f; - mQ[VZ] = 0.0f; - mQ[VW] = 1.0f; -} - - -inline const LLQuaternion& LLQuaternion::set(F32 x, F32 y, F32 z, F32 w) -{ - mQ[VX] = x; - mQ[VY] = y; - mQ[VZ] = z; - mQ[VS] = w; - normalize(); - return (*this); -} - -inline const LLQuaternion& LLQuaternion::set(const LLQuaternion &quat) -{ - mQ[VX] = quat.mQ[VX]; - mQ[VY] = quat.mQ[VY]; - mQ[VZ] = quat.mQ[VZ]; - mQ[VW] = quat.mQ[VW]; - normalize(); - return (*this); -} - -inline const LLQuaternion& LLQuaternion::set(const F32 *q) -{ - mQ[VX] = q[VX]; - mQ[VY] = q[VY]; - mQ[VZ] = q[VZ]; - mQ[VS] = q[VW]; - normalize(); - return (*this); -} - - -// deprecated -inline const LLQuaternion& LLQuaternion::setQuatInit(F32 x, F32 y, F32 z, F32 w) -{ - mQ[VX] = x; - mQ[VY] = y; - mQ[VZ] = z; - mQ[VS] = w; - normalize(); - return (*this); -} - -// deprecated -inline const LLQuaternion& LLQuaternion::setQuat(const LLQuaternion &quat) -{ - mQ[VX] = quat.mQ[VX]; - mQ[VY] = quat.mQ[VY]; - mQ[VZ] = quat.mQ[VZ]; - mQ[VW] = quat.mQ[VW]; - normalize(); - return (*this); -} - -// deprecated -inline const LLQuaternion& LLQuaternion::setQuat(const F32 *q) -{ - mQ[VX] = q[VX]; - mQ[VY] = q[VY]; - mQ[VZ] = q[VZ]; - mQ[VS] = q[VW]; - normalize(); - return (*this); -} - -// There may be a cheaper way that avoids the sqrt. -// Does sin_a = VX*VX + VY*VY + VZ*VZ? -// Copied from Matrix and Quaternion FAQ 1.12 -inline void LLQuaternion::getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const -{ - F32 cos_a = mQ[VW]; - if (cos_a > 1.0f) cos_a = 1.0f; - if (cos_a < -1.0f) cos_a = -1.0f; - - F32 sin_a = (F32) sqrt( 1.0f - cos_a * cos_a ); - - if ( fabs( sin_a ) < 0.0005f ) - sin_a = 1.0f; - else - sin_a = 1.f/sin_a; - - F32 temp_angle = 2.0f * (F32) acos( cos_a ); - if (temp_angle > F_PI) - { - // The (angle,axis) pair should never have angles outside [PI, -PI] - // since we want the _shortest_ (angle,axis) solution. - // Since acos is defined for [0, PI], and we multiply by 2.0, we - // can push the angle outside the acceptible range. - // When this happens we set the angle to the other portion of a - // full 2PI rotation, and negate the axis, which reverses the - // direction of the rotation (by the right-hand rule). - *angle = 2.f * F_PI - temp_angle; - *x = - mQ[VX] * sin_a; - *y = - mQ[VY] * sin_a; - *z = - mQ[VZ] * sin_a; - } - else - { - *angle = temp_angle; - *x = mQ[VX] * sin_a; - *y = mQ[VY] * sin_a; - *z = mQ[VZ] * sin_a; - } -} - -inline const LLQuaternion& LLQuaternion::conjugate() -{ - mQ[VX] *= -1.f; - mQ[VY] *= -1.f; - mQ[VZ] *= -1.f; - return (*this); -} - -inline const LLQuaternion& LLQuaternion::conjQuat() -{ - mQ[VX] *= -1.f; - mQ[VY] *= -1.f; - mQ[VZ] *= -1.f; - return (*this); -} - -// Transpose -inline const LLQuaternion& LLQuaternion::transpose() -{ - mQ[VX] *= -1.f; - mQ[VY] *= -1.f; - mQ[VZ] *= -1.f; - return (*this); -} - -// deprecated -inline const LLQuaternion& LLQuaternion::transQuat() -{ - mQ[VX] *= -1.f; - mQ[VY] *= -1.f; - mQ[VZ] *= -1.f; - return (*this); -} - - -inline LLQuaternion operator+(const LLQuaternion &a, const LLQuaternion &b) -{ - return LLQuaternion( - a.mQ[VX] + b.mQ[VX], - a.mQ[VY] + b.mQ[VY], - a.mQ[VZ] + b.mQ[VZ], - a.mQ[VW] + b.mQ[VW] ); -} - - -inline LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) -{ - return LLQuaternion( - a.mQ[VX] - b.mQ[VX], - a.mQ[VY] - b.mQ[VY], - a.mQ[VZ] - b.mQ[VZ], - a.mQ[VW] - b.mQ[VW] ); -} - - -inline LLQuaternion operator-(const LLQuaternion &a) -{ - return LLQuaternion( - -a.mQ[VX], - -a.mQ[VY], - -a.mQ[VZ], - -a.mQ[VW] ); -} - - -inline LLQuaternion operator*(F32 a, const LLQuaternion &q) -{ - return LLQuaternion( - a * q.mQ[VX], - a * q.mQ[VY], - a * q.mQ[VZ], - a * q.mQ[VW] ); -} - - -inline LLQuaternion operator*(const LLQuaternion &q, F32 a) -{ - return LLQuaternion( - a * q.mQ[VX], - a * q.mQ[VY], - a * q.mQ[VZ], - a * q.mQ[VW] ); -} - -inline LLQuaternion operator~(const LLQuaternion &a) -{ - LLQuaternion q(a); - q.conjQuat(); - return q; -} - -inline bool LLQuaternion::operator==(const LLQuaternion &b) const -{ - return ( (mQ[VX] == b.mQ[VX]) - &&(mQ[VY] == b.mQ[VY]) - &&(mQ[VZ] == b.mQ[VZ]) - &&(mQ[VS] == b.mQ[VS])); -} - -inline bool LLQuaternion::operator!=(const LLQuaternion &b) const -{ - return ( (mQ[VX] != b.mQ[VX]) - ||(mQ[VY] != b.mQ[VY]) - ||(mQ[VZ] != b.mQ[VZ]) - ||(mQ[VS] != b.mQ[VS])); -} - -inline const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b) -{ -#if 1 - LLQuaternion q( - b.mQ[3] * a.mQ[0] + b.mQ[0] * a.mQ[3] + b.mQ[1] * a.mQ[2] - b.mQ[2] * a.mQ[1], - b.mQ[3] * a.mQ[1] + b.mQ[1] * a.mQ[3] + b.mQ[2] * a.mQ[0] - b.mQ[0] * a.mQ[2], - b.mQ[3] * a.mQ[2] + b.mQ[2] * a.mQ[3] + b.mQ[0] * a.mQ[1] - b.mQ[1] * a.mQ[0], - b.mQ[3] * a.mQ[3] - b.mQ[0] * a.mQ[0] - b.mQ[1] * a.mQ[1] - b.mQ[2] * a.mQ[2] - ); - a = q; -#else - a = a * b; -#endif - return a; -} - -const F32 ONE_PART_IN_A_MILLION = 0.000001f; - -inline F32 LLQuaternion::normalize() -{ - F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); - - if (mag > FP_MAG_THRESHOLD) - { - // Floating point error can prevent some quaternions from achieving - // exact unity length. When trying to renormalize such quaternions we - // can oscillate between multiple quantized states. To prevent such - // drifts we only renomalize if the length is far enough from unity. - if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION) - { - F32 oomag = 1.f/mag; - mQ[VX] *= oomag; - mQ[VY] *= oomag; - mQ[VZ] *= oomag; - mQ[VS] *= oomag; - } - } - else - { - // we were given a very bad quaternion so we set it to identity - mQ[VX] = 0.f; - mQ[VY] = 0.f; - mQ[VZ] = 0.f; - mQ[VS] = 1.f; - } - - return mag; -} - -// deprecated -inline F32 LLQuaternion::normQuat() -{ - F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); - - if (mag > FP_MAG_THRESHOLD) - { - if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION) - { - // only renormalize if length not close enough to 1.0 already - F32 oomag = 1.f/mag; - mQ[VX] *= oomag; - mQ[VY] *= oomag; - mQ[VZ] *= oomag; - mQ[VS] *= oomag; - } - } - else - { - mQ[VX] = 0.f; - mQ[VY] = 0.f; - mQ[VZ] = 0.f; - mQ[VS] = 1.f; - } - - return mag; -} - -LLQuaternion::Order StringToOrder( const char *str ); - -// Some notes about Quaternions - -// What is a Quaternion? -// --------------------- -// A quaternion is a point in 4-dimensional complex space. -// Q = { Qx, Qy, Qz, Qw } -// -// -// Why Quaternions? -// ---------------- -// The set of quaternions that make up the the 4-D unit sphere -// can be mapped to the set of all rotations in 3-D space. Sometimes -// it is easier to describe/manipulate rotations in quaternion space -// than rotation-matrix space. -// -// -// How Quaternions? -// ---------------- -// In order to take advantage of quaternions we need to know how to -// go from rotation-matricies to quaternions and back. We also have -// to agree what variety of rotations we're generating. -// -// Consider the equation... v' = v * R -// -// There are two ways to think about rotations of vectors. -// 1) v' is the same vector in a different reference frame -// 2) v' is a new vector in the same reference frame -// -// bookmark -- which way are we using? -// -// -// Quaternion from Angle-Axis: -// --------------------------- -// Suppose we wanted to represent a rotation of some angle (theta) -// about some axis ({Ax, Ay, Az})... -// -// axis of rotation = {Ax, Ay, Az} -// angle_of_rotation = theta -// -// s = sin(0.5 * theta) -// c = cos(0.5 * theta) -// Q = { s * Ax, s * Ay, s * Az, c } -// -// -// 3x3 Matrix from Quaternion -// -------------------------- -// -// | | -// | 1 - 2 * (y^2 + z^2) 2 * (x * y + z * w) 2 * (y * w - x * z) | -// | | -// M = | 2 * (x * y - z * w) 1 - 2 * (x^2 + z^2) 2 * (y * z + x * w) | -// | | -// | 2 * (x * z + y * w) 2 * (y * z - x * w) 1 - 2 * (x^2 + y^2) | -// | | - -#endif +/** + * @file llquaternion.h + * @brief LLQuaternion class header file. + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LLQUATERNION_H +#define LLQUATERNION_H + +#include + +#ifndef LLMATH_H //enforce specific include order to avoid tangling inline dependencies +#error "Please include llmath.h first." +#endif + +class LLVector4; +class LLVector3; +class LLVector3d; +class LLMatrix4; +class LLMatrix3; + +// NOTA BENE: Quaternion code is written assuming Unit Quaternions!!!! +// Moreover, it is written assuming that all vectors and matricies +// passed as arguments are normalized and unitary respectively. +// VERY VERY VERY VERY BAD THINGS will happen if these assumptions fail. + +static const U32 LENGTHOFQUAT = 4; + +class LLQuaternion +{ +public: + F32 mQ[LENGTHOFQUAT]; + + static const LLQuaternion DEFAULT; + + LLQuaternion(); // Initializes Quaternion to (0,0,0,1) + explicit LLQuaternion(const LLMatrix4 &mat); // Initializes Quaternion from Matrix4 + explicit LLQuaternion(const LLMatrix3 &mat); // Initializes Quaternion from Matrix3 + LLQuaternion(F32 x, F32 y, F32 z, F32 w); // Initializes Quaternion to normalize(x, y, z, w) + LLQuaternion(F32 angle, const LLVector4 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec) + LLQuaternion(F32 angle, const LLVector3 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec) + LLQuaternion(const F32 *q); // Initializes Quaternion to normalize(x, y, z, w) + LLQuaternion(const LLVector3 &x_axis, + const LLVector3 &y_axis, + const LLVector3 &z_axis); // Initializes Quaternion from Matrix3 = [x_axis ; y_axis ; z_axis] + + BOOL isIdentity() const; + BOOL isNotIdentity() const; + BOOL isFinite() const; // checks to see if all values of LLQuaternion are finite + void quantize16(F32 lower, F32 upper); // changes the vector to reflect quatization + void quantize8(F32 lower, F32 upper); // changes the vector to reflect quatization + void loadIdentity(); // Loads the quaternion that represents the identity rotation + + const LLQuaternion& set(F32 x, F32 y, F32 z, F32 w); // Sets Quaternion to normalize(x, y, z, w) + const LLQuaternion& set(const LLQuaternion &quat); // Copies Quaternion + const LLQuaternion& set(const F32 *q); // Sets Quaternion to normalize(quat[VX], quat[VY], quat[VZ], quat[VW]) + const LLQuaternion& set(const LLMatrix3 &mat); // Sets Quaternion to mat2quat(mat) + const LLQuaternion& set(const LLMatrix4 &mat); // Sets Quaternion to mat2quat(mat) + + const LLQuaternion& setAngleAxis(F32 angle, F32 x, F32 y, F32 z); // Sets Quaternion to axis_angle2quat(angle, x, y, z) + const LLQuaternion& setAngleAxis(F32 angle, const LLVector3 &vec); // Sets Quaternion to axis_angle2quat(angle, vec) + const LLQuaternion& setAngleAxis(F32 angle, const LLVector4 &vec); // Sets Quaternion to axis_angle2quat(angle, vec) + const LLQuaternion& setEulerAngles(F32 roll, F32 pitch, F32 yaw); // Sets Quaternion to euler2quat(pitch, yaw, roll) + + const LLQuaternion& setQuatInit(F32 x, F32 y, F32 z, F32 w); // deprecated + const LLQuaternion& setQuat(const LLQuaternion &quat); // deprecated + const LLQuaternion& setQuat(const F32 *q); // deprecated + const LLQuaternion& setQuat(const LLMatrix3 &mat); // deprecated + const LLQuaternion& setQuat(const LLMatrix4 &mat); // deprecated + const LLQuaternion& setQuat(F32 angle, F32 x, F32 y, F32 z); // deprecated + const LLQuaternion& setQuat(F32 angle, const LLVector3 &vec); // deprecated + const LLQuaternion& setQuat(F32 angle, const LLVector4 &vec); // deprecated + const LLQuaternion& setQuat(F32 roll, F32 pitch, F32 yaw); // deprecated + + LLMatrix4 getMatrix4(void) const; // Returns the Matrix4 equivalent of Quaternion + LLMatrix3 getMatrix3(void) const; // Returns the Matrix3 equivalent of Quaternion + void getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const; // returns rotation in radians about axis x,y,z + void getAngleAxis(F32* angle, LLVector3 &vec) const; + void getEulerAngles(F32 *roll, F32* pitch, F32 *yaw) const; + + F32 normalize(); // Normalizes Quaternion and returns magnitude + F32 normQuat(); // deprecated + + const LLQuaternion& conjugate(void); // Conjugates Quaternion and returns result + const LLQuaternion& conjQuat(void); // deprecated + + // Other useful methods + const LLQuaternion& transpose(); // transpose (same as conjugate) + const LLQuaternion& transQuat(); // deprecated + + void shortestArc(const LLVector3 &a, const LLVector3 &b); // shortest rotation from a to b + const LLQuaternion& constrain(F32 radians); // constrains rotation to a cone angle specified in radians + + // Standard operators + friend std::ostream& operator<<(std::ostream &s, const LLQuaternion &a); // Prints a + friend LLQuaternion operator+(const LLQuaternion &a, const LLQuaternion &b); // Addition + friend LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b); // Subtraction + friend LLQuaternion operator-(const LLQuaternion &a); // Negation + friend LLQuaternion operator*(F32 a, const LLQuaternion &q); // Scale + friend LLQuaternion operator*(const LLQuaternion &q, F32 b); // Scale + friend LLQuaternion operator*(const LLQuaternion &a, const LLQuaternion &b); // Returns a * b + friend LLQuaternion operator~(const LLQuaternion &a); // Returns a* (Conjugate of a) + bool operator==(const LLQuaternion &b) const; // Returns a == b + bool operator!=(const LLQuaternion &b) const; // Returns a != b + + friend const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b); // Returns a * b + + friend LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot); // Rotates a by rot + friend LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot); // Rotates a by rot + friend LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot); // Rotates a by rot + + // Non-standard operators + friend F32 dot(const LLQuaternion &a, const LLQuaternion &b); + friend LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q); // linear interpolation (t = 0 to 1) from p to q + friend LLQuaternion lerp(F32 t, const LLQuaternion &q); // linear interpolation (t = 0 to 1) from identity to q + friend LLQuaternion slerp(F32 t, const LLQuaternion &p, const LLQuaternion &q); // spherical linear interpolation from p to q + friend LLQuaternion slerp(F32 t, const LLQuaternion &q); // spherical linear interpolation from identity to q + friend LLQuaternion nlerp(F32 t, const LLQuaternion &p, const LLQuaternion &q); // normalized linear interpolation from p to q + friend LLQuaternion nlerp(F32 t, const LLQuaternion &q); // normalized linear interpolation from p to q + + LLVector3 packToVector3() const; // Saves space by using the fact that our quaternions are normalized + void unpackFromVector3(const LLVector3& vec); // Saves space by using the fact that our quaternions are normalized + + enum Order { + XYZ = 0, + YZX = 1, + ZXY = 2, + XZY = 3, + YXZ = 4, + ZYX = 5 + }; + // Creates a quaternions from maya's rotation representation, + // which is 3 rotations (in DEGREES) in the specified order + friend LLQuaternion mayaQ(F32 x, F32 y, F32 z, Order order); + + // Conversions between Order and strings like "xyz" or "ZYX" + friend const char *OrderToString( const Order order ); + friend Order StringToOrder( const char *str ); + + static BOOL parseQuat(const std::string& buf, LLQuaternion* value); + + // For debugging, only + //static U32 mMultCount; +}; + +// checker +inline BOOL LLQuaternion::isFinite() const +{ + return (llfinite(mQ[VX]) && llfinite(mQ[VY]) && llfinite(mQ[VZ]) && llfinite(mQ[VS])); +} + +inline BOOL LLQuaternion::isIdentity() const +{ + return + ( mQ[VX] == 0.f ) && + ( mQ[VY] == 0.f ) && + ( mQ[VZ] == 0.f ) && + ( mQ[VS] == 1.f ); +} + +inline BOOL LLQuaternion::isNotIdentity() const +{ + return + ( mQ[VX] != 0.f ) || + ( mQ[VY] != 0.f ) || + ( mQ[VZ] != 0.f ) || + ( mQ[VS] != 1.f ); +} + + + +inline LLQuaternion::LLQuaternion(void) +{ + mQ[VX] = 0.f; + mQ[VY] = 0.f; + mQ[VZ] = 0.f; + mQ[VS] = 1.f; +} + +inline LLQuaternion::LLQuaternion(F32 x, F32 y, F32 z, F32 w) +{ + mQ[VX] = x; + mQ[VY] = y; + mQ[VZ] = z; + mQ[VS] = w; + + //RN: don't normalize this case as its used mainly for temporaries during calculations + //normalize(); + /* + F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); + mag -= 1.f; + mag = fabs(mag); + llassert(mag < 10.f*FP_MAG_THRESHOLD); + */ +} + +inline LLQuaternion::LLQuaternion(const F32 *q) +{ + mQ[VX] = q[VX]; + mQ[VY] = q[VY]; + mQ[VZ] = q[VZ]; + mQ[VS] = q[VW]; + + normalize(); + /* + F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); + mag -= 1.f; + mag = fabs(mag); + llassert(mag < FP_MAG_THRESHOLD); + */ +} + + +inline void LLQuaternion::loadIdentity() +{ + mQ[VX] = 0.0f; + mQ[VY] = 0.0f; + mQ[VZ] = 0.0f; + mQ[VW] = 1.0f; +} + + +inline const LLQuaternion& LLQuaternion::set(F32 x, F32 y, F32 z, F32 w) +{ + mQ[VX] = x; + mQ[VY] = y; + mQ[VZ] = z; + mQ[VS] = w; + normalize(); + return (*this); +} + +inline const LLQuaternion& LLQuaternion::set(const LLQuaternion &quat) +{ + mQ[VX] = quat.mQ[VX]; + mQ[VY] = quat.mQ[VY]; + mQ[VZ] = quat.mQ[VZ]; + mQ[VW] = quat.mQ[VW]; + normalize(); + return (*this); +} + +inline const LLQuaternion& LLQuaternion::set(const F32 *q) +{ + mQ[VX] = q[VX]; + mQ[VY] = q[VY]; + mQ[VZ] = q[VZ]; + mQ[VS] = q[VW]; + normalize(); + return (*this); +} + + +// deprecated +inline const LLQuaternion& LLQuaternion::setQuatInit(F32 x, F32 y, F32 z, F32 w) +{ + mQ[VX] = x; + mQ[VY] = y; + mQ[VZ] = z; + mQ[VS] = w; + normalize(); + return (*this); +} + +// deprecated +inline const LLQuaternion& LLQuaternion::setQuat(const LLQuaternion &quat) +{ + mQ[VX] = quat.mQ[VX]; + mQ[VY] = quat.mQ[VY]; + mQ[VZ] = quat.mQ[VZ]; + mQ[VW] = quat.mQ[VW]; + normalize(); + return (*this); +} + +// deprecated +inline const LLQuaternion& LLQuaternion::setQuat(const F32 *q) +{ + mQ[VX] = q[VX]; + mQ[VY] = q[VY]; + mQ[VZ] = q[VZ]; + mQ[VS] = q[VW]; + normalize(); + return (*this); +} + +// There may be a cheaper way that avoids the sqrt. +// Does sin_a = VX*VX + VY*VY + VZ*VZ? +// Copied from Matrix and Quaternion FAQ 1.12 +inline void LLQuaternion::getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const +{ + F32 cos_a = mQ[VW]; + if (cos_a > 1.0f) cos_a = 1.0f; + if (cos_a < -1.0f) cos_a = -1.0f; + + F32 sin_a = (F32) sqrt( 1.0f - cos_a * cos_a ); + + if ( fabs( sin_a ) < 0.0005f ) + sin_a = 1.0f; + else + sin_a = 1.f/sin_a; + + F32 temp_angle = 2.0f * (F32) acos( cos_a ); + if (temp_angle > F_PI) + { + // The (angle,axis) pair should never have angles outside [PI, -PI] + // since we want the _shortest_ (angle,axis) solution. + // Since acos is defined for [0, PI], and we multiply by 2.0, we + // can push the angle outside the acceptible range. + // When this happens we set the angle to the other portion of a + // full 2PI rotation, and negate the axis, which reverses the + // direction of the rotation (by the right-hand rule). + *angle = 2.f * F_PI - temp_angle; + *x = - mQ[VX] * sin_a; + *y = - mQ[VY] * sin_a; + *z = - mQ[VZ] * sin_a; + } + else + { + *angle = temp_angle; + *x = mQ[VX] * sin_a; + *y = mQ[VY] * sin_a; + *z = mQ[VZ] * sin_a; + } +} + +inline const LLQuaternion& LLQuaternion::conjugate() +{ + mQ[VX] *= -1.f; + mQ[VY] *= -1.f; + mQ[VZ] *= -1.f; + return (*this); +} + +inline const LLQuaternion& LLQuaternion::conjQuat() +{ + mQ[VX] *= -1.f; + mQ[VY] *= -1.f; + mQ[VZ] *= -1.f; + return (*this); +} + +// Transpose +inline const LLQuaternion& LLQuaternion::transpose() +{ + mQ[VX] *= -1.f; + mQ[VY] *= -1.f; + mQ[VZ] *= -1.f; + return (*this); +} + +// deprecated +inline const LLQuaternion& LLQuaternion::transQuat() +{ + mQ[VX] *= -1.f; + mQ[VY] *= -1.f; + mQ[VZ] *= -1.f; + return (*this); +} + + +inline LLQuaternion operator+(const LLQuaternion &a, const LLQuaternion &b) +{ + return LLQuaternion( + a.mQ[VX] + b.mQ[VX], + a.mQ[VY] + b.mQ[VY], + a.mQ[VZ] + b.mQ[VZ], + a.mQ[VW] + b.mQ[VW] ); +} + + +inline LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) +{ + return LLQuaternion( + a.mQ[VX] - b.mQ[VX], + a.mQ[VY] - b.mQ[VY], + a.mQ[VZ] - b.mQ[VZ], + a.mQ[VW] - b.mQ[VW] ); +} + + +inline LLQuaternion operator-(const LLQuaternion &a) +{ + return LLQuaternion( + -a.mQ[VX], + -a.mQ[VY], + -a.mQ[VZ], + -a.mQ[VW] ); +} + + +inline LLQuaternion operator*(F32 a, const LLQuaternion &q) +{ + return LLQuaternion( + a * q.mQ[VX], + a * q.mQ[VY], + a * q.mQ[VZ], + a * q.mQ[VW] ); +} + + +inline LLQuaternion operator*(const LLQuaternion &q, F32 a) +{ + return LLQuaternion( + a * q.mQ[VX], + a * q.mQ[VY], + a * q.mQ[VZ], + a * q.mQ[VW] ); +} + +inline LLQuaternion operator~(const LLQuaternion &a) +{ + LLQuaternion q(a); + q.conjQuat(); + return q; +} + +inline bool LLQuaternion::operator==(const LLQuaternion &b) const +{ + return ( (mQ[VX] == b.mQ[VX]) + &&(mQ[VY] == b.mQ[VY]) + &&(mQ[VZ] == b.mQ[VZ]) + &&(mQ[VS] == b.mQ[VS])); +} + +inline bool LLQuaternion::operator!=(const LLQuaternion &b) const +{ + return ( (mQ[VX] != b.mQ[VX]) + ||(mQ[VY] != b.mQ[VY]) + ||(mQ[VZ] != b.mQ[VZ]) + ||(mQ[VS] != b.mQ[VS])); +} + +inline const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b) +{ +#if 1 + LLQuaternion q( + b.mQ[3] * a.mQ[0] + b.mQ[0] * a.mQ[3] + b.mQ[1] * a.mQ[2] - b.mQ[2] * a.mQ[1], + b.mQ[3] * a.mQ[1] + b.mQ[1] * a.mQ[3] + b.mQ[2] * a.mQ[0] - b.mQ[0] * a.mQ[2], + b.mQ[3] * a.mQ[2] + b.mQ[2] * a.mQ[3] + b.mQ[0] * a.mQ[1] - b.mQ[1] * a.mQ[0], + b.mQ[3] * a.mQ[3] - b.mQ[0] * a.mQ[0] - b.mQ[1] * a.mQ[1] - b.mQ[2] * a.mQ[2] + ); + a = q; +#else + a = a * b; +#endif + return a; +} + +const F32 ONE_PART_IN_A_MILLION = 0.000001f; + +inline F32 LLQuaternion::normalize() +{ + F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); + + if (mag > FP_MAG_THRESHOLD) + { + // Floating point error can prevent some quaternions from achieving + // exact unity length. When trying to renormalize such quaternions we + // can oscillate between multiple quantized states. To prevent such + // drifts we only renomalize if the length is far enough from unity. + if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION) + { + F32 oomag = 1.f/mag; + mQ[VX] *= oomag; + mQ[VY] *= oomag; + mQ[VZ] *= oomag; + mQ[VS] *= oomag; + } + } + else + { + // we were given a very bad quaternion so we set it to identity + mQ[VX] = 0.f; + mQ[VY] = 0.f; + mQ[VZ] = 0.f; + mQ[VS] = 1.f; + } + + return mag; +} + +// deprecated +inline F32 LLQuaternion::normQuat() +{ + F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); + + if (mag > FP_MAG_THRESHOLD) + { + if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION) + { + // only renormalize if length not close enough to 1.0 already + F32 oomag = 1.f/mag; + mQ[VX] *= oomag; + mQ[VY] *= oomag; + mQ[VZ] *= oomag; + mQ[VS] *= oomag; + } + } + else + { + mQ[VX] = 0.f; + mQ[VY] = 0.f; + mQ[VZ] = 0.f; + mQ[VS] = 1.f; + } + + return mag; +} + +LLQuaternion::Order StringToOrder( const char *str ); + +// Some notes about Quaternions + +// What is a Quaternion? +// --------------------- +// A quaternion is a point in 4-dimensional complex space. +// Q = { Qx, Qy, Qz, Qw } +// +// +// Why Quaternions? +// ---------------- +// The set of quaternions that make up the the 4-D unit sphere +// can be mapped to the set of all rotations in 3-D space. Sometimes +// it is easier to describe/manipulate rotations in quaternion space +// than rotation-matrix space. +// +// +// How Quaternions? +// ---------------- +// In order to take advantage of quaternions we need to know how to +// go from rotation-matricies to quaternions and back. We also have +// to agree what variety of rotations we're generating. +// +// Consider the equation... v' = v * R +// +// There are two ways to think about rotations of vectors. +// 1) v' is the same vector in a different reference frame +// 2) v' is a new vector in the same reference frame +// +// bookmark -- which way are we using? +// +// +// Quaternion from Angle-Axis: +// --------------------------- +// Suppose we wanted to represent a rotation of some angle (theta) +// about some axis ({Ax, Ay, Az})... +// +// axis of rotation = {Ax, Ay, Az} +// angle_of_rotation = theta +// +// s = sin(0.5 * theta) +// c = cos(0.5 * theta) +// Q = { s * Ax, s * Ay, s * Az, c } +// +// +// 3x3 Matrix from Quaternion +// -------------------------- +// +// | | +// | 1 - 2 * (y^2 + z^2) 2 * (x * y + z * w) 2 * (y * w - x * z) | +// | | +// M = | 2 * (x * y - z * w) 1 - 2 * (x^2 + z^2) 2 * (y * z + x * w) | +// | | +// | 2 * (x * z + y * w) 2 * (y * z - x * w) 1 - 2 * (x^2 + y^2) | +// | | + +#endif diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index bba0a6d089..ab9f8c4c24 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -45,7 +45,7 @@ #include "v4math.h" #include "m4math.h" #include "m3math.h" -#include "llmatrix4a.h" +#include "llmatrix3a.h" #include "lloctree.h" #include "lldarray.h" #include "llvolume.h" @@ -53,6 +53,7 @@ #include "llstl.h" #include "llsdserialize.h" #include "llvector4a.h" +#include "llmatrix4a.h" #define DEBUG_SILHOUETTE_BINORMALS 0 #define DEBUG_SILHOUETTE_NORMALS 0 // TomY: Use this to display normals using the silhouette @@ -161,7 +162,7 @@ BOOL LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, co LLVector4a det; det.setAllDot3(edge1, pvec); - if (det.greaterEqual4(LLVector4a::getApproximatelyZero()).getComparisonMask() & 0x7) + if (det.greaterEqual(LLVector4a::getEpsilon()).getGatheredBits() & 0x7) { /* calculate distance from vert0 to ray origin */ LLVector4a tvec; @@ -171,8 +172,8 @@ BOOL LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, co LLVector4a u; u.setAllDot3(tvec,pvec); - if ((u.greaterEqual4(LLVector4a::getZero()).getComparisonMask() & 0x7) && - (u.lessEqual4(det).getComparisonMask() & 0x7)) + if ((u.greaterEqual(LLVector4a::getZero()).getGatheredBits() & 0x7) && + (u.lessEqual(det).getGatheredBits() & 0x7)) { /* prepare to test V parameter */ LLVector4a qvec; @@ -188,8 +189,8 @@ BOOL LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, co LLVector4a sum_uv; sum_uv.setAdd(u, v); - S32 v_gequal = v.greaterEqual4(LLVector4a::getZero()).getComparisonMask() & 0x7; - S32 sum_lequal = sum_uv.lessEqual4(det).getComparisonMask() & 0x7; + S32 v_gequal = v.greaterEqual(LLVector4a::getZero()).getGatheredBits() & 0x7; + S32 sum_lequal = sum_uv.lessEqual(det).getGatheredBits() & 0x7; if (v_gequal && sum_lequal) { @@ -230,7 +231,7 @@ BOOL LLTriangleRayIntersectTwoSided(const LLVector4a& vert0, const LLVector4a& v pvec.setCross3(dir, edge2); /* if determinant is near zero, ray lies in plane of triangle */ - F32 det = edge1.dot3(pvec); + F32 det = edge1.dot3(pvec).getF32(); if (det > -F_APPROXIMATELY_ZERO && det < F_APPROXIMATELY_ZERO) @@ -245,7 +246,7 @@ BOOL LLTriangleRayIntersectTwoSided(const LLVector4a& vert0, const LLVector4a& v tvec.setSub(orig, vert0); /* calculate U parameter and test bounds */ - u = (tvec.dot3(pvec)) * inv_det; + u = (tvec.dot3(pvec).getF32()) * inv_det; if (u < 0.f || u > 1.f) { return FALSE; @@ -255,7 +256,7 @@ BOOL LLTriangleRayIntersectTwoSided(const LLVector4a& vert0, const LLVector4a& v tvec.sub(edge1); /* calculate V parameter and test bounds */ - v = (dir.dot3(tvec)) * inv_det; + v = (dir.dot3(tvec).getF32()) * inv_det; if (v < 0.f || u + v > 1.f) { @@ -263,7 +264,7 @@ BOOL LLTriangleRayIntersectTwoSided(const LLVector4a& vert0, const LLVector4a& v } /* calculate t, ray intersects triangle */ - t = (edge2.dot3(tvec)) * inv_det; + t = (edge2.dot3(tvec).getF32()) * inv_det; intersection_a = u; intersection_b = v; @@ -326,20 +327,20 @@ public: //stretch by triangles in node tri = *iter; - min.setMin(*tri->mV[0]); - min.setMin(*tri->mV[1]); - min.setMin(*tri->mV[2]); + min.setMin(min, *tri->mV[0]); + min.setMin(min, *tri->mV[1]); + min.setMin(min, *tri->mV[2]); - max.setMax(*tri->mV[0]); - max.setMax(*tri->mV[1]); - max.setMax(*tri->mV[2]); + max.setMax(max, *tri->mV[0]); + max.setMax(max, *tri->mV[1]); + max.setMax(max, *tri->mV[2]); } for (S32 i = 0; i < branch->getChildCount(); ++i) { //stretch by child extents LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(i)->getListener(0); - min.setMin(child->mExtents[0]); - max.setMax(child->mExtents[1]); + min.setMin(min, child->mExtents[0]); + max.setMax(min, child->mExtents[1]); } } else if (branch->getChildCount() != 0) @@ -352,8 +353,8 @@ public: for (S32 i = 1; i < branch->getChildCount(); ++i) { //stretch by child extents child = (LLVolumeOctreeListener*) branch->getChild(i)->getListener(0); - min.setMin(child->mExtents[0]); - max.setMax(child->mExtents[1]); + min.setMin(min, child->mExtents[0]); + max.setMax(max, child->mExtents[1]); } } else @@ -2011,7 +2012,7 @@ const LLVolumeFace::VertexData& LLVolumeFace::VertexData::operator=(const LLVolu if (this != &rhs) { init(); - LLVector4a::memcpyNonAliased16((F32*) mData, (F32*) rhs.mData, 8); + LLVector4a::memcpyNonAliased16((F32*) mData, (F32*) rhs.mData, 8*sizeof(F32)); mTexCoord = rhs.mTexCoord; } return *this; @@ -2055,8 +2056,8 @@ void LLVolumeFace::VertexData::setNormal(const LLVector4a& norm) bool LLVolumeFace::VertexData::operator<(const LLVolumeFace::VertexData& rhs)const { - const F32* lp = this->getPosition().getF32(); - const F32* rp = rhs.getPosition().getF32(); + const F32* lp = this->getPosition().getF32ptr(); + const F32* rp = rhs.getPosition().getF32ptr(); if (lp[0] != rp[0]) { @@ -2073,8 +2074,8 @@ bool LLVolumeFace::VertexData::operator<(const LLVolumeFace::VertexData& rhs)con return lp[2] < rp[2]; } - lp = getNormal().getF32(); - rp = rhs.getNormal().getF32(); + lp = getNormal().getF32ptr(); + rp = rhs.getNormal().getF32ptr(); if (lp[0] != rp[0]) { @@ -2101,23 +2102,23 @@ bool LLVolumeFace::VertexData::operator<(const LLVolumeFace::VertexData& rhs)con bool LLVolumeFace::VertexData::operator==(const LLVolumeFace::VertexData& rhs)const { - return mData[POSITION].equal3(rhs.getPosition()) && - mData[NORMAL].equal3(rhs.getNormal()) && + return mData[POSITION].equals3(rhs.getPosition()) && + mData[NORMAL].equals3(rhs.getNormal()) && mTexCoord == rhs.mTexCoord; } bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs, F32 angle_cutoff) const { bool retval = false; - if (rhs.mData[POSITION].equal3(mData[POSITION]) && rhs.mTexCoord == mTexCoord) + if (rhs.mData[POSITION].equals3(mData[POSITION]) && rhs.mTexCoord == mTexCoord) { if (angle_cutoff > 1.f) { - retval = (mData[NORMAL].equal3(rhs.mData[NORMAL])); + retval = (mData[NORMAL].equals3(rhs.mData[NORMAL])); } else { - F32 cur_angle = rhs.mData[NORMAL].dot3(mData[NORMAL]); + F32 cur_angle = rhs.mData[NORMAL].dot3(mData[NORMAL]).getF32(); retval = cur_angle > angle_cutoff; } } @@ -2331,8 +2332,8 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) } else { - min.setMin(*pos_out); - max.setMax(*pos_out); + min.setMin(min, *pos_out); + max.setMax(max, *pos_out); } pos_out++; @@ -2944,7 +2945,7 @@ void sculpt_calc_mesh_resolution(U16 width, U16 height, U8 type, F32 detail, S32 ratio = (F32) width / (F32) height; - s = (S32)fsqrtf(((F32)vertices / ratio)); + s = (S32)(F32) sqrt(((F32)vertices / ratio)); s = llmax(s, 4); // no degenerate sizes, please t = vertices / s; @@ -5280,16 +5281,15 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) freeData(); - LLVector4a::memcpyNonAliased16((F32*) mExtents, (F32*) src.mExtents, 12); + LLVector4a::memcpyNonAliased16((F32*) mExtents, (F32*) src.mExtents, 12*sizeof(F32)); resizeVertices(src.mNumVertices); resizeIndices(src.mNumIndices); if (mNumVertices) { - S32 vert_size = mNumVertices*4; + S32 vert_size = mNumVertices*4*sizeof(F32); S32 tc_size = (mNumVertices*8+0xF) & ~0xF; - tc_size /= 4; LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size); LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size); @@ -5322,8 +5322,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) if (mNumIndices) { S32 idx_size = (mNumIndices*2+0xF) & ~0xF; - idx_size /= 4; - + LLVector4a::memcpyNonAliased16((F32*) mIndices, (F32*) src.mIndices, idx_size); } @@ -5388,9 +5387,9 @@ void LLVolumeFace::getVertexData(U16 index, LLVolumeFace::VertexData& cv) bool LLVolumeFace::VertexMapData::operator==(const LLVolumeFace::VertexData& rhs) const { - return getPosition().equal3(rhs.getPosition()) && + return getPosition().equals3(rhs.getPosition()) && mTexCoord == rhs.mTexCoord && - getNormal().equal3(rhs.getNormal()); + getNormal().equals3(rhs.getNormal()); } bool LLVolumeFace::VertexMapData::ComparePosition::operator()(const LLVector3& a, const LLVector3& b) const @@ -5423,7 +5422,7 @@ void LLVolumeFace::optimize(F32 angle_cutoff) getVertexData(index, cv); BOOL found = FALSE; - VertexMapData::PointMap::iterator point_iter = point_map.find(LLVector3(cv.getPosition().getF32())); + VertexMapData::PointMap::iterator point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr())); if (point_iter != point_map.end()) { //duplicate point might exist for (U32 j = 0; j < point_iter->second.size(); ++j) @@ -5455,7 +5454,7 @@ void LLVolumeFace::optimize(F32 angle_cutoff) } else { - point_map[LLVector3(d.getPosition().getF32())].push_back(d); + point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d); } } } @@ -5491,12 +5490,12 @@ void LLVolumeFace::createOctree() tri->mIndex[2] = mIndices[i+2]; LLVector4a min = v0; - min.setMin(v1); - min.setMin(v2); + min.setMin(min, v1); + min.setMin(min, v2); LLVector4a max = v0; - max.setMax(v1); - max.setMax(v2); + max.setMax(max, v1); + max.setMax(max, v2); LLVector4a center; center.setAdd(min, max); @@ -5507,7 +5506,7 @@ void LLVolumeFace::createOctree() LLVector4a size; size.setSub(max,min); - tri->mRadius = size.length3() * 0.5f; + tri->mRadius = size.getLength3().getF32() * 0.5f; mOctree->insert(tri); } @@ -5655,12 +5654,13 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) if (gx == 0 && gy == 0) { - min = max = newVert.getPosition(); + min = newVert.getPosition(); + max = min; } else { - min.setMin(newVert.getPosition()); - max.setMax(newVert.getPosition()); + min.setMin(min, newVert.getPosition()); + max.setMax(max, newVert.getPosition()); } } } @@ -5795,7 +5795,8 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) if (i == 0) { - min = max = pos[i]; + max = pos[i]; + min = max; min_uv = max_uv = tc[i]; } else @@ -5848,8 +5849,8 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) for (S32 i = 0; i < num_vertices; i++) { - binorm[i].load4a((F32*) &binormal.mQ); - norm[i].load4a((F32*) &normal.mQ); + binorm[i].load4a(binormal.getF32ptr()); + norm[i].load4a(normal.getF32ptr()); } if (partial_build) @@ -6186,7 +6187,7 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con LLVector4a* dst = (LLVector4a*) ll_aligned_malloc_16(new_size); if (mPositions) { - LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mPositions, old_size/4); + LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mPositions, old_size); ll_aligned_free_16(mPositions); } mPositions = dst; @@ -6195,7 +6196,7 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con dst = (LLVector4a*) ll_aligned_malloc_16(new_size); if (mNormals) { - LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mNormals, old_size/4); + LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mNormals, old_size); ll_aligned_free_16(mNormals); } mNormals = dst; @@ -6209,7 +6210,7 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con LLVector2* dst = (LLVector2*) ll_aligned_malloc_16(new_size); if (mTexCoords) { - LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mTexCoords, old_size/4); + LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mTexCoords, old_size); ll_aligned_free_16(mTexCoords); } } @@ -6268,7 +6269,7 @@ void LLVolumeFace::pushIndex(const U16& idx) U16* dst = (U16*) ll_aligned_malloc_16(new_size); if (mIndices) { - LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mIndices, old_size/4); + LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mIndices, old_size); ll_aligned_free_16(mIndices); } mIndices = dst; @@ -6319,9 +6320,9 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat if (mNumVertices > 0) { //copy old buffers - LLVector4a::memcpyNonAliased16((F32*) new_pos, (F32*) mPositions, mNumVertices*4); - LLVector4a::memcpyNonAliased16((F32*) new_norm, (F32*) mNormals, mNumVertices*4); - LLVector4a::memcpyNonAliased16((F32*) new_tc, (F32*) mTexCoords, mNumVertices*2); + LLVector4a::memcpyNonAliased16((F32*) new_pos, (F32*) mPositions, mNumVertices*4*sizeof(F32)); + LLVector4a::memcpyNonAliased16((F32*) new_norm, (F32*) mNormals, mNumVertices*4*sizeof(F32)); + LLVector4a::memcpyNonAliased16((F32*) new_tc, (F32*) mTexCoords, mNumVertices*2*sizeof(F32)); } //free old buffer space @@ -6382,7 +6383,7 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat if (mNumIndices > 0) { //copy old index buffer S32 old_size = (mNumIndices*2+0xF) & ~0xF; - LLVector4a::memcpyNonAliased16((F32*) new_indices, (F32*) mIndices, old_size/4); + LLVector4a::memcpyNonAliased16((F32*) new_indices, (F32*) mIndices, old_size); } //free old index buffer diff --git a/indra/llmath/tests/v2math_test.cpp b/indra/llmath/tests/v2math_test.cpp index 4660fcb955..c745b9989e 100644 --- a/indra/llmath/tests/v2math_test.cpp +++ b/indra/llmath/tests/v2math_test.cpp @@ -91,7 +91,7 @@ namespace tut F32 x = 2.2345f, y = 3.5678f ; LLVector2 vec2(x,y); ensure("magVecSquared:Fail ", is_approx_equal(vec2.magVecSquared(), (x*x + y*y))); - ensure("magVec:Fail ", is_approx_equal(vec2.magVec(), fsqrtf(x*x + y*y))); + ensure("magVec:Fail ", is_approx_equal(vec2.magVec(), (F32) sqrt(x*x + y*y))); } template<> template<> @@ -413,7 +413,7 @@ namespace tut ensure_equals("dist_vec_squared values are not equal",val2, val1); val1 = dist_vec(vec2, vec3); - val2 = fsqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2)); + val2 = (F32) sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2)); ensure_equals("dist_vec values are not equal",val2, val1); } @@ -437,7 +437,7 @@ namespace tut LLVector2 vec2(x1, y1); F32 vecMag = vec2.normVec(); - F32 mag = fsqrtf(x1*x1 + y1*y1); + F32 mag = (F32) sqrt(x1*x1 + y1*y1); F32 oomag = 1.f / mag; val1 = x1 * oomag; diff --git a/indra/llmath/tests/v3color_test.cpp b/indra/llmath/tests/v3color_test.cpp index 316b6e392f..0efba8e9f3 100644 --- a/indra/llmath/tests/v3color_test.cpp +++ b/indra/llmath/tests/v3color_test.cpp @@ -99,7 +99,7 @@ namespace tut F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f; LLColor3 llcolor3(r,g,b); ensure("magVecSquared:Fail ", is_approx_equal(llcolor3.magVecSquared(), (r*r + g*g + b*b))); - ensure("magVec:Fail ", is_approx_equal(llcolor3.magVec(), fsqrtf(r*r + g*g + b*b))); + ensure("magVec:Fail ", is_approx_equal(llcolor3.magVec(), (F32) sqrt(r*r + g*g + b*b))); } template<> template<> @@ -109,7 +109,7 @@ namespace tut F32 val1, val2,val3; LLColor3 llcolor3(r,g,b); F32 vecMag = llcolor3.normVec(); - F32 mag = fsqrtf(r*r + g*g + b*b); + F32 mag = (F32) sqrt(r*r + g*g + b*b); F32 oomag = 1.f / mag; val1 = r * oomag; val2 = g * oomag; @@ -292,7 +292,7 @@ namespace tut F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2); F32 val = distVec(llcolor3,llcolor3a); - ensure("distVec failed ", is_approx_equal(fsqrtf((r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2)) ,val)); + ensure("distVec failed ", is_approx_equal((F32) sqrt((r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2)) ,val)); F32 val1 = distVec_squared(llcolor3,llcolor3a); ensure("distVec_squared failed ", is_approx_equal(((r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2)) ,val1)); diff --git a/indra/llmath/tests/v3dmath_test.cpp b/indra/llmath/tests/v3dmath_test.cpp index e7c949186c..894b6200f5 100644 --- a/indra/llmath/tests/v3dmath_test.cpp +++ b/indra/llmath/tests/v3dmath_test.cpp @@ -409,7 +409,7 @@ namespace tut LLVector3d vec3D(x,y,z); F64 res = (x*x + y*y + z*z) - vec3D.magVecSquared(); ensure("1:magVecSquared:Fail ", ((-F_APPROXIMATELY_ZERO <= res)&& (res <=F_APPROXIMATELY_ZERO))); - res = fsqrtf(x*x + y*y + z*z) - vec3D.magVec(); + res = (F32) sqrt(x*x + y*y + z*z) - vec3D.magVec(); ensure("2:magVec: Fail ", ((-F_APPROXIMATELY_ZERO <= res)&& (res <=F_APPROXIMATELY_ZERO))); } diff --git a/indra/llmath/tests/v3math_test.cpp b/indra/llmath/tests/v3math_test.cpp index 7faf076243..d5c8dd2f9c 100644 --- a/indra/llmath/tests/v3math_test.cpp +++ b/indra/llmath/tests/v3math_test.cpp @@ -155,7 +155,7 @@ namespace tut F32 x = 2.32f, y = 1.212f, z = -.12f; LLVector3 vec3(x,y,z); ensure("1:magVecSquared:Fail ", is_approx_equal(vec3.magVecSquared(), (x*x + y*y + z*z))); - ensure("2:magVec:Fail ", is_approx_equal(vec3.magVec(), fsqrtf(x*x + y*y + z*z))); + ensure("2:magVec:Fail ", is_approx_equal(vec3.magVec(), (F32) sqrt(x*x + y*y + z*z))); } template<> template<> @@ -515,7 +515,7 @@ namespace tut F32 val1,val2; LLVector3 vec3(x1,y1,z1),vec3a(x2,y2,z2); val1 = dist_vec(vec3,vec3a); - val2 = fsqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); + val2 = (F32) sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); ensure_equals("1:dist_vec: Fail ",val2, val1); val1 = dist_vec_squared(vec3,vec3a); val2 =((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); diff --git a/indra/llmath/tests/v4color_test.cpp b/indra/llmath/tests/v4color_test.cpp index 33921e0f0f..636446027a 100644 --- a/indra/llmath/tests/v4color_test.cpp +++ b/indra/llmath/tests/v4color_test.cpp @@ -161,7 +161,7 @@ namespace tut F32 r = 0x20, g = 0xFFFF, b = 0xFF; LLColor4 llcolor4(r,g,b); ensure("magVecSquared:Fail ", is_approx_equal(llcolor4.magVecSquared(), (r*r + g*g + b*b))); - ensure("magVec:Fail ", is_approx_equal(llcolor4.magVec(), fsqrtf(r*r + g*g + b*b))); + ensure("magVec:Fail ", is_approx_equal(llcolor4.magVec(), (F32) sqrt(r*r + g*g + b*b))); } template<> template<> @@ -170,7 +170,7 @@ namespace tut F32 r = 0x20, g = 0xFFFF, b = 0xFF; LLColor4 llcolor4(r,g,b); F32 vecMag = llcolor4.normVec(); - F32 mag = fsqrtf(r*r + g*g + b*b); + F32 mag = (F32) sqrt(r*r + g*g + b*b); F32 oomag = 1.f / mag; F32 val1 = r * oomag, val2 = g * oomag, val3 = b * oomag; ensure("1:normVec failed ", (is_approx_equal(val1, llcolor4.mV[0]) && is_approx_equal(val2, llcolor4.mV[1]) && is_approx_equal(val3, llcolor4.mV[2]) && is_approx_equal(vecMag, mag))); diff --git a/indra/llmath/tests/v4coloru_test.cpp b/indra/llmath/tests/v4coloru_test.cpp index 9f71cfc8cc..b3dbfece34 100644 --- a/indra/llmath/tests/v4coloru_test.cpp +++ b/indra/llmath/tests/v4coloru_test.cpp @@ -141,7 +141,7 @@ namespace tut U8 r = 0x12, g = 0xFF, b = 0xAF; LLColor4U llcolor4u(r,g,b); ensure("magVecSquared:Fail ", is_approx_equal(llcolor4u.magVecSquared(), (F32)(r*r + g*g + b*b))); - ensure("magVec:Fail ", is_approx_equal(llcolor4u.magVec(), fsqrtf(r*r + g*g + b*b))); + ensure("magVec:Fail ", is_approx_equal(llcolor4u.magVec(), (F32) sqrt((F32) (r*r + g*g + b*b)))); } template<> template<> diff --git a/indra/llmath/tests/v4math_test.cpp b/indra/llmath/tests/v4math_test.cpp index fe051c27e9..e919c90efa 100644 --- a/indra/llmath/tests/v4math_test.cpp +++ b/indra/llmath/tests/v4math_test.cpp @@ -102,7 +102,7 @@ namespace tut { F32 x = 10.f, y = -2.3f, z = -.023f; LLVector4 vec4(x,y,z); - ensure("magVec:Fail ", is_approx_equal(vec4.magVec(), fsqrtf(x*x + y*y + z*z))); + ensure("magVec:Fail ", is_approx_equal(vec4.magVec(), (F32) sqrt(x*x + y*y + z*z))); ensure("magVecSquared:Fail ", is_approx_equal(vec4.magVecSquared(), (x*x + y*y + z*z))); } @@ -343,7 +343,7 @@ namespace tut F32 val1,val2; LLVector4 vec4(x1,y1,z1),vec4a(x2,y2,z2); val1 = dist_vec(vec4,vec4a); - val2 = fsqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); + val2 = (F32) sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); ensure_equals("dist_vec: Fail ",val2, val1); val1 = dist_vec_squared(vec4,vec4a); val2 =((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); diff --git a/indra/llmath/v2math.cpp b/indra/llmath/v2math.cpp index 220336e0c2..2603127f75 100644 --- a/indra/llmath/v2math.cpp +++ b/indra/llmath/v2math.cpp @@ -92,7 +92,7 @@ F32 dist_vec(const LLVector2 &a, const LLVector2 &b) { F32 x = a.mV[0] - b.mV[0]; F32 y = a.mV[1] - b.mV[1]; - return fsqrtf( x*x + y*y ); + return (F32) sqrt( x*x + y*y ); } F32 dist_vec_squared(const LLVector2 &a, const LLVector2 &b) diff --git a/indra/llmath/v2math.h b/indra/llmath/v2math.h index ae26c85ce4..35fd1b6048 100644 --- a/indra/llmath/v2math.h +++ b/indra/llmath/v2math.h @@ -225,7 +225,7 @@ inline void LLVector2::setVec(const F32 *vec) inline F32 LLVector2::length(void) const { - return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1]); + return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); } inline F32 LLVector2::lengthSquared(void) const @@ -235,7 +235,7 @@ inline F32 LLVector2::lengthSquared(void) const inline F32 LLVector2::normalize(void) { - F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1]); + F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); F32 oomag; if (mag > FP_MAG_THRESHOLD) @@ -262,7 +262,7 @@ inline bool LLVector2::isFinite() const // deprecated inline F32 LLVector2::magVec(void) const { - return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1]); + return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); } // deprecated @@ -274,7 +274,7 @@ inline F32 LLVector2::magVecSquared(void) const // deprecated inline F32 LLVector2::normVec(void) { - F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1]); + F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); F32 oomag; if (mag > FP_MAG_THRESHOLD) diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h index 1915d80502..95a3de8b62 100644 --- a/indra/llmath/v3color.h +++ b/indra/llmath/v3color.h @@ -284,7 +284,7 @@ inline F32 LLColor3::brightness(void) const inline F32 LLColor3::length(void) const { - return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); } inline F32 LLColor3::lengthSquared(void) const @@ -294,7 +294,7 @@ inline F32 LLColor3::lengthSquared(void) const inline F32 LLColor3::normalize(void) { - F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); F32 oomag; if (mag) @@ -310,7 +310,7 @@ inline F32 LLColor3::normalize(void) // deprecated inline F32 LLColor3::magVec(void) const { - return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); } // deprecated @@ -322,7 +322,7 @@ inline F32 LLColor3::magVecSquared(void) const // deprecated inline F32 LLColor3::normVec(void) { - F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); F32 oomag; if (mag) @@ -444,7 +444,7 @@ inline F32 distVec(const LLColor3 &a, const LLColor3 &b) F32 x = a.mV[0] - b.mV[0]; F32 y = a.mV[1] - b.mV[1]; F32 z = a.mV[2] - b.mV[2]; - return fsqrtf( x*x + y*y + z*z ); + return (F32) sqrt( x*x + y*y + z*z ); } inline F32 distVec_squared(const LLColor3 &a, const LLColor3 &b) diff --git a/indra/llmath/v3dmath.h b/indra/llmath/v3dmath.h index 6ab31e8a41..ab253de064 100644 --- a/indra/llmath/v3dmath.h +++ b/indra/llmath/v3dmath.h @@ -240,7 +240,7 @@ inline const LLVector3d& LLVector3d::setVec(const F64 *vec) inline F64 LLVector3d::normVec(void) { - F64 mag = fsqrtf(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); + F64 mag = (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); F64 oomag; if (mag > FP_MAG_THRESHOLD) @@ -262,7 +262,7 @@ inline F64 LLVector3d::normVec(void) inline F64 LLVector3d::normalize(void) { - F64 mag = fsqrtf(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); + F64 mag = (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); F64 oomag; if (mag > FP_MAG_THRESHOLD) @@ -286,7 +286,7 @@ inline F64 LLVector3d::normalize(void) inline F64 LLVector3d::magVec(void) const { - return fsqrtf(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); + return (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); } inline F64 LLVector3d::magVecSquared(void) const @@ -296,7 +296,7 @@ inline F64 LLVector3d::magVecSquared(void) const inline F64 LLVector3d::length(void) const { - return fsqrtf(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); + return (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); } inline F64 LLVector3d::lengthSquared(void) const @@ -406,7 +406,7 @@ inline F64 dist_vec(const LLVector3d &a, const LLVector3d &b) F64 x = a.mdV[0] - b.mdV[0]; F64 y = a.mdV[1] - b.mdV[1]; F64 z = a.mdV[2] - b.mdV[2]; - return fsqrtf( x*x + y*y + z*z ); + return (F32) sqrt( x*x + y*y + z*z ); } inline F64 dist_vec_squared(const LLVector3d &a, const LLVector3d &b) diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h index 75c860a91e..5d483a8753 100644 --- a/indra/llmath/v3math.h +++ b/indra/llmath/v3math.h @@ -282,7 +282,7 @@ inline void LLVector3::setVec(const F32 *vec) inline F32 LLVector3::normalize(void) { - F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); F32 oomag; if (mag > FP_MAG_THRESHOLD) @@ -305,7 +305,7 @@ inline F32 LLVector3::normalize(void) // deprecated inline F32 LLVector3::normVec(void) { - F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); F32 oomag; if (mag > FP_MAG_THRESHOLD) @@ -329,7 +329,7 @@ inline F32 LLVector3::normVec(void) inline F32 LLVector3::length(void) const { - return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); } inline F32 LLVector3::lengthSquared(void) const @@ -339,7 +339,7 @@ inline F32 LLVector3::lengthSquared(void) const inline F32 LLVector3::magVec(void) const { - return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); } inline F32 LLVector3::magVecSquared(void) const @@ -473,7 +473,7 @@ inline F32 dist_vec(const LLVector3 &a, const LLVector3 &b) F32 x = a.mV[0] - b.mV[0]; F32 y = a.mV[1] - b.mV[1]; F32 z = a.mV[2] - b.mV[2]; - return fsqrtf( x*x + y*y + z*z ); + return (F32) sqrt( x*x + y*y + z*z ); } inline F32 dist_vec_squared(const LLVector3 &a, const LLVector3 &b) diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h index 6b63b976b0..dd92e1cc63 100644 --- a/indra/llmath/v4color.h +++ b/indra/llmath/v4color.h @@ -392,7 +392,7 @@ inline const LLColor4& LLColor4::setAlpha(F32 a) inline F32 LLColor4::length(void) const { - return fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); } inline F32 LLColor4::lengthSquared(void) const @@ -402,7 +402,7 @@ inline F32 LLColor4::lengthSquared(void) const inline F32 LLColor4::normalize(void) { - F32 mag = fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); F32 oomag; if (mag) @@ -418,7 +418,7 @@ inline F32 LLColor4::normalize(void) // deprecated inline F32 LLColor4::magVec(void) const { - return fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); } // deprecated @@ -430,7 +430,7 @@ inline F32 LLColor4::magVecSquared(void) const // deprecated inline F32 LLColor4::normVec(void) { - F32 mag = fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); F32 oomag; if (mag) diff --git a/indra/llmath/v4coloru.h b/indra/llmath/v4coloru.h index 4ec5a345eb..08245403a1 100644 --- a/indra/llmath/v4coloru.h +++ b/indra/llmath/v4coloru.h @@ -300,7 +300,7 @@ inline const LLColor4U& LLColor4U::setAlpha(U8 a) inline F32 LLColor4U::length(void) const { - return fsqrtf( ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ] ); + return (F32) sqrt( ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ] ); } inline F32 LLColor4U::lengthSquared(void) const @@ -311,7 +311,7 @@ inline F32 LLColor4U::lengthSquared(void) const // deprecated inline F32 LLColor4U::magVec(void) const { - return fsqrtf( ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ] ); + return (F32) sqrt( ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ] ); } // deprecated diff --git a/indra/llmath/v4math.h b/indra/llmath/v4math.h index 4c82e6b629..72a477ed20 100644 --- a/indra/llmath/v4math.h +++ b/indra/llmath/v4math.h @@ -321,7 +321,7 @@ inline void LLVector4::setVec(const F32 *vec) inline F32 LLVector4::length(void) const { - return fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); } inline F32 LLVector4::lengthSquared(void) const @@ -331,7 +331,7 @@ inline F32 LLVector4::lengthSquared(void) const inline F32 LLVector4::magVec(void) const { - return fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); } inline F32 LLVector4::magVecSquared(void) const @@ -463,7 +463,7 @@ inline LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u) inline F32 LLVector4::normalize(void) { - F32 mag = fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); F32 oomag; if (mag > FP_MAG_THRESHOLD) @@ -486,7 +486,7 @@ inline F32 LLVector4::normalize(void) // deprecated inline F32 LLVector4::normVec(void) { - F32 mag = fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); F32 oomag; if (mag > FP_MAG_THRESHOLD) diff --git a/indra/llmessage/llsdmessagebuilder.cpp b/indra/llmessage/llsdmessagebuilder.cpp index 6e41b03895..2680dd0b77 100755 --- a/indra/llmessage/llsdmessagebuilder.cpp +++ b/indra/llmessage/llsdmessagebuilder.cpp @@ -35,6 +35,7 @@ #include "llsdmessagebuilder.h" #include "llmessagetemplate.h" +#include "llmath.h" #include "llquaternion.h" #include "llsdutil.h" #include "llsdutil_math.h" diff --git a/indra/llmessage/lltemplatemessagebuilder.cpp b/indra/llmessage/lltemplatemessagebuilder.cpp index fa02456d90..6f9707ed57 100644 --- a/indra/llmessage/lltemplatemessagebuilder.cpp +++ b/indra/llmessage/lltemplatemessagebuilder.cpp @@ -35,6 +35,7 @@ #include "lltemplatemessagebuilder.h" #include "llmessagetemplate.h" +#include "llmath.h" #include "llquaternion.h" #include "u64.h" #include "v3dmath.h" diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp index 8f56cf2521..2b67e9f6fa 100644 --- a/indra/llmessage/lltemplatemessagereader.cpp +++ b/indra/llmessage/lltemplatemessagereader.cpp @@ -36,6 +36,7 @@ #include "llfasttimer.h" #include "llmessagebuilder.h" #include "llmessagetemplate.h" +#include "llmath.h" #include "llquaternion.h" #include "message.h" #include "u64.h" diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 70601663e6..2b1a9bbf94 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -924,7 +924,7 @@ LLVector3 LLRender::getUITranslation() { llerrs << "UI offset stack empty." << llendl; } - return LLVector3(mUIOffset[mUIStackDepth-1].getF32()); + return LLVector3(mUIOffset[mUIStackDepth-1].getF32ptr()); } LLVector3 LLRender::getUIScale() @@ -933,7 +933,7 @@ LLVector3 LLRender::getUIScale() { llerrs << "UI scale stack empty." << llendl; } - return LLVector3(mUIScale[mUIStackDepth-1].getF32()); + return LLVector3(mUIScale[mUIStackDepth-1].getF32ptr()); } diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 72d51540ef..5fae5b893f 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1210,7 +1210,7 @@ void LLAgent::startAutoPilotGlobal(const LLVector3d &target_global, const std::s else { // Guess at a reasonable stop distance. - mAutoPilotStopDistance = fsqrtf( distance ); + mAutoPilotStopDistance = (F32) sqrt( distance ); if (mAutoPilotStopDistance < 0.5f) { mAutoPilotStopDistance = 0.5f; diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 8d0a06378f..68f52e04bc 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -743,7 +743,7 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update) } else { - pos = LLVector3(getPositionGroup().getF32()); + pos = LLVector3(getPositionGroup().getF32ptr()); } pos -= camera.getOrigin(); @@ -824,7 +824,7 @@ void LLDrawable::shiftPos(const LLVector4a &shift_vector) for (S32 i = 0; i < getNumFaces(); i++) { LLFace *facep = getFace(i); - facep->mCenterAgent += LLVector3(shift_vector.getF32()); + facep->mCenterAgent += LLVector3(shift_vector.getF32ptr()); facep->mExtents[0].add(shift_vector); facep->mExtents[1].add(shift_vector); @@ -1153,13 +1153,13 @@ void LLSpatialBridge::updateSpatialExtents() LLVector4a max; max.setAdd(center, delta); - newMin.setMin(min); - newMax.setMax(max); + newMin.setMin(newMin, min); + newMax.setMax(newMax, max); } LLVector4a diagonal; diagonal.setSub(newMax, newMin); - mRadius = diagonal.length3() * 0.5f; + mRadius = diagonal.getLength3().getF32() * 0.5f; mPositionGroup->setAdd(newMin,newMax); mPositionGroup->mul(0.5f); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index af082eea3e..d698624c15 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -37,6 +37,7 @@ #include "llvoavatar.h" #include "m3math.h" +#include "llmatrix4a.h" #include "llagent.h" //for gAgent.needsRenderAvatar() #include "lldrawable.h" @@ -495,7 +496,7 @@ S32 LLDrawPoolAvatar::getNumPasses() } else { - return 3; + return 4; } #else if (LLPipeline::sImpostorRender) @@ -814,26 +815,46 @@ void LLDrawPoolAvatar::endSkinned() #if LL_MESH_ENABLED void LLDrawPoolAvatar::beginRiggedSimple() { - if (LLPipeline::sUnderWaterRender) + if (sShaderLevel > 0) { - sVertexProgram = &gSkinnedObjectSimpleWaterProgram; + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectSimpleWaterProgram; + } + else + { + sVertexProgram = &gSkinnedObjectSimpleProgram; + } } else { - sVertexProgram = &gSkinnedObjectSimpleProgram; + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gObjectSimpleWaterProgram; + } + else + { + sVertexProgram = &gObjectSimpleProgram; + } } - sDiffuseChannel = 0; - sVertexProgram->bind(); - LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sDiffuseChannel = 0; + sVertexProgram->bind(); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); + } } void LLDrawPoolAvatar::endRiggedSimple() { LLVertexBuffer::unbind(); - sVertexProgram->unbind(); - sVertexProgram = NULL; - LLVertexBuffer::sWeight4Loc = -1; + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sVertexProgram->unbind(); + sVertexProgram = NULL; + LLVertexBuffer::sWeight4Loc = -1; + } } void LLDrawPoolAvatar::beginRiggedAlpha() @@ -1281,8 +1302,10 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) } #if LL_MESH_ENABLED -void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face) +void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face) { + LLVertexBuffer* buffer = face->mVertexBuffer; + U32 data_mask = 0; for (U32 i = 0; i < face->mRiggedIndex.size(); ++i) { @@ -1292,17 +1315,23 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSk } } - LLVertexBuffer* buff = face->mVertexBuffer; - - if (!buff || - buff->getTypeMask() != data_mask || - buff->getRequestedVerts() != vol_face.mNumVertices) + if (!buffer || + buffer->getTypeMask() != data_mask || + buffer->getRequestedVerts() != vol_face.mNumVertices) { face->setGeomIndex(0); face->setIndicesIndex(0); face->setSize(vol_face.mNumVertices, vol_face.mNumIndices, true); - face->mVertexBuffer = new LLVertexBuffer(data_mask, 0); + if (sShaderLevel > 0) + { + face->mVertexBuffer = new LLVertexBuffer(data_mask, GL_DYNAMIC_DRAW_ARB); + } + else + { + face->mVertexBuffer = new LLVertexBuffer(data_mask, GL_STREAM_DRAW_ARB); + } + face->mVertexBuffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), true); U16 offset = 0; @@ -1319,7 +1348,83 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSk LLMatrix3 mat_normal(mat3); face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_normal, offset, true); - buff = face->mVertexBuffer; + buffer = face->mVertexBuffer; + } + + if (sShaderLevel <= 0 && face->mLastSkinTime < avatar->getLastSkinTime()) + { //perform software vertex skinning for this face + LLStrider position; + LLStrider normal; + + buffer->getVertexStrider(position); + buffer->getNormalStrider(normal); + + LLVector4a* pos = (LLVector4a*) position.get(); + LLVector4a* norm = (LLVector4a*) normal.get(); + + //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(); + } + } + + LLVector4a* weight = vol_face.mWeights; + + 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] = (S32) floorf(w); + 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; + + LLVector4a& n = vol_face.mNormals[j]; + bind_shape_matrix.rotate(n, t); + final_mat.rotate(t, dst); + norm[j] = dst; + } } } @@ -1371,7 +1476,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) stop_glerror(); const LLVolumeFace& vol_face = volume->getVolumeFace(te); - updateRiggedFaceVertexBuffer(face, skin, volume, vol_face); + updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face); stop_glerror(); @@ -1381,30 +1486,37 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) if (buff) { - LLMatrix4 mat[64]; + if (sShaderLevel > 0) + { //upload matrix palette to shader + LLMatrix4 mat[64]; - for (U32 i = 0; i < skin->mJointNames.size(); ++i) - { - LLJoint* joint = avatar->getJoint(skin->mJointNames[i]); - if (joint) + for (U32 i = 0; i < skin->mJointNames.size(); ++i) { - mat[i] = skin->mInvBindMatrix[i]; - mat[i] *= joint->getWorldMatrix(); + LLJoint* joint = avatar->getJoint(skin->mJointNames[i]); + if (joint) + { + mat[i] = skin->mInvBindMatrix[i]; + mat[i] *= joint->getWorldMatrix(); + } } + + stop_glerror(); + + LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv("matrixPalette", + skin->mJointNames.size(), + FALSE, + (GLfloat*) mat[0].mMatrix); + LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv("matrixPalette[0]", + skin->mJointNames.size(), + FALSE, + (GLfloat*) mat[0].mMatrix); + + stop_glerror(); + } + else + { + data_mask &= ~LLVertexBuffer::MAP_WEIGHT4; } - - stop_glerror(); - - LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv("matrixPalette", - skin->mJointNames.size(), - FALSE, - (GLfloat*) mat[0].mMatrix); - LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv("matrixPalette[0]", - skin->mJointNames.size(), - FALSE, - (GLfloat*) mat[0].mMatrix); - - stop_glerror(); buff->setBuffer(data_mask); diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index b01394534b..d08ae04516 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -138,7 +138,8 @@ public: void endDeferredRiggedSimple(); void endDeferredRiggedBump(); - void updateRiggedFaceVertexBuffer(LLFace* facep, + void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, + LLFace* facep, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 8533f9710c..5d7d3387a4 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -106,8 +106,8 @@ void planarProjection(LLVector2 &tc, const LLVector4a& normal, LLVector4a tangent; tangent.setCross3(binormal,normal); - tc.mV[1] = -((tangent.dot3(vec))*2 - 0.5f); - tc.mV[0] = 1.0f+((binormal.dot3(vec))*2 - 0.5f); + tc.mV[1] = -((tangent.dot3(vec).getF32())*2 - 0.5f); + tc.mV[0] = 1.0f+((binormal.dot3(vec).getF32())*2 - 0.5f); } void sphericalProjection(LLVector2 &tc, const LLVector4a& normal, @@ -156,6 +156,7 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) mLastUpdateTime = gFrameTimeSeconds; mLastMoveTime = 0.f; + mLastSkinTime = gFrameTimeSeconds; mVSize = 0.f; mPixelArea = 16.f; mState = GLOBAL; @@ -828,8 +829,8 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, LLVector4a max; max.setAdd(center, delta); - newMin.setMin(min); - newMax.setMax(max); + newMin.setMin(newMin,min); + newMax.setMax(newMax,max); } if (!mDrawablep->isActive()) @@ -844,11 +845,11 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, t.mul(0.5f); //VECTORIZE THIS - mCenterLocal.set(t.getF32()); + mCenterLocal.set(t.getF32ptr()); t.setSub(newMax,newMin); t.mul(0.5f); - mBoundingSphereRadius = t.length3(); + mBoundingSphereRadius = t.getLength3().getF32(); updateCenterAgent(); } @@ -1313,7 +1314,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { if (!do_xform) { - LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2); + LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); } else { @@ -1529,13 +1530,13 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (mDrawablep->isActive()) { LLVector3 t; - t.set(binormal.getF32()); + t.set(binormal.getF32ptr()); t *= bump_quat; binormal.load3(t.mV); } binormal.normalize3fast(); - tc += LLVector2( bump_s_primary_light_ray.dot3(tangent), bump_t_primary_light_ray.dot3(binormal) ); + tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() ); *tex_coords2++ = tc; } @@ -1583,7 +1584,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_weights && vf.mWeights) { - LLVector4a::memcpyNonAliased16((F32*) weights, (F32*) vf.mWeights, num_vertices*4); + LLVector4a::memcpyNonAliased16((F32*) weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32)); } if (rebuild_color) @@ -1705,21 +1706,21 @@ BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) LLViewerCamera* camera = LLViewerCamera::getInstance(); - F32 size_squared = size.dot3(size); + F32 size_squared = size.dot3(size).getF32(); LLVector4a lookAt; LLVector4a t; t.load3(camera->getOrigin().mV); lookAt.setSub(center, t); - F32 dist = lookAt.length3(); + F32 dist = lookAt.getLength3().getF32(); lookAt.normalize3fast() ; //get area of circle around node - F32 app_angle = atanf(fsqrtf(size_squared) / dist); + F32 app_angle = atanf((F32) sqrt(size_squared) / dist); radius = app_angle*LLDrawable::sCurPixelAngle; mPixelArea = radius*radius * 3.14159f; LLVector4a x_axis; x_axis.load3(camera->getXAxis().mV); - cos_angle_to_view_dir = lookAt.dot3(x_axis); + cos_angle_to_view_dir = lookAt.dot3(x_axis).getF32(); //if has media, check if the face is out of the view frustum. if(hasMedia()) diff --git a/indra/newview/llface.h b/indra/newview/llface.h index b6a67c7fc4..a7d7889350 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -240,6 +240,7 @@ public: LLPointer mVertexBuffer; LLPointer mLastVertexBuffer; F32 mLastUpdateTime; + F32 mLastSkinTime; F32 mLastMoveTime; LLMatrix4* mTextureMatrix; LLDrawInfo* mDrawInfo; @@ -274,7 +275,7 @@ private: S32 mReferenceIndex; std::vector mRiggedIndex; - + F32 mVSize; F32 mPixelArea; diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index 8be4e34748..62336b03bf 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -100,7 +100,7 @@ void LLVolumeImplFlexible::onParameterChanged(U16 param_type, LLNetworkData *dat void LLVolumeImplFlexible::onShift(const LLVector4a &shift_vector) { //VECTORIZE THIS - LLVector3 shift(shift_vector.getF32()); + LLVector3 shift(shift_vector.getF32ptr()); for (int section = 0; section < (1<getInterest()); // proximity distance is actually distance squared -- display it as straight distance. - debug_str += llformat("%g/", fsqrtf(impl->getProximityDistance())); + debug_str += llformat("%g/", (F32) sqrt(impl->getProximityDistance())); // s += llformat("%g/", (float)impl->getCPUUsage()); // s += llformat("%g/", (float)impl->getApproximateTextureInterest()); diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 98fbebbc5d..d84ac2e4c8 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -576,8 +576,8 @@ void LLPanelPrimMediaControls::updateShape() const LLVolumeFace& vf = volume->getVolumeFace(mTargetObjectFace); LLVector3 ext[2]; - ext[0].set(vf.mExtents[0].getF32()); - ext[1].set(vf.mExtents[1].getF32()); + ext[0].set(vf.mExtents[0].getF32ptr()); + ext[1].set(vf.mExtents[1].getF32ptr()); LLVector3 center = (ext[0]+ext[1])*0.5f; LLVector3 size = (ext[1]-ext[0])*0.5f; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 42f09f7396..92903a6aa9 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1124,13 +1124,13 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 & size.setSub(max_extents, min_extents); size.mul(0.5f); - mGridOrigin.set(center.getF32()); + mGridOrigin.set(center.getF32ptr()); LLDrawable* drawable = first_grid_object->mDrawable; if (drawable && drawable->isActive()) { mGridOrigin = mGridOrigin * first_grid_object->getRenderMatrix(); } - mGridScale.set(size.getF32()); + mGridScale.set(size.getF32ptr()); } } else // GRID_MODE_WORLD or just plain default @@ -3543,7 +3543,7 @@ void LLSelectMgr::deselectAllIfTooFar() { if (mDebugSelectMgr) { - llinfos << "Selection manager: auto-deselecting, select_dist = " << fsqrtf(select_dist_sq) << llendl; + llinfos << "Selection manager: auto-deselecting, select_dist = " << (F32) sqrt(select_dist_sq) << llendl; llinfos << "agent pos global = " << gAgent.getPositionGlobal() << llendl; llinfos << "selection pos global = " << selectionCenter << llendl; } diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 2335c7bb8e..e55ec03356 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -231,7 +231,7 @@ U8* get_box_fan_indices(LLCamera* camera, const LLVector4a& center) LLVector4a origin; origin.load3(camera->getOrigin().mV); - S32 cypher = center.greaterThan4(origin).getComparisonMask() & 0x7; + S32 cypher = center.greaterThan(origin).getGatheredBits() & 0x7; return sOcclusionIndices+cypher*8; } @@ -253,7 +253,7 @@ void LLSpatialGroup::buildOcclusion() r2.splat(0.25f); r2.add(mBounds[1]); - r.setMin(r2); + r.setMin(r, r2); LLVector4a* v = mOcclusionVerts; const LLVector4a& c = mBounds[0]; @@ -775,8 +775,8 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector4a& minOut, LLVector4a& ma } else { - minOut.setMin(newMin); - maxOut.setMax(newMax); + minOut.setMin(minOut, newMin); + maxOut.setMax(maxOut, newMax); } return TRUE; @@ -1220,8 +1220,8 @@ void LLSpatialGroup::updateDistance(LLCamera &camera) #endif if (!getData().empty()) { - mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].length3() : - (F32) mOctreeNode->getSize().length3(); + mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].getLength3().getF32() : + (F32) mOctreeNode->getSize().getLength3().getF32(); mDistance = mSpatialPartition->calcDistance(this, camera); mPixelArea = mSpatialPartition->calcPixelArea(this, camera); } @@ -1241,7 +1241,7 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) { LLVector4a v = eye; - dist = eye.length3(); + dist = eye.getLength3().getF32(); eye.normalize3fast(); if (!group->isState(LLSpatialGroup::ALPHA_DIRTY)) @@ -1253,7 +1253,7 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) LLVector4a diff; diff.setSub(view_angle, *group->mLastUpdateViewAngle); - if (diff.length3() > 0.64f) + if (diff.getLength3().getF32() > 0.64f) { *group->mViewAngle = view_angle; *group->mLastUpdateViewAngle = view_angle; @@ -1279,11 +1279,11 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) t.mul(group->mObjectBounds[1]); v.sub(t); - group->mDepth = v.dot3(ata); + group->mDepth = v.dot3(ata).getF32(); } else { - dist = eye.length3(); + dist = eye.getLength3().getF32(); } if (dist < 16.f) @@ -1497,8 +1497,8 @@ BOOL LLSpatialGroup::rebound() const LLVector4a& max = group->mExtents[1]; const LLVector4a& min = group->mExtents[0]; - newMax.setMax(max); - newMin.setMin(min); + newMax.setMax(newMax, max); + newMin.setMin(newMin, min); } boundObjects(FALSE, newMin, newMax); @@ -2196,8 +2196,8 @@ BOOL LLSpatialPartition::getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLOctreeCullVisExtents vis(&camera, visMina, visMaxa); vis.traverse(mOctree); - visMin.set(visMina.getF32()); - visMax.set(visMaxa.getF32()); + visMin.set(visMina.getF32ptr()); + visMax.set(visMaxa.getF32ptr()); return vis.mEmpty; } @@ -2280,13 +2280,13 @@ BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group) LLVector4a max; max.setAdd(c,r); - S32 lt = e.lessThan4(min).getComparisonMask() & 0x7; + S32 lt = e.lessThan(min).getGatheredBits() & 0x7; if (lt) { return FALSE; } - S32 gt = e.greaterThan4(max).getComparisonMask() & 0x7; + S32 gt = e.greaterThan(max).getGatheredBits() & 0x7; if (gt) { return FALSE; @@ -2745,8 +2745,8 @@ void renderNormals(LLDrawable* drawablep) p.setAdd(face.mPositions[j], n); gGL.color4f(1,1,1,1); - gGL.vertex3fv(face.mPositions[j].getF32()); - gGL.vertex3fv(p.getF32()); + gGL.vertex3fv(face.mPositions[j].getF32ptr()); + gGL.vertex3fv(p.getF32ptr()); if (face.mBinormals) { @@ -2754,8 +2754,8 @@ void renderNormals(LLDrawable* drawablep) p.setAdd(face.mPositions[j], n); gGL.color4f(0,1,1,1); - gGL.vertex3fv(face.mPositions[j].getF32()); - gGL.vertex3fv(p.getF32()); + gGL.vertex3fv(face.mPositions[j].getF32ptr()); + gGL.vertex3fv(p.getF32ptr()); } } @@ -3024,8 +3024,8 @@ public: LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) branch->getListener(0); LLVector3 center, size; - center.set(vl->mBounds[0].getF32()); - size.set(vl->mBounds[1].getF32()); + center.set(vl->mBounds[0].getF32ptr()); + size.set(vl->mBounds[1].getF32ptr()); drawBoxOutline(center, size); } diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index cef7c4abbb..917185ed04 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -810,7 +810,7 @@ BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts) render_mata.affineTransform(t, vec); } - BOOL in_frustum = pointInFrustum(LLVector3(vec.getF32())) > 0; + BOOL in_frustum = pointInFrustum(LLVector3(vec.getF32ptr())) > 0; if (( !in_frustum && all_verts) || (in_frustum && !all_verts)) diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 9e35b5cc51..0a181e09bb 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -726,8 +726,8 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w U32 words = num_verts*4; - LLVector4a::memcpyNonAliased16(v, (F32*) mMesh->getCoords(), words); - LLVector4a::memcpyNonAliased16(n, (F32*) mMesh->getNormals(), words); + LLVector4a::memcpyNonAliased16(v, (F32*) mMesh->getCoords(), words*sizeof(F32)); + LLVector4a::memcpyNonAliased16(n, (F32*) mMesh->getNormals(), words*sizeof(F32)); if (!terse_update) @@ -740,9 +740,9 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w F32* vw = (F32*) vertex_weightsp.get(); F32* cw = (F32*) clothing_weightsp.get(); - LLVector4a::memcpyNonAliased16(tc, (F32*) mMesh->getTexCoords(), num_verts*2); - LLVector4a::memcpyNonAliased16(vw, (F32*) mMesh->getWeights(), num_verts); - LLVector4a::memcpyNonAliased16(cw, (F32*) mMesh->getClothingWeights(), num_verts*4); + LLVector4a::memcpyNonAliased16(tc, (F32*) mMesh->getTexCoords(), num_verts*2*sizeof(F32)); + LLVector4a::memcpyNonAliased16(vw, (F32*) mMesh->getWeights(), num_verts*sizeof(F32)); + LLVector4a::memcpyNonAliased16(cw, (F32*) mMesh->getClothingWeights(), num_verts*4*sizeof(F32)); } const U32 idx_count = mMesh->getNumFaces()*3; diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index 79d8fc7df9..16a6022b86 100644 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -764,7 +764,7 @@ void LLViewerJoystick::moveAvatar(bool reset) sDelta[RX_I] += (cur_delta[RX_I] - sDelta[RX_I]) * time * feather; sDelta[RY_I] += (cur_delta[RY_I] - sDelta[RY_I]) * time * feather; - handleRun(fsqrtf(sDelta[Z_I]*sDelta[Z_I] + sDelta[X_I]*sDelta[X_I])); + handleRun((F32) sqrt(sDelta[Z_I]*sDelta[Z_I] + sDelta[X_I]*sDelta[X_I])); // Allow forward/backward movement some priority if (dom_axis == Z_I) diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 178d928f57..303f339f7d 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -865,7 +865,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg) // Set the low priority size for downsampling to approximately the size the texture is displayed at. { - F32 approximate_interest_dimension = fsqrtf(pimpl->getInterest()); + F32 approximate_interest_dimension = (F32) sqrt(pimpl->getInterest()); pimpl->setLowPrioritySizeLimit(llround(approximate_interest_dimension)); } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 2b89deaa53..9587fbafb1 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -2973,7 +2973,7 @@ F32 LLViewerObject::getBinRadius() const LLVector4a* ext = mDrawable->getSpatialExtents(); LLVector4a diff; diff.setSub(ext[1], ext[0]); - return diff.length3(); + return diff.getLength3().getF32(); } return getScale().magVec(); diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index 41848e8b7a..4759454ee7 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -161,8 +161,8 @@ LLViewerPartGroup::LLViewerPartGroup(const LLVector3 ¢er_agent, const F32 bo if (group != NULL) { - LLVector3 center(group->mOctreeNode->getCenter().getF32()); - LLVector3 size(group->mOctreeNode->getSize().getF32()); + LLVector3 center(group->mOctreeNode->getCenter().getF32ptr()); + LLVector3 size(group->mOctreeNode->getSize().getF32ptr()); size += LLVector3(0.01f, 0.01f, 0.01f); mMinObjPos = center - size; mMaxObjPos = center + size; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 719c5b0da5..d50efe89dd 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1580,7 +1580,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority() S32 cur_discard = getCurrentDiscardLevelForFetching(); bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel)); - F32 pixel_priority = fsqrtf(mMaxVirtualSize); + F32 pixel_priority = (F32) sqrt(mMaxVirtualSize); F32 priority = 0.f; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index abf22b5e5a..e50d0fce49 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -675,6 +675,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mTexHairColor( NULL ), mTexEyeColor( NULL ), mNeedsSkin(FALSE), + mLastSkinTime(0.f), mUpdatePeriod(1), mFullyLoaded(FALSE), mPreviousFullyLoaded(FALSE), @@ -1356,7 +1357,7 @@ void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) if (isImpostor() && !needsImpostorUpdate()) { LLVector3 delta = getRenderPosition() - - ((LLVector3(mDrawable->getPositionGroup().getF32())-mImpostorOffset)); + ((LLVector3(mDrawable->getPositionGroup().getF32ptr())-mImpostorOffset)); newMin.load3( (mLastAnimExtents[0] + delta).mV); newMax.load3( (mLastAnimExtents[1] + delta).mV); @@ -1364,12 +1365,12 @@ void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) else { getSpatialExtents(newMin,newMax); - mLastAnimExtents[0].set(newMin.getF32()); - mLastAnimExtents[1].set(newMax.getF32()); + mLastAnimExtents[0].set(newMin.getF32ptr()); + mLastAnimExtents[1].set(newMax.getF32ptr()); LLVector4a pos_group; pos_group.setAdd(newMin,newMax); pos_group.mul(0.5f); - mImpostorOffset = LLVector3(pos_group.getF32())-getRenderPosition(); + mImpostorOffset = LLVector3(pos_group.getF32ptr())-getRenderPosition(); mDrawable->setPositionGroup(pos_group); } } @@ -1435,7 +1436,7 @@ void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) distance.setSub(ext[1], ext[0]); LLVector4a max_span(max_attachment_span); - S32 lt = distance.lessThan4(max_span).getComparisonMask() & 0x7; + S32 lt = distance.lessThan(max_span).getGatheredBits() & 0x7; // Only add the prim to spatial extents calculations if it isn't a megaprim. // max_attachment_span calculated at the start of the function @@ -2533,14 +2534,14 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) getSpatialExtents(ext[0], ext[1]); LLVector4a diff; diff.setSub(ext[1], mImpostorExtents[1]); - if (diff.length3() > 0.05f) + if (diff.getLength3().getF32() > 0.05f) { mNeedsImpostorUpdate = TRUE; } else { diff.setSub(ext[0], mImpostorExtents[0]); - if (diff.length3() > 0.05f) + if (diff.getLength3().getF32() > 0.05f) { mNeedsImpostorUpdate = TRUE; } @@ -3887,7 +3888,8 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) mMeshLOD[MESH_ID_HAIR]->updateJointGeometry(); } mNeedsSkin = FALSE; - + mLastSkinTime = gFrameTimeSeconds; + LLVertexBuffer* vb = mDrawable->getFace(0)->mVertexBuffer; if (vb) { @@ -4231,7 +4233,7 @@ void LLVOAvatar::updateTextures() if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { - setDebugText(llformat("%4.0f:%4.0f", fsqrtf(mMinPixelArea),fsqrtf(mMaxPixelArea))); + setDebugText(llformat("%4.0f:%4.0f", (F32) sqrt(mMinPixelArea),(F32) sqrt(mMaxPixelArea))); } } @@ -5443,7 +5445,7 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent) } else { - F32 radius = size.length3(); + F32 radius = size.getLength3().getF32(); mAppAngle = (F32) atan2( radius, range) * RAD_TO_DEG; } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 95b0665f7d..94b564fc8f 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -345,6 +345,7 @@ public: U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0); U32 renderRigid(); U32 renderSkinned(EAvatarRenderPass pass); + F32 getLastSkinTime() { return mLastSkinTime; } U32 renderSkinnedAttachments(); U32 renderTransparent(BOOL first_pass); void renderCollisionVolumes(); @@ -357,6 +358,8 @@ private: bool shouldAlphaMask(); BOOL mNeedsSkin; // avatar has been animated and verts have not been updated + F32 mLastSkinTime; //value of gFrameTimeSeconds at last skin update + S32 mUpdatePeriod; S32 mNumInitFaces; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer. diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index fe1e36cbe8..65829b213e 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -328,7 +328,7 @@ void LLVOGrass::updateTextures() { if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { - setDebugText(llformat("%4.0f", fsqrtf(mPixelArea))); + setDebugText(llformat("%4.0f", (F32) sqrt(mPixelArea))); } getTEImage(0)->addTextureStats(mPixelArea); } diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 63f662c5a1..c047758a59 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -999,8 +999,8 @@ BOOL LLVOSurfacePatch::lineSegmentIntersect(const LLVector3& start, const LLVect const LLVector4a* exta = mDrawable->getSpatialExtents(); LLVector3 ext[2]; - ext[0].set(exta[0].getF32()); - ext[1].set(exta[1].getF32()); + ext[0].set(exta[0].getF32ptr()); + ext[1].set(exta[1].getF32ptr()); F32 rad = (delta*tdelta).magVecSquared(); diff --git a/indra/newview/llvotextbubble.cpp b/indra/newview/llvotextbubble.cpp index 339da3c0bf..e790373d02 100644 --- a/indra/newview/llvotextbubble.cpp +++ b/indra/newview/llvotextbubble.cpp @@ -254,8 +254,8 @@ void LLVOTextBubble::getGeometry(S32 idx, LLVector2* dst_tc = (LLVector2*) texcoordsp.get(); LLVector2* src_tc = (LLVector2*) face.mTexCoords; - LLVector4a::memcpyNonAliased16((F32*) dst_norm, (F32*) src_norm, face.mNumVertices*4); - LLVector4a::memcpyNonAliased16((F32*) dst_tc, (F32*) src_tc, face.mNumVertices*2); + LLVector4a::memcpyNonAliased16((F32*) dst_norm, (F32*) src_norm, face.mNumVertices*4*sizeof(F32)); + LLVector4a::memcpyNonAliased16((F32*) dst_tc, (F32*) src_tc, face.mNumVertices*2*sizeof(F32)); for (U32 i = 0; i < face.mNumVertices; i++) diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index eb790b04cc..e3b4efb9dd 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -472,7 +472,7 @@ void LLVOTree::updateTextures() { if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { - setDebugText(llformat("%4.0f", fsqrtf(mPixelArea))); + setDebugText(llformat("%4.0f", (F32) sqrt(mPixelArea))); } mTreeImagep->addTextureStats(mPixelArea); } @@ -1278,8 +1278,8 @@ BOOL LLVOTree::lineSegmentIntersect(const LLVector3& start, const LLVector3& end //VECTORIZE THIS LLVector3 ext[2]; - ext[0].set(exta[0].getF32()); - ext[1].set(exta[1].getF32()); + ext[0].set(exta[0].getF32ptr()); + ext[1].set(exta[1].getF32ptr()); LLVector3 center = (ext[1]+ext[0])*0.5f; LLVector3 size = (ext[1]-ext[0]); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 1397b64623..128fd15142 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -696,7 +696,7 @@ void LLVOVolume::updateTextureVirtualSize() const LLTextureEntry *te = face->getTextureEntry(); LLViewerTexture *imagep = face->getTexture(); if (!imagep || !te || - face->mExtents[0].equal3(face->mExtents[1])) + face->mExtents[0].equals3(face->mExtents[1])) { continue; } @@ -820,15 +820,15 @@ void LLVOVolume::updateTextureVirtualSize() if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { - setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); + setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); } else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) { - setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); + setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); } else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) { - setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); + setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); } if (mPixelArea == 0) @@ -1355,8 +1355,8 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) } else { - min.setMin(face->mExtents[0]); - max.setMax(face->mExtents[1]); + min.setMin(min, face->mExtents[0]); + max.setMax(max, face->mExtents[1]); } } } @@ -1864,7 +1864,7 @@ LLVector3 LLVOVolume::getApproximateFaceNormal(U8 face_id) result.add(face.mNormals[i]); } - LLVector3 ret((F32*) &result.mQ); + LLVector3 ret(result.getF32ptr()); ret = volumeDirectionToAgent(ret); ret.normVec(); } @@ -3075,7 +3075,7 @@ F32 LLVOVolume::getBinRadius() LLVector4a rad; rad.setSub(ext[1], ext[0]); - radius = rad.length3()*0.5f; + radius = rad.getLength3().getF32()*0.5f; } else if (mDrawable->isStatic()) { diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index a1e4df8a66..53eca0d08e 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -591,7 +591,7 @@ void LLWorld::updateVisibilities() region_list_t::iterator curiter = iter++; LLViewerRegion* regionp = *curiter; F32 height = regionp->getLand().getMaxZ() - regionp->getLand().getMinZ(); - F32 radius = 0.5f*fsqrtf(height * height + diagonal_squared); + F32 radius = 0.5f*(F32) sqrt(height * height + diagonal_squared); if (!regionp->getLand().hasZData() || LLViewerCamera::getInstance()->sphereInFrustum(regionp->getCenterAgent(), radius)) { @@ -612,7 +612,7 @@ void LLWorld::updateVisibilities() } F32 height = regionp->getLand().getMaxZ() - regionp->getLand().getMinZ(); - F32 radius = 0.5f*fsqrtf(height * height + diagonal_squared); + F32 radius = 0.5f*(F32) sqrt(height * height + diagonal_squared); if (LLViewerCamera::getInstance()->sphereInFrustum(regionp->getCenterAgent(), radius)) { regionp->calculateCameraDistance(); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index fec7da1dd0..b0a7b1ce83 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1522,7 +1522,7 @@ F32 LLPipeline::calcPixelArea(const LLVector4a& center, const LLVector4a& size, LLVector4a lookAt; lookAt.setSub(center, origin); - F32 dist = lookAt.length3(); + F32 dist = lookAt.getLength3().getF32(); //ramp down distance for nearby objects //shrink dist by dist/16. @@ -1534,7 +1534,7 @@ F32 LLPipeline::calcPixelArea(const LLVector4a& center, const LLVector4a& size, } //get area of circle around node - F32 app_angle = atanf(size.length3()/dist); + F32 app_angle = atanf(size.getLength3().getF32()/dist); F32 radius = app_angle*LLDrawable::sCurPixelAngle; return radius*radius * F_PI; } @@ -4671,7 +4671,7 @@ static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_ { return max_dist; } - F32 dist = fsqrtf(dist2); + F32 dist = (F32) sqrt(dist2); dist *= 1.f / inten; dist -= radius; if (selected) @@ -6980,7 +6980,7 @@ void LLPipeline::renderDeferredLighting() LLVector4a center; center.load3(drawablep->getPositionAgent().mV); - const F32* c = center.getF32(); + const F32* c = center.getF32ptr(); F32 s = volume->getLightRadius()*1.5f; LLColor3 col = volume->getLightColor(); @@ -7078,7 +7078,7 @@ void LLPipeline::renderDeferredLighting() LLVector4a center; center.load3(drawablep->getPositionAgent().mV); - const F32* c = center.getF32(); + const F32* c = center.getF32ptr(); F32 s = volume->getLightRadius()*1.5f; sVisibleLightCount++; @@ -9184,8 +9184,8 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) up.mul(up); up.normalize3fast(); - tdim.mV[0] = fabsf(half_height.dot3(left)); - tdim.mV[1] = fabsf(half_height.dot3(up)); + tdim.mV[0] = fabsf(half_height.dot3(left).getF32()); + tdim.mV[1] = fabsf(half_height.dot3(up).getF32()); glMatrixMode(GL_PROJECTION); glPushMatrix(); -- cgit v1.3 From 314a89535791e1e5a0c3f4d901c9c1d16fb9b6cc Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 19 Aug 2010 16:48:15 -0500 Subject: Software fallback for avatar vertex skinning. Reviewed by Nyx. --- indra/newview/lldrawpoolavatar.cpp | 200 +++++++++++++++++++++---------------- 1 file changed, 115 insertions(+), 85 deletions(-) (limited to 'indra/newview/lldrawpoolavatar.cpp') diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index d698624c15..ccc060f3fa 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -490,14 +490,10 @@ S32 LLDrawPoolAvatar::getNumPasses() { return 8; } - else if (getVertexShaderLevel() > 0) + else { return 10; } - else - { - return 4; - } #else if (LLPipeline::sImpostorRender) { @@ -859,143 +855,168 @@ void LLDrawPoolAvatar::endRiggedSimple() void LLDrawPoolAvatar::beginRiggedAlpha() { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gSkinnedObjectSimpleWaterProgram; - } - else - { - sVertexProgram = &gSkinnedObjectSimpleProgram; - } - sDiffuseChannel = 0; - sVertexProgram->bind(); - LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); + beginRiggedSimple(); } void LLDrawPoolAvatar::endRiggedAlpha() { - sVertexProgram->unbind(); - sVertexProgram = NULL; - LLVertexBuffer::unbind(); - LLVertexBuffer::sWeight4Loc = -1; + endRiggedSimple(); } void LLDrawPoolAvatar::beginRiggedFullbrightAlpha() { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gSkinnedObjectFullbrightWaterProgram; - } - else - { - sVertexProgram = &gSkinnedObjectFullbrightProgram; - } - sDiffuseChannel = 0; - sVertexProgram->bind(); - LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); + beginRiggedFullbright(); } void LLDrawPoolAvatar::endRiggedFullbrightAlpha() { - sVertexProgram->unbind(); - sVertexProgram = NULL; - LLVertexBuffer::unbind(); - LLVertexBuffer::sWeight4Loc = -1; + endRiggedFullbright(); } void LLDrawPoolAvatar::beginRiggedGlow() { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gSkinnedObjectFullbrightWaterProgram; - } - else - { - sVertexProgram = &gSkinnedObjectFullbrightProgram; - } - sDiffuseChannel = 0; - sVertexProgram->bind(); - LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); + beginRiggedFullbright(); } void LLDrawPoolAvatar::endRiggedGlow() { - sVertexProgram->unbind(); - sVertexProgram = NULL; - LLVertexBuffer::unbind(); - LLVertexBuffer::sWeight4Loc = -1; + endRiggedFullbright(); } void LLDrawPoolAvatar::beginRiggedFullbright() { - if (LLPipeline::sUnderWaterRender) + if (sShaderLevel > 0) { - sVertexProgram = &gSkinnedObjectFullbrightWaterProgram; + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectFullbrightWaterProgram; + } + else + { + sVertexProgram = &gSkinnedObjectFullbrightProgram; + } } else { - sVertexProgram = &gSkinnedObjectFullbrightProgram; + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gObjectFullbrightWaterProgram; + } + else + { + sVertexProgram = &gObjectFullbrightProgram; + } + } + + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sDiffuseChannel = 0; + sVertexProgram->bind(); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } - sDiffuseChannel = 0; - sVertexProgram->bind(); - LLVertexBuffer::sWeight4Loc = gSkinnedObjectFullbrightProgram.getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } void LLDrawPoolAvatar::endRiggedFullbright() { LLVertexBuffer::unbind(); - sVertexProgram->unbind(); - sVertexProgram = NULL; - LLVertexBuffer::sWeight4Loc = -1; + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sVertexProgram->unbind(); + sVertexProgram = NULL; + LLVertexBuffer::sWeight4Loc = -1; + } } void LLDrawPoolAvatar::beginRiggedShinySimple() { - if (LLPipeline::sUnderWaterRender) + if (sShaderLevel > 0) { - sVertexProgram = &gSkinnedObjectShinySimpleWaterProgram; + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectShinySimpleWaterProgram; + } + else + { + sVertexProgram = &gSkinnedObjectShinySimpleProgram; + } } else { - sVertexProgram = &gSkinnedObjectShinySimpleProgram; + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gObjectShinyWaterProgram; + } + else + { + sVertexProgram = &gObjectShinyProgram; + } + } + + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sVertexProgram->bind(); + LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } - sVertexProgram->bind(); - LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); - LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } void LLDrawPoolAvatar::endRiggedShinySimple() { LLVertexBuffer::unbind(); - LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); - sVertexProgram->unbind(); - sVertexProgram = NULL; - LLVertexBuffer::sWeight4Loc = -1; + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); + sVertexProgram->unbind(); + sVertexProgram = NULL; + LLVertexBuffer::sWeight4Loc = -1; + } } void LLDrawPoolAvatar::beginRiggedFullbrightShiny() { - if (LLPipeline::sUnderWaterRender) + if (sShaderLevel > 0) { - sVertexProgram = &gSkinnedObjectFullbrightShinyWaterProgram; + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectFullbrightShinyWaterProgram; + } + else + { + sVertexProgram = &gSkinnedObjectFullbrightShinyProgram; + } } else { - sVertexProgram = &gSkinnedObjectFullbrightShinyProgram; + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gObjectFullbrightShinyWaterProgram; + } + else + { + sVertexProgram = &gObjectFullbrightShinyProgram; + } + } + + + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sVertexProgram->bind(); + LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } - sVertexProgram->bind(); - LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); - LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } void LLDrawPoolAvatar::endRiggedFullbrightShiny() { LLVertexBuffer::unbind(); - LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); - sVertexProgram->unbind(); - sVertexProgram = NULL; - LLVertexBuffer::sWeight4Loc = -1; + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); + sVertexProgram->unbind(); + sVertexProgram = NULL; + LLVertexBuffer::sWeight4Loc = -1; + } } @@ -1356,11 +1377,17 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* LLStrider position; LLStrider normal; + bool has_normal = buffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); buffer->getVertexStrider(position); - buffer->getNormalStrider(normal); + + if (has_normal) + { + buffer->getNormalStrider(normal); + } LLVector4a* pos = (LLVector4a*) position.get(); - LLVector4a* norm = (LLVector4a*) normal.get(); + + LLVector4a* norm = has_normal ? (LLVector4a*) normal.get() : NULL; //build matrix palette LLMatrix4a mp[64]; @@ -1420,10 +1447,13 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* final_mat.affineTransform(t, dst); pos[j] = dst; - LLVector4a& n = vol_face.mNormals[j]; - bind_shape_matrix.rotate(n, t); - final_mat.rotate(t, dst); - norm[j] = dst; + if (norm) + { + LLVector4a& n = vol_face.mNormals[j]; + bind_shape_matrix.rotate(n, t); + final_mat.rotate(t, dst); + norm[j] = dst; + } } } } -- cgit v1.3