diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index ddfa38336f..0c896dc182 100644
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -2145,10 +2145,21 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit)
}
// [/RLVa:KB]
+// FIRE-33613: [OpenSim] [PBR] Camera cannot be located at negative Z
+ F32 camera_ground_plane = F_ALMOST_ZERO;
+#ifdef OPENSIM
+ // integrate OpenSimExtras.MinSimHeight into the camera ground plane calculation
+ if (auto regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global))
+ {
+ camera_ground_plane += regionp->getMinSimHeight();
+ }
+#endif
+//
+
// Don't let camera go underground
F32 camera_min_off_ground = getCameraMinOffGround();
camera_land_height = LLWorld::getInstance()->resolveLandHeightGlobal(camera_position_global);
- F32 minZ = llmax(F_ALMOST_ZERO, camera_land_height + camera_min_off_ground);
+ F32 minZ = llmax(camera_ground_plane, camera_land_height + camera_min_off_ground);
if (camera_position_global.mdV[VZ] < minZ)
{
camera_position_global.mdV[VZ] = minZ;
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 920ec2f8fd..efba2669ef 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -675,7 +675,8 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
//
// Aurora Sim
mWidth(region_width_meters),
- mWidthScaleFactor(region_width_meters / REGION_WIDTH_METERS) // FIRE-19563: Scaling for OpenSim VarRegions
+ mWidthScaleFactor(region_width_meters / REGION_WIDTH_METERS), // FIRE-19563: Scaling for OpenSim VarRegions
+ mMinSimHeight(0.f) // FIRE-33613: [OpenSim] [PBR] Camera cannot be located at negative Z
{
// Moved this up... -> mWidth = region_width_meters;
//
@@ -2632,6 +2633,11 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features)
mMaxTEs = LLAvatarAppearanceDefines::ETextureIndex::TEX_NUM_INDICES;
#endif // OPENSIM
//
+// FIRE-33613: [OpenSim] [PBR] Camera cannot be located at negative Z
+#ifdef OPENSIM
+ mMinSimHeight = !mSimulatorFeatures.has("OpenSimExtras") ? 0.0f : mSimulatorFeatures["OpenSimExtras"]["MinSimHeight"].asReal();
+#endif
+//
}
//this is called when the parent is not cacheable.
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 928a6909d8..49138d3243 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -249,6 +249,7 @@ public:
F32 getWidth() const { return mWidth; }
F32 getWidthScaleFactor() const { return mWidthScaleFactor; } // FIRE-19563: Scaling for OpenSim VarRegions
+ F32 getMinSimHeight() const { return mMinSimHeight; } // FIRE-33613: [OpenSim] [PBR] Camera cannot be located at negative Z
// regions are expensive to release, this function gradually releases cache from memory
static void idleCleanup(F32 max_update_time);
@@ -548,7 +549,8 @@ public:
S32 mLastUpdate; //last time called idleUpdate()
F32 mWidthScaleFactor; // FIRE-19563: Scaling for OpenSim VarRegions
S32 mMaxBakes; // store max bakes on the region
- S32 mMaxTEs; // store max bakes on the region
+ S32 mMaxTEs; // store max texture entries on the region
+ F32 mMinSimHeight; // FIRE-33613: [OpenSim] [PBR] Camera cannot be located at negative Z
// simulator name
std::string mName;
std::string mZoning;