void test_create() { ecl_grid_type * ecl_grid; int nx = 100; int ny = 100; int nz = 10; double * DXV = util_malloc( nx * sizeof * DXV ); double * DYV = util_malloc( ny * sizeof * DYV ); double * DZV = util_malloc( nz * sizeof * DZV ); double * DEPTHZ = util_malloc( (nx + 1) * (ny + 1) * sizeof * DEPTHZ); for (int i=0; i < nx; i++) DXV[i] = 1.0 / nx; for (int j=0; j < ny; j++) DYV[j] = 1.0 / ny; for (int k=0; k < nz; k++) DZV[k] = 3.0 / nz; for (int j=0; j <= ny; j++) { double y = center_sum(DYV , j); for (int i=0; i <= nx; i++) { double x = center_sum(DXV , i); DEPTHZ[i + j*(nx + 1)] = zfunc( x,y ); } } ecl_grid = ecl_grid_alloc_dxv_dyv_dzv_depthz( nx,ny,nz,DXV , DYV , DZV , DEPTHZ , NULL); for (int k=0; k < nz; k++) { double z0 = center_sum(DZV , k ) - 0.5*DZV[0]; for (int j=0; j < ny; j++) { double y0 = center_sum(DYV , j ); for (int i=0; i < nx; i++) { double x0 = center_sum(DXV , i ); double xc,yc,zc; int g = ecl_grid_get_global_index3( ecl_grid , i , j , k ); ecl_grid_get_xyz1( ecl_grid , g , &xc , &yc , &zc); test_assert_double_equal( x0 , xc ); test_assert_double_equal( y0 , yc ); ecl_grid_get_cell_corner_xyz1( ecl_grid , g , 0 , &xc , &yc , &zc); test_assert_double_equal( z0 + zfunc(x0 , y0) , zc ); ecl_grid_get_cell_corner_xyz1( ecl_grid , g , 4, &xc , &yc , &zc); test_assert_double_equal( z0 + zfunc(x0 , y0) + DZV[k] , zc ); } } } free( DXV ); free( DYV ); free( DZV ); free( DEPTHZ ); ecl_grid_free( ecl_grid ); }
BOOL LLFace::getGeometryVolume(const LLVolume& volume, const S32 &f, const LLMatrix4& mat_vert_in, const LLMatrix3& mat_norm_in, const U16 &index_offset, bool force_rebuild) { llassert(verify()); const LLVolumeFace &vf = volume.getVolumeFace(f); S32 num_vertices = (S32)vf.mNumVertices; S32 num_indices = (S32) vf.mNumIndices; if (mVertexBuffer.notNull()) { if (num_indices + (S32) mIndicesIndex > mVertexBuffer->getNumIndices()) { llwarns << "Index buffer overflow!" << llendl; llwarns << "Indices Count: " << mIndicesCount << " VF Num Indices: " << num_indices << " Indices Index: " << mIndicesIndex << " VB Num Indices: " << mVertexBuffer->getNumIndices() << llendl; llwarns << "Last Indices Count: " << mLastIndicesCount << " Last Indices Index: " << mLastIndicesIndex << " Face Index: " << f << " Pool Type: " << mPoolType << llendl; return FALSE; } if (num_vertices + mGeomIndex > mVertexBuffer->getNumVerts()) { llwarns << "Vertex buffer overflow!" << llendl; return FALSE; } } LLStrider<LLVector3> vertices; LLStrider<LLVector2> tex_coords; LLStrider<LLVector2> tex_coords2; LLStrider<LLVector3> normals; LLStrider<LLColor4U> colors; LLStrider<LLVector3> binormals; LLStrider<U16> indicesp; #if MESH_ENABLED LLStrider<LLVector4> weights; #endif //MESH_ENABLED BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME); BOOL global_volume = mDrawablep->getVOVolume()->isVolumeGlobal(); LLVector3 scale; if (global_volume) { scale.setVec(1,1,1); } else { scale = mVObjp->getScale(); } bool rebuild_pos = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_POSITION); bool rebuild_color = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_COLOR); bool rebuild_tcoord = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_TCOORD); bool rebuild_normal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); bool rebuild_binormal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_BINORMAL); #if MESH_ENABLED bool rebuild_weights = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_WEIGHT4); #endif //MESH_ENABLED const LLTextureEntry *tep = mVObjp->getTE(f); if (!tep) rebuild_color = FALSE; // can't get color when tep is NULL U8 bump_code = tep ? tep->getBumpmap() : 0; BOOL is_static = mDrawablep->isStatic(); BOOL is_global = is_static; LLVector3 center_sum(0.f, 0.f, 0.f); if (is_global) { setState(GLOBAL); } else { clearState(GLOBAL); } LLColor4U color = (tep ? LLColor4U(tep->getColor()) : LLColor4U::white); if (rebuild_color) // FALSE if tep == NULL { if (tep) { GLfloat alpha[4] = { 0.00f, 0.25f, 0.5f, 0.75f }; if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || (LLPipeline::sRenderBump && tep->getShiny()))) { color.mV[3] = U8 (alpha[tep->getShiny()] * 255); } } } // INDICES if (full_rebuild) { mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex); for (U32 i = 0; i < (U32) num_indices; i++) { indicesp[i] = vf.mIndices[i] + index_offset; } //mVertexBuffer->setBuffer(0); } LLMatrix4a mat_normal; mat_normal.loadu(mat_norm_in); //if it's not fullbright and has no normals, bake sunlight based on face normal //bool bake_sunlight = !getTextureEntry()->getFullbright() && // !mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0; if (rebuild_tcoord) { bool do_xform; if (tep) { r = tep->getRotation(); os = tep->mOffsetS; ot = tep->mOffsetT; ms = tep->mScaleS; mt = tep->mScaleT; cos_ang = cos(r); sin_ang = sin(r); if (cos_ang != 1.f || sin_ang != 0.f || os != 0.f || ot != 0.f || ms != 1.f || mt != 1.f) { do_xform = true; } else { do_xform = false; } } else { do_xform = false; } //bump setup LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f ); LLVector4a bump_s_primary_light_ray(0.f, 0.f, 0.f); LLVector4a bump_t_primary_light_ray(0.f, 0.f, 0.f); LLQuaternion bump_quat; if (mDrawablep->isActive()) { bump_quat = LLQuaternion(mDrawablep->getRenderMatrix()); } if (bump_code) { mVObjp->getVolume()->genBinormals(f); F32 offset_multiple; switch( bump_code ) { case BE_NO_BUMP: offset_multiple = 0.f; break; case BE_BRIGHTNESS: case BE_DARKNESS: if( mTexture.notNull() && mTexture->hasGLTexture()) { // Offset by approximately one texel S32 cur_discard = mTexture->getDiscardLevel(); S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() ); max_size <<= cur_discard; const F32 ARTIFICIAL_OFFSET = 2.f; offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; } else { offset_multiple = 1.f/256; } break; default: // Standard bumpmap textures. Assumed to be 256x256 offset_multiple = 1.f / 256; break; } F32 s_scale = 1.f; F32 t_scale = 1.f; if( tep ) { tep->getScale( &s_scale, &t_scale ); } // Use the nudged south when coming from above sun angle, such // that emboss mapping always shows up on the upward faces of cubes when // it's noon (since a lot of builders build with the sun forced to noon). LLVector3 sun_ray = gSky.mVOSkyp->mBumpSunDir; LLVector3 moon_ray = gSky.getMoonDirection(); LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV); bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV); } U8 texgen = getTextureEntry()->getTexGen(); if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT) { //planar texgen needs binormals mVObjp->getVolume()->genBinormals(f); } U8 tex_mode = 0; if (isState(TEXTURE_ANIM)) { LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp; tex_mode = vobj->mTexAnimMode; if (!tex_mode) { clearState(TEXTURE_ANIM); } else { os = ot = 0.f; r = 0.f; cos_ang = 1.f; sin_ang = 0.f; ms = mt = 1.f; do_xform = false; } if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) { //don't override texture transform during tc bake tex_mode = 0; } } LLVector4a scalea; scalea.load3(scale.mV); bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); bool do_tex_mat = tex_mode && mTextureMatrix; if (!do_bump) { //not in atlas or not bump mapped, might be able to do a cheap update mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex); if (texgen != LLTextureEntry::TEX_GEN_PLANAR) { if (!do_tex_mat) { if (!do_xform) { tex_coords.assignArray((U8*) vf.mTexCoords, sizeof(vf.mTexCoords[0]), num_vertices); } else { for (S32 i = 0; i < num_vertices; i++) { LLVector2 tc(vf.mTexCoords[i]); xform(tc, cos_ang, sin_ang, os, ot, ms, mt); *tex_coords++ = tc; } } } else { //do tex mat, no texgen, no atlas, no bump for (S32 i = 0; i < num_vertices; i++) { LLVector2 tc(vf.mTexCoords[i]); //LLVector4a& norm = vf.mNormals[i]; //LLVector4a& center = *(vf.mCenter); LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); tmp = tmp * *mTextureMatrix; tc.mV[0] = tmp.mV[0]; tc.mV[1] = tmp.mV[1]; *tex_coords++ = tc; } } } else { //no bump, no atlas, tex gen planar if (do_tex_mat) { for (S32 i = 0; i < num_vertices; i++) { LLVector2 tc(vf.mTexCoords[i]); LLVector4a& norm = vf.mNormals[i]; LLVector4a& center = *(vf.mCenter); LLVector4a vec = vf.mPositions[i]; vec.mul(scalea); planarProjection(tc, norm, center, vec); LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); tmp = tmp * *mTextureMatrix; tc.mV[0] = tmp.mV[0]; tc.mV[1] = tmp.mV[1]; *tex_coords++ = tc; } } else { for (S32 i = 0; i < num_vertices; i++) { LLVector2 tc(vf.mTexCoords[i]); LLVector4a& norm = vf.mNormals[i]; LLVector4a& center = *(vf.mCenter); LLVector4a vec = vf.mPositions[i]; vec.mul(scalea); planarProjection(tc, norm, center, vec); xform(tc, cos_ang, sin_ang, os, ot, ms, mt); *tex_coords++ = tc; } } } //mVertexBuffer->setBuffer(0); } else { //either bump mapped or in atlas, just do the whole expensive loop mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex); std::vector<LLVector2> bump_tc; for (S32 i = 0; i < num_vertices; i++) { LLVector2 tc(vf.mTexCoords[i]); LLVector4a& norm = vf.mNormals[i]; LLVector4a& center = *(vf.mCenter); if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) { LLVector4a vec = vf.mPositions[i]; vec.mul(scalea); switch (texgen) { case LLTextureEntry::TEX_GEN_PLANAR: planarProjection(tc, norm, center, vec); break; case LLTextureEntry::TEX_GEN_SPHERICAL: sphericalProjection(tc, norm, center, vec); break; case LLTextureEntry::TEX_GEN_CYLINDRICAL: cylindricalProjection(tc, norm, center, vec); break; default: break; } } if (tex_mode && mTextureMatrix) { LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); tmp = tmp * *mTextureMatrix; tc.mV[0] = tmp.mV[0]; tc.mV[1] = tmp.mV[1]; } else { xform(tc, cos_ang, sin_ang, os, ot, ms, mt); } *tex_coords++ = tc; if (do_bump) { bump_tc.push_back(tc); } } //mVertexBuffer->setBuffer(0); if (do_bump) { mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex); for (S32 i = 0; i < num_vertices; i++) { LLVector4a tangent; tangent.setCross3(vf.mBinormals[i], vf.mNormals[i]); LLMatrix4a tangent_to_object; tangent_to_object.setRows(tangent, vf.mBinormals[i], vf.mNormals[i]); LLVector4a t; tangent_to_object.rotate(binormal_dir, t); LLVector4a binormal; mat_normal.rotate(t, binormal); //VECTORIZE THIS if (mDrawablep->isActive()) { LLVector3 t; t.set(binormal.getF32ptr()); t *= bump_quat; binormal.load3(t.mV); } binormal.normalize3fast(); LLVector2 tc = bump_tc[i]; tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() ); *tex_coords2++ = tc; } //mVertexBuffer->setBuffer(0); } } } if (rebuild_pos) { llassert(num_vertices > 0); mVertexBuffer->getVertexStrider(vertices, mGeomIndex); LLMatrix4a mat_vert; mat_vert.loadu(mat_vert_in); LLVector4a* src = vf.mPositions; LLVector4a position; for (S32 i = 0; i < num_vertices; i++) { mat_vert.affineTransform(src[i], position); vertices[i].set(position.getF32ptr()); } //mVertexBuffer->setBuffer(0); } if (rebuild_normal) { mVertexBuffer->getNormalStrider(normals, mGeomIndex); for (S32 i = 0; i < num_vertices; i++) { LLVector4a normal; mat_normal.rotate(vf.mNormals[i], normal); normal.normalize3fast(); normals[i].set(normal.getF32ptr()); } //mVertexBuffer->setBuffer(0); } if (rebuild_binormal) { mVertexBuffer->getBinormalStrider(binormals, mGeomIndex); for (S32 i = 0; i < num_vertices; i++) { LLVector4a binormal; mat_normal.rotate(vf.mBinormals[i], binormal); binormal.normalize3fast(); binormals[i].set(binormal.getF32ptr()); } //mVertexBuffer->setBuffer(0); } #if MESH_ENABLED if (rebuild_weights && vf.mWeights) { mVertexBuffer->getWeight4Strider(weights, mGeomIndex); weights.assignArray((U8*) vf.mWeights, sizeof(vf.mWeights[0]), num_vertices); //mVertexBuffer->setBuffer(0); } #endif //MESH_ENABLED if (rebuild_color) { mVertexBuffer->getColorStrider(colors, mGeomIndex); for (S32 i = 0; i < num_vertices; i++) { colors[i] = color; } //mVertexBuffer->setBuffer(0); } if (rebuild_tcoord) { mTexExtents[0].setVec(0,0); mTexExtents[1].setVec(1,1); xform(mTexExtents[0], cos_ang, sin_ang, os, ot, ms, mt); xform(mTexExtents[1], cos_ang, sin_ang, os, ot, ms, mt); F32 es = vf.mTexCoordExtents[1].mV[0] - vf.mTexCoordExtents[0].mV[0] ; F32 et = vf.mTexCoordExtents[1].mV[1] - vf.mTexCoordExtents[0].mV[1] ; mTexExtents[0][0] *= es ; mTexExtents[1][0] *= es ; mTexExtents[0][1] *= et ; mTexExtents[1][1] *= et ; } mLastVertexBuffer = mVertexBuffer; mLastGeomCount = mGeomCount; mLastGeomIndex = mGeomIndex; mLastIndicesCount = mIndicesCount; mLastIndicesIndex = mIndicesIndex; return TRUE; }