summaryrefslogtreecommitdiff
path: root/indra/newview/llvlcomposition.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llvlcomposition.cpp')
-rw-r--r--indra/newview/llvlcomposition.cpp725
1 files changed, 420 insertions, 305 deletions
diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp
index c3334866a5..077e6e6cb1 100644
--- a/indra/newview/llvlcomposition.cpp
+++ b/indra/newview/llvlcomposition.cpp
@@ -28,47 +28,427 @@
#include "llvlcomposition.h"
+#include <functional>
+
#include "llerror.h"
#include "v3math.h"
#include "llsurface.h"
#include "lltextureview.h"
#include "llviewertexture.h"
#include "llviewertexturelist.h"
+#include "llfetchedgltfmaterial.h"
+#include "llgltfmateriallist.h"
#include "llviewerregion.h"
#include "noise.h"
#include "llregionhandle.h" // for from_region_handle
#include "llviewercontrol.h"
+extern LLColor4U MAX_WATER_COLOR;
+
+static const U32 BASE_SIZE = 128;
+static const F32 TERRAIN_DECODE_PRIORITY = 2048.f * 2048.f;
-F32 bilinear(const F32 v00, const F32 v01, const F32 v10, const F32 v11, const F32 x_frac, const F32 y_frac)
+namespace
{
- // Not sure if this is the right math...
- // Take weighted average of all four points (bilinear interpolation)
- F32 result;
+ F32 bilinear(const F32 v00, const F32 v01, const F32 v10, const F32 v11, const F32 x_frac, const F32 y_frac)
+ {
+ // Not sure if this is the right math...
+ // Take weighted average of all four points (bilinear interpolation)
+ F32 result;
+
+ const F32 inv_x_frac = 1.f - x_frac;
+ const F32 inv_y_frac = 1.f - y_frac;
+ result = inv_x_frac*inv_y_frac*v00
+ + x_frac*inv_y_frac*v10
+ + inv_x_frac*y_frac*v01
+ + x_frac*y_frac*v11;
+
+ return result;
+ }
+
+ void boost_minimap_texture(LLViewerFetchedTexture* tex, F32 virtual_size)
+ {
+ llassert(tex);
+ if (!tex) { return; }
+
+ tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case the raw image is at low detail
+ tex->addTextureStats(virtual_size); // priority
+ }
- const F32 inv_x_frac = 1.f - x_frac;
- const F32 inv_y_frac = 1.f - y_frac;
- result = inv_x_frac*inv_y_frac*v00
- + x_frac*inv_y_frac*v10
- + inv_x_frac*y_frac*v01
- + x_frac*y_frac*v11;
+ void boost_minimap_material(LLFetchedGLTFMaterial* mat, F32 virtual_size)
+ {
+ if (!mat) { return; }
+ if (mat->mBaseColorTexture) { boost_minimap_texture(mat->mBaseColorTexture, virtual_size); }
+ if (mat->mNormalTexture) { boost_minimap_texture(mat->mNormalTexture, virtual_size); }
+ if (mat->mMetallicRoughnessTexture) { boost_minimap_texture(mat->mMetallicRoughnessTexture, virtual_size); }
+ if (mat->mEmissiveTexture) { boost_minimap_texture(mat->mEmissiveTexture, virtual_size); }
+ }
+
+ void unboost_minimap_texture(LLViewerFetchedTexture* tex)
+ {
+ if (!tex) { return; }
+ tex->setBoostLevel(LLGLTexture::BOOST_NONE);
+ tex->setMinDiscardLevel(MAX_DISCARD_LEVEL + 1);
+ }
- return result;
+ void unboost_minimap_material(LLFetchedGLTFMaterial* mat)
+ {
+ if (!mat) { return; }
+ if (mat->mBaseColorTexture) { unboost_minimap_texture(mat->mBaseColorTexture); }
+ if (mat->mNormalTexture) { unboost_minimap_texture(mat->mNormalTexture); }
+ if (mat->mMetallicRoughnessTexture) { unboost_minimap_texture(mat->mMetallicRoughnessTexture); }
+ if (mat->mEmissiveTexture) { unboost_minimap_texture(mat->mEmissiveTexture); }
+ }
+};
+
+LLTerrainMaterials::LLTerrainMaterials()
+{
+ for (S32 i = 0; i < ASSET_COUNT; ++i)
+ {
+ mMaterialTexturesSet[i] = false;
+ }
}
+LLTerrainMaterials::~LLTerrainMaterials()
+{
+ unboost();
+}
-LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale) :
- LLViewerLayer(width, scale),
- mParamsReady(FALSE)
+void LLTerrainMaterials::apply(const LLModifyRegion& other)
{
- mSurfacep = surfacep;
+ for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i)
+ {
+ const LLGLTFMaterial* other_override = other.getMaterialOverride(i);
+ LLGLTFMaterial* material_override = other_override ? new LLGLTFMaterial(*other_override) : nullptr;
+ setMaterialOverride(i, material_override);
+ }
+}
+
+bool LLTerrainMaterials::generateMaterials()
+{
+ if (makeTexturesReady(true, true))
+ {
+ return true;
+ }
+
+ if (makeMaterialsReady(true, true))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+void LLTerrainMaterials::boost()
+{
+ for (S32 i = 0; i < ASSET_COUNT; ++i)
+ {
+ LLPointer<LLViewerFetchedTexture>& tex = mDetailTextures[i];
+ llassert(tex.notNull());
+ boost_minimap_texture(tex, TERRAIN_DECODE_PRIORITY);
+
+ LLPointer<LLFetchedGLTFMaterial>& mat = mDetailMaterials[i];
+ boost_minimap_material(mat, TERRAIN_DECODE_PRIORITY);
+ }
+}
+
+void LLTerrainMaterials::unboost()
+{
+ for (S32 i = 0; i < ASSET_COUNT; ++i)
+ {
+ LLPointer<LLViewerFetchedTexture>& tex = mDetailTextures[i];
+ unboost_minimap_texture(tex);
+
+ LLPointer<LLFetchedGLTFMaterial>& mat = mDetailMaterials[i];
+ unboost_minimap_material(mat);
+ }
+}
+
+LLUUID LLTerrainMaterials::getDetailAssetID(S32 asset)
+{
+ llassert(mDetailTextures[asset] && mDetailMaterials[asset]);
+ // Assume both the the material and texture were fetched in the same way
+ // using the same UUID. However, we may not know at this point which one
+ // will load.
+ return mDetailTextures[asset] ? mDetailTextures[asset]->getID() : LLUUID::null;
+}
+
+LLPointer<LLViewerFetchedTexture> fetch_terrain_texture(const LLUUID& id)
+{
+ if (id.isNull())
+ {
+ return nullptr;
+ }
+
+ LLPointer<LLViewerFetchedTexture> tex = LLViewerTextureManager::getFetchedTexture(id);
+ return tex;
+}
+
+void LLTerrainMaterials::setDetailAssetID(S32 asset, const LLUUID& id)
+{
+ // *NOTE: If there were multiple terrain swatches using the same asset
+ // ID, the asset still in use will be temporarily unboosted.
+ // It will be boosted again during terrain rendering.
+ unboost_minimap_texture(mDetailTextures[asset]);
+ unboost_minimap_material(mDetailMaterials[asset]);
+
+ // This is terrain texture, but we are not setting it as BOOST_TERRAIN
+ // since we will be manipulating it later as needed.
+ mDetailTextures[asset] = fetch_terrain_texture(id);
+ LLPointer<LLFetchedGLTFMaterial>& mat = mDetailMaterials[asset];
+ mat = id.isNull() ? nullptr : gGLTFMaterialList.getMaterial(id);
+ mDetailRenderMaterials[asset] = nullptr;
+ mMaterialTexturesSet[asset] = false;
+}
+
+const LLGLTFMaterial* LLTerrainMaterials::getMaterialOverride(S32 asset) const
+{
+ return mDetailMaterialOverrides[asset];
+}
+
+void LLTerrainMaterials::setMaterialOverride(S32 asset, LLGLTFMaterial* mat_override)
+{
+ // Non-null overrides must be nontrivial. Otherwise, please set the override to null instead.
+ llassert(!mat_override || *mat_override != LLGLTFMaterial::sDefault);
+
+ mDetailMaterialOverrides[asset] = mat_override;
+ mDetailRenderMaterials[asset] = nullptr;
+}
+
+LLTerrainMaterials::Type LLTerrainMaterials::getMaterialType()
+{
+ LL_PROFILE_ZONE_SCOPED;
+
+ const bool use_textures = makeTexturesReady(false, false) || !makeMaterialsReady(false, false);
+ return use_textures ? Type::TEXTURE : Type::PBR;
+}
+
+bool LLTerrainMaterials::makeTexturesReady(bool boost, bool strict)
+{
+ bool ready[ASSET_COUNT];
+ // *NOTE: Calls to makeTextureReady may boost textures. Do not early-return.
+ for (S32 i = 0; i < ASSET_COUNT; i++)
+ {
+ ready[i] = mDetailTextures[i].notNull() && makeTextureReady(mDetailTextures[i], boost);
+ }
+
+ bool one_ready = false;
+ for (S32 i = 0; i < ASSET_COUNT; i++)
+ {
+ const bool current_ready = ready[i];
+ one_ready = one_ready || current_ready;
+ if (!current_ready && strict)
+ {
+ return false;
+ }
+ }
+ return one_ready;
+}
+
+namespace
+{
+ bool material_asset_ready(LLFetchedGLTFMaterial* mat) { return mat && mat->isLoaded(); }
+};
+
+bool LLTerrainMaterials::makeMaterialsReady(bool boost, bool strict)
+{
+ bool ready[ASSET_COUNT];
+ // *NOTE: This section may boost materials/textures. Do not early-return if ready[i] is false.
+ for (S32 i = 0; i < ASSET_COUNT; i++)
+ {
+ ready[i] = false;
+ LLPointer<LLFetchedGLTFMaterial>& mat = mDetailMaterials[i];
+ if (!material_asset_ready(mat)) { continue; }
+
+ LLPointer<LLFetchedGLTFMaterial>& render_mat = mDetailRenderMaterials[i];
+ if (!render_mat)
+ {
+ render_mat = new LLFetchedGLTFMaterial();
+ *render_mat = *mat;
+ // This render_mat is effectively already loaded, because it gets its data from mat.
+
+ LLPointer<LLGLTFMaterial>& override_mat = mDetailMaterialOverrides[i];
+ if (override_mat)
+ {
+ render_mat->applyOverride(*override_mat);
+ }
+ }
+
+ ready[i] = materialTexturesReady(render_mat, mMaterialTexturesSet[i], boost, strict);
+ }
+
+#if 1
+ static LLCachedControl<bool> sRenderTerrainPBREnabled(gSavedSettings, "RenderTerrainPBREnabled", false);
+ static LLCachedControl<bool> sRenderTerrainPBRForce(gSavedSettings, "RenderTerrainPBRForce", false);
+ if (sRenderTerrainPBREnabled && sRenderTerrainPBRForce)
+ {
+ bool defined = true;
+ for (S32 i = 0; i < ASSET_COUNT; i++)
+ {
+ if (!mDetailMaterials[i])
+ {
+ defined = false;
+ break;
+ }
+ }
+ if (defined)
+ {
+ return true;
+ }
+ }
+#endif
+
+ bool one_ready = false;
+ for (S32 i = 0; i < ASSET_COUNT; i++)
+ {
+ const bool current_ready = ready[i];
+ one_ready = one_ready || current_ready;
+ if (!current_ready && strict)
+ {
+ return false;
+ }
+ }
+ return one_ready;
+}
+
+LLViewerTexture* LLTerrainMaterials::getPaintMap()
+{
+ return mPaintMap.get();
+}
+
+void LLTerrainMaterials::setPaintMap(LLViewerTexture* paint_map)
+{
+ llassert(!paint_map || mPaintType == TERRAIN_PAINT_TYPE_PBR_PAINTMAP);
+ mPaintMap = paint_map;
+}
+
+// Boost the texture loading priority
+// Return true when ready to use (i.e. texture is sufficiently loaded)
+// static
+bool LLTerrainMaterials::makeTextureReady(LLPointer<LLViewerFetchedTexture>& tex, bool boost)
+{
+ //llassert(tex); ??? maybe ok ???
+ if (!tex) { return false; }
+
+ if (tex->getDiscardLevel() < 0)
+ {
+ if (boost)
+ {
+ boost_minimap_texture(tex, BASE_SIZE*BASE_SIZE);
+ }
+ return false;
+ }
+ if ((tex->getDiscardLevel() != 0 &&
+ (tex->getWidth() < BASE_SIZE ||
+ tex->getHeight() < BASE_SIZE)))
+ {
+ if (boost)
+ {
+ boost_minimap_texture(tex, BASE_SIZE*BASE_SIZE);
+
+ S32 width = tex->getFullWidth();
+ S32 height = tex->getFullHeight();
+ S32 min_dim = llmin(width, height);
+ S32 ddiscard = 0;
+ while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
+ {
+ ddiscard++;
+ min_dim /= 2;
+ }
+ tex->setMinDiscardLevel(ddiscard);
+ }
+ return false;
+ }
+ if (tex->getComponents() == 0)
+ {
+ return false;
+ }
+ return true;
+}
+
+// Make sure to call material_asset_ready first
+// strict = true -> all materials must be sufficiently loaded
+// strict = false -> at least one material must be loaded
+// static
+bool LLTerrainMaterials::materialTexturesReady(LLPointer<LLFetchedGLTFMaterial>& mat, bool& textures_set, bool boost, bool strict)
+{
+ llassert(mat);
+
+ // Material is loaded, but textures may not be
+ if (!textures_set)
+ {
+ textures_set = true;
+ // *NOTE: These can sometimes be set to to nullptr due to
+ // updateTEMaterialTextures. For the sake of robustness, we emulate
+ // that fetching behavior by setting textures of null IDs to nullptr.
+ mat->mBaseColorTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]);
+ mat->mNormalTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL]);
+ mat->mMetallicRoughnessTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS]);
+ mat->mEmissiveTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]);
+ }
+
+ // *NOTE: Calls to makeTextureReady may boost textures. Do not early-return.
+ bool ready[LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT];
+ ready[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] =
+ mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].isNull() || makeTextureReady(mat->mBaseColorTexture, boost);
+ ready[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] =
+ mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].isNull() || makeTextureReady(mat->mNormalTexture, boost);
+ ready[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] =
+ mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].isNull() ||
+ makeTextureReady(mat->mMetallicRoughnessTexture, boost);
+ ready[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] =
+ mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].isNull() || makeTextureReady(mat->mEmissiveTexture, boost);
+
+ if (strict)
+ {
+ for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i)
+ {
+ if (!ready[i])
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+// Boost the loading priority of every known texture in the material
+// Return true when ready to use
+// static
+bool LLTerrainMaterials::makeMaterialReady(LLPointer<LLFetchedGLTFMaterial> &mat, bool &textures_set, bool boost, bool strict)
+{
+ if (!material_asset_ready(mat)) { return false; }
+
+ return materialTexturesReady(mat, textures_set, boost, strict);
+}
+
+// static
+const LLUUID (&LLVLComposition::getDefaultTextures())[ASSET_COUNT]
+{
+ const static LLUUID default_textures[LLVLComposition::ASSET_COUNT] =
+ {
+ TERRAIN_DIRT_DETAIL,
+ TERRAIN_GRASS_DETAIL,
+ TERRAIN_MOUNTAIN_DETAIL,
+ TERRAIN_ROCK_DETAIL
+ };
+ return default_textures;
+}
+
+LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale) :
+ LLTerrainMaterials(),
+ LLViewerLayer(width, scale)
+{
// Load Terrain Textures - Original ones
- setDetailTextureID(0, TERRAIN_DIRT_DETAIL);
- setDetailTextureID(1, TERRAIN_GRASS_DETAIL);
- setDetailTextureID(2, TERRAIN_MOUNTAIN_DETAIL);
- setDetailTextureID(3, TERRAIN_ROCK_DETAIL);
+ const LLUUID (&default_textures)[LLVLComposition::ASSET_COUNT] = LLVLComposition::getDefaultTextures();
+ for (S32 i = 0; i < ASSET_COUNT; ++i)
+ {
+ setDetailAssetID(i, default_textures[i]);
+ }
+
+ mSurfacep = surfacep;
// Initialize the texture matrix to defaults.
for (S32 i = 0; i < CORNER_COUNT; ++i)
@@ -76,14 +456,12 @@ LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32
mStartHeight[i] = gSavedSettings.getF32("TerrainColorStartHeight");
mHeightRange[i] = gSavedSettings.getF32("TerrainColorHeightRange");
}
- mTexScaleX = 16.f;
- mTexScaleY = 16.f;
- mTexturesLoaded = FALSE;
}
LLVLComposition::~LLVLComposition()
{
+ LLTerrainMaterials::~LLTerrainMaterials();
}
@@ -92,27 +470,13 @@ void LLVLComposition::setSurface(LLSurface *surfacep)
mSurfacep = surfacep;
}
-
-void LLVLComposition::setDetailTextureID(S32 corner, const LLUUID& id)
-{
- if(id.isNull())
- {
- return;
- }
- // This is terrain texture, but we are not setting it as BOOST_TERRAIN
- // since we will be manipulating it later as needed.
- mDetailTextures[corner] = LLViewerTextureManager::getFetchedTexture(id);
- mDetailTextures[corner]->setNoDelete() ;
- mRawImages[corner] = NULL;
-}
-
-BOOL LLVLComposition::generateHeights(const F32 x, const F32 y,
+bool LLVLComposition::generateHeights(const F32 x, const F32 y,
const F32 width, const F32 height)
{
if (!mParamsReady)
{
// All the parameters haven't been set yet (we haven't gotten the message from the sim)
- return FALSE;
+ return false;
}
llassert(mSurfacep);
@@ -120,7 +484,7 @@ BOOL LLVLComposition::generateHeights(const F32 x, const F32 y,
if (!mSurfacep || !mSurfacep->getRegion())
{
// We don't always have the region yet here....
- return FALSE;
+ return false;
}
S32 x_begin, y_begin, x_end, y_end;
@@ -149,10 +513,6 @@ BOOL LLVLComposition::generateHeights(const F32 x, const F32 y,
const F32 noise_magnitude = 2.f; // Degree to which noise modulates composition layer (versus
// simple height)
- // Heights map into textures as 0-1 = first, 1-2 = second, etc.
- // So we need to compress heights into this range.
- const S32 NUM_TEXTURES = 4;
-
const F32 xyScaleInv = (1.f / xyScale);
const F32 zScaleInv = (1.f / zScale);
@@ -199,289 +559,44 @@ BOOL LLVLComposition::generateHeights(const F32 x, const F32 y,
twiddle += turbulence2(vec, 2)*slope_squared; // High frequency component
twiddle *= noise_magnitude;
- F32 scaled_noisy_height = (height + twiddle - start_height) * F32(NUM_TEXTURES) / height_range;
+ F32 scaled_noisy_height = (height + twiddle - start_height) * F32(ASSET_COUNT) / height_range;
scaled_noisy_height = llmax(0.f, scaled_noisy_height);
scaled_noisy_height = llmin(3.f, scaled_noisy_height);
*(mDatap + i + j*mWidth) = scaled_noisy_height;
}
}
- return TRUE;
+ return true;
}
-static const U32 BASE_SIZE = 128;
+LLTerrainMaterials gLocalTerrainMaterials;
-BOOL LLVLComposition::generateComposition()
+bool LLVLComposition::generateComposition()
{
-
if (!mParamsReady)
{
// All the parameters haven't been set yet (we haven't gotten the message from the sim)
- return FALSE;
- }
-
- for (S32 i = 0; i < 4; i++)
- {
- if (mDetailTextures[i]->getDiscardLevel() < 0)
- {
- mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail
- mDetailTextures[i]->addTextureStats(BASE_SIZE*BASE_SIZE);
- return FALSE;
- }
- if ((mDetailTextures[i]->getDiscardLevel() != 0 &&
- (mDetailTextures[i]->getWidth() < BASE_SIZE ||
- mDetailTextures[i]->getHeight() < BASE_SIZE)))
- {
- S32 width = mDetailTextures[i]->getFullWidth();
- S32 height = mDetailTextures[i]->getFullHeight();
- S32 min_dim = llmin(width, height);
- S32 ddiscard = 0;
- while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
- {
- ddiscard++;
- min_dim /= 2;
- }
- mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail
- mDetailTextures[i]->setMinDiscardLevel(ddiscard);
- mDetailTextures[i]->addTextureStats(BASE_SIZE*BASE_SIZE); // priority
- return FALSE;
- }
+ return false;
}
- return TRUE;
+ return LLTerrainMaterials::generateMaterials();
}
-BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
- const F32 width, const F32 height)
-{
- LL_PROFILE_ZONE_SCOPED
- llassert(mSurfacep);
- llassert(x >= 0.f);
- llassert(y >= 0.f);
-
- LLTimer gen_timer;
-
- ///////////////////////////
- //
- // Generate raw data arrays for surface textures
- //
- //
-
- // These have already been validated by generateComposition.
- U8* st_data[4];
- S32 st_data_size[4]; // for debugging
-
- for (S32 i = 0; i < 4; i++)
- {
- if (mRawImages[i].isNull())
- {
- // Read back a raw image for this discard level, if it exists
- S32 min_dim = llmin(mDetailTextures[i]->getFullWidth(), mDetailTextures[i]->getFullHeight());
- S32 ddiscard = 0;
- while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
- {
- ddiscard++;
- min_dim /= 2;
- }
-
- BOOL delete_raw = (mDetailTextures[i]->reloadRawImage(ddiscard) != NULL) ;
- if(mDetailTextures[i]->getRawImageLevel() != ddiscard)//raw iamge is not ready, will enter here again later.
- {
- if (mDetailTextures[i]->getFetchPriority() <= 0.0f && !mDetailTextures[i]->hasSavedRawImage())
- {
- mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_MAP);
- mDetailTextures[i]->forceToRefetchTexture(ddiscard);
- }
-
- if(delete_raw)
- {
- mDetailTextures[i]->destroyRawImage() ;
- }
- LL_DEBUGS("Terrain") << "cached raw data for terrain detail texture is not ready yet: " << mDetailTextures[i]->getID() << " Discard: " << ddiscard << LL_ENDL;
- return FALSE;
- }
-
- mRawImages[i] = mDetailTextures[i]->getRawImage() ;
- if(delete_raw)
- {
- mDetailTextures[i]->destroyRawImage() ;
- }
- if (mDetailTextures[i]->getWidth(ddiscard) != BASE_SIZE ||
- mDetailTextures[i]->getHeight(ddiscard) != BASE_SIZE ||
- mDetailTextures[i]->getComponents() != 3)
- {
- LLPointer<LLImageRaw> newraw = new LLImageRaw(BASE_SIZE, BASE_SIZE, 3);
- newraw->composite(mRawImages[i]);
- mRawImages[i] = newraw; // deletes old
- }
- }
- st_data[i] = mRawImages[i]->getData();
- st_data_size[i] = mRawImages[i]->getDataSize();
- }
-
- ///////////////////////////////////////
- //
- // Generate and clamp x/y bounding box.
- //
- //
-
- S32 x_begin, y_begin, x_end, y_end;
- x_begin = (S32)(x * mScaleInv);
- y_begin = (S32)(y * mScaleInv);
- x_end = ll_round( (x + width) * mScaleInv );
- y_end = ll_round( (y + width) * mScaleInv );
-
- if (x_end > mWidth)
- {
- LL_WARNS("Terrain") << "x end > width" << LL_ENDL;
- x_end = mWidth;
- }
- if (y_end > mWidth)
- {
- LL_WARNS("Terrain") << "y end > width" << LL_ENDL;
- y_end = mWidth;
- }
-
-
- ///////////////////////////////////////////
- //
- // Generate target texture information, stride ratios.
- //
- //
-
- LLViewerTexture *texturep;
- U32 tex_width, tex_height, tex_comps;
- U32 tex_stride;
- F32 tex_x_scalef, tex_y_scalef;
- S32 tex_x_begin, tex_y_begin, tex_x_end, tex_y_end;
- F32 tex_x_ratiof, tex_y_ratiof;
-
- texturep = mSurfacep->getSTexture();
- tex_width = texturep->getWidth();
- tex_height = texturep->getHeight();
- tex_comps = texturep->getComponents();
- tex_stride = tex_width * tex_comps;
-
- U32 st_comps = 3;
- U32 st_width = BASE_SIZE;
- U32 st_height = BASE_SIZE;
-
- if (tex_comps != st_comps)
- {
- LL_WARNS("Terrain") << "Base texture comps != input texture comps" << LL_ENDL;
- return FALSE;
- }
-
- tex_x_scalef = (F32)tex_width / (F32)mWidth;
- tex_y_scalef = (F32)tex_height / (F32)mWidth;
- tex_x_begin = (S32)((F32)x_begin * tex_x_scalef);
- tex_y_begin = (S32)((F32)y_begin * tex_y_scalef);
- tex_x_end = (S32)((F32)x_end * tex_x_scalef);
- tex_y_end = (S32)((F32)y_end * tex_y_scalef);
-
- tex_x_ratiof = (F32)mWidth*mScale / (F32)tex_width;
- tex_y_ratiof = (F32)mWidth*mScale / (F32)tex_height;
-
- LLPointer<LLImageRaw> raw = new LLImageRaw(tex_width, tex_height, tex_comps);
- U8 *rawp = raw->getData();
-
- F32 st_x_stride, st_y_stride;
- st_x_stride = ((F32)st_width / (F32)mTexScaleX)*((F32)mWidth / (F32)tex_width);
- st_y_stride = ((F32)st_height / (F32)mTexScaleY)*((F32)mWidth / (F32)tex_height);
-
- llassert(st_x_stride > 0.f);
- llassert(st_y_stride > 0.f);
- ////////////////////////////////
- //
- // Iterate through the target texture, striding through the
- // subtextures and interpolating appropriately.
- //
- //
-
- F32 sti, stj;
- S32 st_offset;
- sti = (tex_x_begin * st_x_stride) - st_width*(llfloor((tex_x_begin * st_x_stride)/st_width));
- stj = (tex_y_begin * st_y_stride) - st_height*(llfloor((tex_y_begin * st_y_stride)/st_height));
-
- st_offset = (llfloor(stj * st_width) + llfloor(sti)) * st_comps;
- for (S32 j = tex_y_begin; j < tex_y_end; j++)
- {
- U32 offset = j * tex_stride + tex_x_begin * tex_comps;
- sti = (tex_x_begin * st_x_stride) - st_width*((U32)(tex_x_begin * st_x_stride)/st_width);
- for (S32 i = tex_x_begin; i < tex_x_end; i++)
- {
- S32 tex0, tex1;
- F32 composition = getValueScaled(i*tex_x_ratiof, j*tex_y_ratiof);
-
- tex0 = llfloor( composition );
- tex0 = llclamp(tex0, 0, 3);
- composition -= tex0;
- tex1 = tex0 + 1;
- tex1 = llclamp(tex1, 0, 3);
-
- st_offset = (lltrunc(sti) + lltrunc(stj)*st_width) * st_comps;
- for (U32 k = 0; k < tex_comps; k++)
- {
- // Linearly interpolate based on composition.
- if (st_offset >= st_data_size[tex0] || st_offset >= st_data_size[tex1])
- {
- // SJB: This shouldn't be happening, but does... Rounding error?
- //LL_WARNS() << "offset 0 [" << tex0 << "] =" << st_offset << " >= size=" << st_data_size[tex0] << LL_ENDL;
- //LL_WARNS() << "offset 1 [" << tex1 << "] =" << st_offset << " >= size=" << st_data_size[tex1] << LL_ENDL;
- }
- else
- {
- F32 a = *(st_data[tex0] + st_offset);
- F32 b = *(st_data[tex1] + st_offset);
- rawp[ offset ] = (U8)lltrunc( a + composition * (b - a) );
- }
- offset++;
- st_offset++;
- }
-
- sti += st_x_stride;
- if (sti >= st_width)
- {
- sti -= st_width;
- }
- }
-
- stj += st_y_stride;
- if (stj >= st_height)
- {
- stj -= st_height;
- }
- }
-
- if (!texturep->hasGLTexture())
- {
- texturep->createGLTexture(0, raw);
- }
- texturep->setSubImage(raw, tex_x_begin, tex_y_begin, tex_x_end - tex_x_begin, tex_y_end - tex_y_begin);
-
- for (S32 i = 0; i < 4; i++)
- {
- // Un-boost detatil textures (will get re-boosted if rendering in high detail)
- mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_NONE);
- mDetailTextures[i]->setMinDiscardLevel(MAX_DISCARD_LEVEL + 1);
- }
-
- return TRUE;
-}
-
-LLUUID LLVLComposition::getDetailTextureID(S32 corner)
-{
- return mDetailTextures[corner]->getID();
-}
-
-LLViewerFetchedTexture* LLVLComposition::getDetailTexture(S32 corner)
+F32 LLVLComposition::getStartHeight(S32 corner)
{
- return mDetailTextures[corner];
+ return mStartHeight[corner];
}
-F32 LLVLComposition::getStartHeight(S32 corner)
+void LLVLComposition::setDetailAssetID(S32 asset, const LLUUID& id)
{
- return mStartHeight[corner];
+ if (id.isNull())
+ {
+ return;
+ }
+ LLTerrainMaterials::setDetailAssetID(asset, id);
+ mRawImages[asset] = NULL;
+ mRawImagesBaseColor[asset] = NULL;
+ mRawImagesEmissive[asset] = NULL;
}
void LLVLComposition::setStartHeight(S32 corner, const F32 start_height)