16 result.
minimum.fill(std::numeric_limits<float>::max());
17 result.
maximum.fill(-std::numeric_limits<float>::max());
18 for(
unsigned corner=0;corner<8;++corner)
20 std::array<float,3>
p{};
37 if(!std::isfinite(
groundY) || !std::isfinite(original.fieldOfView) ||
38 original.fieldOfView<=0 || original.fieldOfView>=3.14159265F ||
39 !std::isfinite(original.nearPlane) || original.nearPlane<=0 ||
40 !std::isfinite(original.farPlane) || original.farPlane<=original.nearPlane)
return original;
42 if(!std::isfinite(original.location[
axis]) || !std::isfinite(original.forward[
axis]) ||
43 !std::isfinite(original.up[
axis]))
return original;
44 if(original.forward[1]>=-0.00001F)
return original;
45 const float magnitude=std::hypot(original.forward[0],original.forward[1],original.forward[2]);
51 if(!std::isfinite(
retreat))
return original;
56 if(!std::isfinite(
adjusted.location[
axis]))
return original;
63 std::span<const data::MeshBounds> buildings,
float groundY,
68 !std::isfinite(original.nearPlane) || original.nearPlane <= 0 ||
69 !std::isfinite(original.farPlane) || original.farPlane <= original.nearPlane ||
70 !std::isfinite(original.fieldOfView) || original.fieldOfView <= 0)
return original;
72 if (!std::isfinite(original.location[
axis]) || !std::isfinite(original.forward[
axis]) ||
73 !std::isfinite(original.up[
axis]))
return original;
76 if (original.forward[1] >= -0.00001F)
return original;
80 for (
const auto& bounds : buildings)
85 std::isfinite(bounds.maximum[
axis]) && bounds.minimum[
axis] <= bounds.maximum[
axis];
87 const float dx=std::max({bounds.minimum[0]-original.location[0],0.0F,
88 original.location[0]-bounds.maximum[0]});
89 const float dz=std::max({bounds.minimum[2]-original.location[2],0.0F,
90 original.location[2]-bounds.maximum[2]});
94 const float weight=
t*
t*(3-2*
t);
95 const float needed=bounds.maximum[1]+std::max(
clearance,original.nearPlane)-original.location[1];
96 if (!std::isfinite(
needed))
return original;
99 if (
lift == 0)
return original;
100 auto result=original;
101 result.location[1]+=
lift;
102 std::array<float,3>
aim{};
110 if (!std::isfinite(result.location[1]) || !std::isfinite(
lengthSquared) ||
117 int pixelWidth,
int pixelHeight,
int controlsTop)
noexcept
121 if(!ui.valid() || !world.valid() || viewport.empty())
return 0;
124 double(viewport.bottom-viewport.top)});
125 if(pixels.height<=0)
return 0;
127 return float(std::clamp((pixels.y+pixels.height-
uiTop)/pixels.height,0.0,0.4));
133 auto dot=[](
const auto&
a,
const auto&
b){
return a[0]*
b[0]+
a[1]*
b[1]+
a[2]*
b[2];};
142 !std::isfinite(forward[
axis]) || !std::isfinite(up[
axis]))
return original;
153 const std::array<float,3>
right{up[1]*forward[2]-up[2]*forward[1],
154 up[2]*forward[0]-up[0]*forward[2],up[0]*forward[1]-up[1]*forward[0]};
155 std::array<float,3>
delta{};
159 auto camera=original;
165 for(
unsigned corner=0;corner<8;++corner)
193 const float rad = 0.01745329252F;
198 std::array<float,3> forward{-std::cos(
e)*std::sin(
a),-std::sin(
e),std::cos(
e)*std::cos(
a)};
199 std::array<float,3>
right{std::cos(
a),0,std::sin(
a)};
200 std::array<float,3> up{-std::sin(
e)*std::sin(
a),std::cos(
e),std::sin(
e)*std::cos(
a)};
201 auto dot=[](
const auto&
x,
const auto&
y){
return x[0]*
y[0]+
x[1]*
y[1]+
x[2]*
y[2];};
202 std::array<float,3>
target{};
215 for(
unsigned corner=0;corner<8;++corner)
217 std::array<float,3>
rel{};
239 lighting.
ambient={.24F,.28F,.33F};
241 lighting.
sun.
color={1.25F,1.16F,1.02F};
std::atomic< float > right
data::MeshBounds presentationWorldBounds(const data::MeshBounds &local, const sequence::Matrix3D &world)
World3DLighting modernBoardPresentationLighting()
World3DCamera fitModernTopDownBoard(const data::MeshBounds &bounds, const World3DCamera &original, float aspect, float bottomReservedFraction=0) noexcept
World3DCamera modernBoardPresentationCamera(const data::MeshBounds &bounds, float aspect, float elevationDegrees=48.0F, float yawDegrees=8.0F, float bottomReservedFraction=0.0F)
World3DCamera avoidModernPresentationBuildings(const World3DCamera &original, std::span< const data::MeshBounds > buildings, float groundY, float clearance, float influenceRadius) noexcept
float modernBoardControlReservation(const World3DRect &viewport, int pixelWidth, int pixelHeight, int controlsTop) noexcept
World3DCamera preserveModernTravelFraming(const World3DCamera &original, float groundY) noexcept
Transform makeTransform(int targetWidth, int targetHeight) noexcept
PixelRect logicalToPixelRect(const Transform &transform, const LogicalRect &logicalRect) noexcept
Transform makeWorld3DTransform(int targetWidth, int targetHeight) noexcept
std::array< float, 3 > maximum
std::array< float, 3 > minimum
std::array< float, 3 > location
std::array< float, 3 > forward
std::array< float, 3 > up
std::array< float, 3 > direction
std::array< float, 3 > color
World3DDirectionalLight sun
std::array< float, 3 > ambient
World3DDirectionalLight boardReflection
std::array< float, 16 > values