mirror of
https://github.com/Linloir/SceneEditor.git
synced 2025-12-18 16:08:11 +08:00
[CORE][FIX] Update terrain hitpoint precision
- change search method - prevent outbound retrieving
This commit is contained in:
parent
4cbc16e4c6
commit
14f7c8b33a
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#define LOCALLOGLEVEL INFO
|
#define LOCALLOGLEVEL DEBUG
|
||||||
|
|
||||||
class Logger {
|
class Logger {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#include "terrain.h"
|
#include "terrain.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "vertex.h"
|
#include "vertex.h"
|
||||||
|
#include "logger.h"
|
||||||
|
|
||||||
Terrain::Terrain(std::string path){
|
Terrain::Terrain(std::string path){
|
||||||
// Convert '\ ' to '/' for Windows
|
// Convert '\ ' to '/' for Windows
|
||||||
@ -137,14 +138,23 @@ void Terrain::render() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
float Terrain::GetHeight(float px, float pz) {
|
float Terrain::GetHeight(float px, float pz) {
|
||||||
float fx = px + height / 2;
|
float fx = px + double(height) / 2;
|
||||||
float fz = pz + width / 2;
|
float fz = pz + double(width) / 2;
|
||||||
|
|
||||||
int x = ((int)fx) % height;
|
int x = ((int)fx) % height;
|
||||||
int z = ((int)fz) % width;
|
int z = ((int)fz) % width;
|
||||||
int gx = (x + 1) % height;
|
int gx = (x + 1) % height;
|
||||||
int gz = (z + 1) % width;
|
int gz = (z + 1) % width;
|
||||||
|
|
||||||
|
// prevent retrieving out of bounds
|
||||||
|
if (x < 0) x = 0;
|
||||||
|
if (z < 0) z = 0;
|
||||||
|
if (gx < 0) gx = 0;
|
||||||
|
if (gz < 0) gz = 0;
|
||||||
|
if (x > height - 1) x = height - 1;
|
||||||
|
if (z > width - 1) z = width - 1;
|
||||||
|
if (gx > height - 1) gx = height - 1;
|
||||||
|
if (gz > width - 1) gz = width - 1;
|
||||||
float ans = (x - fx) * (Point[gx][gz] - Point[x][z]) + Point[x][z];
|
float ans = (x - fx) * (Point[gx][gz] - Point[x][z]) + Point[x][z];
|
||||||
|
|
||||||
//float ans = Point[x][z];
|
//float ans = Point[x][z];
|
||||||
@ -153,16 +163,34 @@ float Terrain::GetHeight(float px, float pz) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 Terrain::GetNormal(glm::vec3 pos) {
|
glm::vec3 Terrain::GetNormal(glm::vec3 pos) {
|
||||||
float fx = pos.x;
|
// construct a triangle with its geometry center at pos
|
||||||
float fz = pos.z;
|
glm::vec3 p1 = pos + glm::vec3(-1.0f, 0.0f, -0.57735f);
|
||||||
|
glm::vec3 p2 = pos + glm::vec3(1.0f, 0.0f, -0.57735f);
|
||||||
|
glm::vec3 p3 = pos + glm::vec3(0.0f, 0.0f, 1.1547f);
|
||||||
|
|
||||||
glm::vec3 point1(fx - 1, GetHeight(fx - 1, fz - 1), fz - 1);
|
// calculate the height
|
||||||
glm::vec3 point2(fx + 1, GetHeight(fx + 1, fz + 1), fz + 1);
|
p1.y = GetHeight(p1.x, p1.z);
|
||||||
|
p2.y = GetHeight(p2.x, p2.z);
|
||||||
|
p3.y = GetHeight(p3.x, p3.z);
|
||||||
|
|
||||||
glm::vec3 l1 = pos - point1;
|
// calculate the normal
|
||||||
glm::vec3 l2 = point2 - point1;
|
glm::vec3 v1 = p2 - p1;
|
||||||
glm::vec3 ans = glm::normalize(glm::cross(l1, l2));
|
glm::vec3 v2 = p3 - p1;
|
||||||
return ans;
|
glm::vec3 normal = glm::normalize(glm::cross(v1, v2));
|
||||||
|
|
||||||
|
// make the normal point up
|
||||||
|
if (normal.y < 0.0f) {
|
||||||
|
normal = -normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
//glm::vec3 point1(fx - 1, GetHeight(fx - 1, fz - 1), fz - 1);
|
||||||
|
//glm::vec3 point2(fx + 1, GetHeight(fx + 1, fz + 1), fz + 1);
|
||||||
|
|
||||||
|
//glm::vec3 l1 = pos - point1;
|
||||||
|
//glm::vec3 l2 = point2 - point1;
|
||||||
|
|
||||||
|
//glm::vec3 ans = glm::normalize(glm::cross(l1, l2));
|
||||||
|
return normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
HitRecord Terrain::hit(const Ray& ray) {
|
HitRecord Terrain::hit(const Ray& ray) {
|
||||||
@ -193,17 +221,38 @@ HitRecord Terrain::hit(const Ray& ray) {
|
|||||||
glm::vec3 startPosition = lastRayPosition;
|
glm::vec3 startPosition = lastRayPosition;
|
||||||
glm::vec3 endPosition = orig;
|
glm::vec3 endPosition = orig;
|
||||||
|
|
||||||
// Binary search with 32 steps. Try to find the exact collision point
|
// Binary search with 64 steps. Try to find the exact collision point
|
||||||
for (int i = 0; i < 32; i++)
|
float threshold = 0.1f;
|
||||||
{
|
glm::vec3 mid;
|
||||||
// Binary search pass
|
while(true) {
|
||||||
glm::vec3 middlePoint = (startPosition + endPosition) * 0.5f;
|
mid = (startPosition + endPosition) * 0.5f;
|
||||||
if (middlePoint.y < height)
|
map_height = GetHeight(mid.x, mid.z);
|
||||||
endPosition = middlePoint;
|
if (abs(mid.y - map_height) < threshold) {
|
||||||
else
|
break;
|
||||||
startPosition = middlePoint;
|
|
||||||
}
|
}
|
||||||
glm::vec3 position = (startPosition + endPosition) * 0.5f;
|
else if (mid.y - endPosition.y < 0.001f) {
|
||||||
|
// if no more space to search, return
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Logger::debug("Current height difference: " + std::to_string(abs(mid.y - map_height)));
|
||||||
|
if (mid.y > map_height)
|
||||||
|
{
|
||||||
|
startPosition = mid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
endPosition = mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//{
|
||||||
|
// // Binary search pass
|
||||||
|
// glm::vec3 middlePoint = (startPosition + endPosition) * 0.5f;
|
||||||
|
// if (middlePoint.y < height)
|
||||||
|
// endPosition = middlePoint;
|
||||||
|
// else
|
||||||
|
// startPosition = middlePoint;
|
||||||
|
//}
|
||||||
|
glm::vec3 position = mid;
|
||||||
glm::vec3 normal = GetNormal(position);
|
glm::vec3 normal = GetNormal(position);
|
||||||
|
|
||||||
// If t > 200, consider the ray as not hitted
|
// If t > 200, consider the ray as not hitted
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user