commit x64 compilation from lulu cause the other branch dont seems to compile properly at home

This commit is contained in:
2026-07-17 16:08:20 +02:00
parent c0f3eeb00d
commit 0efa4ee6f7
625 changed files with 117283 additions and 4426 deletions

View File

@ -0,0 +1,468 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "core/camera.h"
#include "core/terrain.h"
#include "core/geometry.h"
#include "core/resource_factories.h"
#include "core/render_resource_factory.h"
#include "picture/pict.h"
#include "picture/pict_io.h"
#include "filesystem/filesystem.h"
#include "log/log.h"
using namespace GS;
using namespace GS::Core;
//------------------------------------------------------------------------------
void Terrain::RenderSetup(ResourceFactories *f)
{
if (LoadHeightmap(heightmap_path))
{
ComputeNormals();
BuildQuadtree();
}
ComputeNormals();
BuildQuadtree();
if (render_data = new RenderData)
if (f && f->render)
{
render_data->blendmap = f->render->LoadTexture(blendmap_path);
render_data->material = f->render->LoadMaterial(material);
for (uint n = 0; n < 4; ++n)
{
render_data->layer[n].diffuse = f->render->LoadTexture(layer[n].diffuse);
render_data->layer[n].specular = f->render->LoadTexture(layer[n].specular);
render_data->layer[n].normal = f->render->LoadTexture(layer[n].normal);
render_data->layer[n].self = f->render->LoadTexture(layer[n].self);
}
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Terrain::LocalToTexture(const Vector4 &p, float w, float h, float &u, float &v) const
{
float lx = p.x + width * 0.5f,
lz = p.z + depth * 0.5f;
u = (lx / width) * w;
v = (lz / depth) * h;
return asbool((u >= 0) && (u < w) && (v >= 0) && (v < h));
}
bool Terrain::LocalToHeightmap(const Vector4 &p, float &u, float &v) const
{
return LocalToTexture(p, (float)heightmap_w, (float)heightmap_h, u, v);
}
float Terrain::SampleHeight(float u, float v) const
{
// Fetch samples coordinates.
int s_u[4], s_v[4];
s_u[0] = Types::Clamp(int(u), 0, heightmap_w); s_v[0] = Types::Clamp(int(v), 0, heightmap_h);
s_u[1] = Types::Clamp(s_u[0] + 1, 0, heightmap_w); s_v[1] = Types::Clamp(s_v[0] + 0, 0, heightmap_h);
s_u[2] = Types::Clamp(s_u[0] + 0, 0, heightmap_w); s_v[2] = Types::Clamp(s_v[0] + 1, 0, heightmap_h);
s_u[3] = Types::Clamp(s_u[0] + 1, 0, heightmap_w); s_v[3] = Types::Clamp(s_v[0] + 1, 0, heightmap_h);
// Fetch samples.
float s[4];
for (int n = 0; n < 4; ++n)
s[n] = heightmap[s_v[n] * GetHeightmapPitch() + s_u[n]];
// Bilinear.
float k_u = u - int(u), k_v = v - (int)v;
return (s[0] * (1 - k_u) + s[1] * k_u) * (1 - k_v) + (s[2] * (1 - k_u) + s[3] * k_u) * k_v;
}
float Terrain::SampleHeight(const Vector4 &p) const
{
float u, v;
if (!LocalToHeightmap(p, u, v))
return 0;
return SampleHeight(u, v);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Terrain::ComputeRenderableMinMax(MinMax &mm)
{
if (root_node)
{
OBB obb(root_node->minmax);
obb.Transform(GetMatrix());
obb.ComputeMinMax(mm);
}
}
void Terrain::CullRenderablePrimitiveList(const Camera &view, const Camera &default_view, Stack <Render::Primitive *> &list, Context context, Patch *node)
{
MinMax &minmax = node->minmax;
if (view.frustum.ClassifyMinMax(minmax, &GetMatrix()) == Frustum::Outside)
return;
// Check error for the current level.
Vector4 center = minmax.GetCenter() * GetMatrix();
float lod_d = (minmax.mx - minmax.mn).Len() * 1.5f,
/*v_d = nVector::Dist(center, view.GetMatrix().GetRow(3)),*/
d_d = Vector4::Dist(center, default_view.GetMatrix().GetRow(3));
float d = d_d;// Types::Min(v_d, d_d); // Ensure high-resolution close to the viewer and the light source.
if ((d > lod_d) || !node->children[0])
list.Push(new Render::Primitive(node, this, 0));
else
for (int n = 0; n < 4; ++n)
if (node->children[n])
CullRenderablePrimitiveList(view, default_view, list, context, node->children[n]);
}
uint Terrain::GetRenderablePrimitiveList(const Camera &view, const Camera &default_view, Stack <Render::Primitive *> &list, Context context, bool nUnused(cull))
{
if (root_node)
CullRenderablePrimitiveList(view, default_view, list, context, root_node);
return node_count;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Geometry *Terrain::CreateNodeGeometry(const Patch *node)
{
Geometry *geometry = new Geometry;
int patch_w = node->w / node->decimation,
patch_h = node->h / node->decimation;
// Create vertices.
geometry->vtx.Allocate((patch_w + 1) * (patch_h + 1));
float step_w = width / heightmap_w, step_h = depth / heightmap_h;
Vector4 p(node->u * step_w * GetUnit(), 0, -node->v * step_h * GetUnit()),
*pv = geometry->vtx;
for (int _v = node->v; _v <= (node->v + node->h); _v += node->decimation)
{
float *ph = &heightmap[_v * heightmap_w + node->u];
for (int _u = node->u; _u <= (node->u + node->w); _u += node->decimation)
{
pv->Set(p.x, ph[0], p.z);
pv++;
ph += node->decimation;
p.x += step_w * node->decimation * GetUnit();
}
p.x = node->u * step_w * GetUnit();
p.z += step_h * node->decimation * GetUnit();
}
// Create polygons.
geometry->AllocatePolygon(patch_w * patch_h);
for (uint n = 0; n < geometry->pol.GetCount(); ++n)
{
geometry->pol[n].vtx_count = 4;
geometry->pol[n].material = 0;
}
geometry->AllocatePolygonBinding();
Polygon *polygon = geometry->pol;
for (int _v = 0; _v < patch_h; ++_v)
for (int _u = 0; _u < patch_w; ++_u)
{
polygon->vtx_count = 4;
polygon->material = 0;
polygon->binding[0] = _v * (patch_w + 1) + _u;
polygon->binding[1] = _v * (patch_w + 1) + _u + 1;
polygon->binding[2] = (_v + 1) * (patch_w + 1) + _u + 1;
polygon->binding[3] = (_v + 1) * (patch_w + 1) + _u;
polygon++;
}
geometry->ComputeVertexNormal();
return geometry;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Terrain::UpdatePatchMinMax(Patch *node) const
{
float *ph = &heightmap[node->v * GetHeightmapPitch() + node->u];
float min_height, max_height;
min_height = max_height = ph[0];
for (int _v = 0; _v < node->h; _v += node->decimation)
{
for (int _u = 0; _u < node->w; _u += node->decimation)
{
if (ph[_u] < min_height)
min_height = ph[_u];
if (ph[_u] > max_height)
max_height = ph[_u];
}
ph += GetHeightmapPitch() * node->decimation;
}
node->minmax.mn.Set(node->u * GetUnit() - width * 0.5f, min_height, (node->v + node->h) * GetUnit() - depth * 0.5f);
node->minmax.mx.Set((node->u + node->w) * GetUnit() - width * 0.5f, max_height, node->v * GetUnit() - depth * 0.5f);
}
Patch *Terrain::BuildTerrainStaticQuadtree(int u, int v, int w, int h, int decimation, int tree_depth)
{
if (!decimation || (tree_depth == 8))
return NULL;
if (!w || !h)
return NULL;
// Create a new node.
Patch *node = new Patch;
node->terrain = this;
node->u = u; node->v = v;
node->w = w; node->h = h;
node->decimation = decimation;
// Create node geometry (helper function, should normally be done on the fly by the renderer).
// CreateNodeGeometry(node);
// Update patch minmax.
UpdatePatchMinMax(node);
// Split to create children.
int hw = w / 2, hh = h / 2;
node->children[0] = BuildTerrainStaticQuadtree(node->u, node->v, hw, hh, decimation / 2, tree_depth + 1);
node->children[1] = BuildTerrainStaticQuadtree(node->u + hw, node->v, node->w - hw, hh, decimation / 2, tree_depth + 1);
node->children[2] = BuildTerrainStaticQuadtree(node->u, node->v + hh, hw, node->h - hh, decimation / 2, tree_depth + 1);
node->children[3] = BuildTerrainStaticQuadtree(node->u + hw, node->v + hh, node->w - hw, node->h - hh, decimation / 2, tree_depth + 1);
node_count++;
return node;
}
Patch *Terrain::BuildQuadtree()
{
node_count = 0;
return root_node = BuildTerrainStaticQuadtree(0, 0, heightmap_w, heightmap_h, heightmap_w / 64, 0);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Terrain::UpdateQuadtreePatch(Patch *patch, iRect &update_rect)
{
iRect patch_rect = patch->GetRect();
if (!patch_rect.Intersect(update_rect))
return;
UpdatePatchMinMax(patch);
for (int n = 0; n < 4; ++n)
if (patch->children[n])
UpdateQuadtreePatch(patch->children[n], update_rect);
}
void Terrain::UpdateQuadtree(int u, int v, int w, int h)
{
iRect update_rect(u, v, u + w, v + h);
UpdateQuadtreePatch(root_node, update_rect);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Terrain::ComputeNormals(int u, int v, int w, int h)
{
if (!attribmap)
return;
if (!u && !v && !w && !h)
{
w = heightmap_w;
h = heightmap_h;
}
u = Types::Clamp(u, 0, heightmap_w);
v = Types::Clamp(v, 0, heightmap_h);
if (u + w > heightmap_w) w = heightmap_w - u;
if (v + h > heightmap_h) h = heightmap_h - v;
float *ph = &heightmap[v * GetHeightmapPitch() + u];
Attrib *pv = &attribmap[v * GetHeightmapPitch() + u];
for (int _v = 0; _v < h; ++_v)
{
float *sh = ph;
Attrib *sv = pv;
for (int _u = 0; _u < w; ++_u)
{
Vector4 vu(unit, sh[1] - sh[0], 0),
vv(0, sh[GetHeightmapPitch()] - sh[0], unit),
n = vv.Normalized().Cross(vu.Normalized());
sv[0].nx = (char)(n.x * 127.f);
sv[0].ny = (char)(n.y * 127.f);
sv[0].nz = (char)(n.z * 127.f);
++sh;
++sv;
}
pv += GetHeightmapPitch();
ph += GetHeightmapPitch();
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Terrain::Allocate(uint w_res, uint h_res, float _unit)
{
Free();
// Global heightmap.
heightmap_w = w_res;
heightmap_h = h_res;
if (!attribmap.Allocate((heightmap_w + 1) * (heightmap_h + 1)) || !heightmap.Allocate((heightmap_w + 1) * (heightmap_h + 1)))
__ERR__(__LOG_E__ << "Failed to allocate terrain heightmap.\n", false)
Memory::Set(&attribmap[0], 0, (heightmap_w + 1) * (heightmap_h + 1) * sizeof(Attrib));
Memory::Set(&heightmap[0], 0, sizeof(float) * (heightmap_w + 1) * (heightmap_h + 1));
width = w_res * _unit;
depth = h_res * _unit;
unit = _unit;
return true;
}
void Terrain::Free()
{
width = 0;
depth = 0;
attribmap.Free();
heightmap.Free();
heightmap_w = 0;
heightmap_h = 0;
node_count = 0;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Terrain::Raytrace(const Vector4 &w_s, const Vector4 &w_d, TraceResult &trace, float len)
{
trace.has_hit = false;
// Move ray to terrain space.
Vector4 s = w_s * GetInverseMatrix(),
d = w_d * GetRotationMatrix().Transposed();
// Clip ray against the terrain bounding box.
float tmin, tmax;
if (!root_node->minmax.IntersectRay(s, d, tmin, tmax))
return false;
tmin -= 0.1f; tmax += 0.1f;
Vector4 e = s + d * tmax;
if (tmin > 0)
s += d * tmin;
// Walk along the ray, looking for an intersection point.
bool side = SampleHeight(s) < s.y;
Vector4 dt = e - s;
float max_dist = dt.Len();
dt /= max_dist;
dt *= 1.f; // minimum step size is 1 meters (so as not to spend too much time stepping)
float dt_len = dt.Len();
float dist = 0.f;
for (Vector4 p = s + dt; dist < max_dist; p += dt)
{
if ((SampleHeight(p) < p.y) != side)
{
#if 1
// [EJ] Extra precision at terrain crossing boundary.
s = p - dt;
for (int n = 0; n < 24; ++n)
{
Vector4 m = (s + p) * 0.5f;
if ((SampleHeight(m) < m.y) != side)
p = m;
else s = m;
}
#endif
// Final hit.
trace.has_hit = true;
trace.w_i = p * GetMatrix();
LocalToHeightmap(p, trace.uv.x, trace.uv.y);
return true;
}
dist += dt_len;
}
return false;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Terrain::ApplyBlur(int pass_count)
{
if (heightmap)
for (int p = 0; p < pass_count; ++p)
{
int n = (heightmap_w + 1) + 1;
for (int v = 1; v < heightmap_h; ++v)
{
for (int u = 1; u < heightmap_w; ++u)
{
heightmap[n] = (heightmap[n] + heightmap[n - 1] + heightmap[n - (heightmap_w + 1)] + heightmap[n + 1] + heightmap[n + (heightmap_w + 1)]) / 5.f;
++n;
}
n += 2;
}
}
}
bool Terrain::FromPicture(const char *path, int blur_pass_count)
{
// Initial values.
Picture pic;
PictureIO::Get().Load(pic, path);
int n = 0;
for (int v = 0; v < (heightmap_h + 1); ++v)
for (int u = 0; u < (heightmap_w + 1); ++u)
heightmap[n++] = pic.SampleColor((float)u / heightmap_w, (float)v / heightmap_h).x * 16.f;
ApplyBlur(blur_pass_count);
return true;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Terrain::Attrib *Terrain::GetAttributesMapAt(int u, int v) const
{ return &attribmap[(heightmap_w + 1) * v + u]; }
Vector4 Terrain::GetNormalAt(int u, int v) const
{
Attrib *n = GetAttributesMapAt(u, v);
return Vector4((float)n->nx / 127.f, (float)n->ny / 127.f, (float)n->nz / 127.f);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Terrain::Terrain()
{
width = 0;
depth = 0;
heightmap_w = 0;
heightmap_h = 0;
node_count = 0;
for (uint n = 1; n < 4; ++n)
layer[n].enabled = false;
}
Terrain::~Terrain()
{
Free();
}
//------------------------------------------------------------------------------