Forums WoW Modding Support Archives Azerothcore Discord Archives [DiscordArchive] Here is naive collision test (as a radius I'm using GetCollisionRadius() of the player):

[DiscordArchive] Here is naive collision test (as a radius I'm using GetCollisionRadius() of the player):

[DiscordArchive] Here is naive collision test (as a radius I'm using GetCollisionRadius() of the player):

Pages (2): 1 2 Next
rektbyfaith
Administrator
0
02-20-2025, 08:25 PM
#1
Archived author: walkline • Posted: 2025-02-20T20:25:19.334000+00:00
Original source

Here is naive collision test (as a radius I'm using GetCollisionRadius() of the player):
```
float GetMaxHeightInCircle(Map* map, uint32 phaseMask, float centerX, float centerY, float centerZ, float radius, int numRings, int numSamplesPerRing)
{
float maxHeight = centerZ; // Start with the center height as the initial max

// Check the center point
maxHeight = std::max(maxHeight, map->GetHeight(phaseMask, centerX, centerY, centerZ));

// Loop through rings from the center outward
for (int ring = 1; ring <= numRings; ++ring)
{
float currentRadius = (radius * ring) / numRings; // Distribute points inside the circle
float angleStep = 2.0f * M_PI / numSamplesPerRing;

for (int i = 0; i < numSamplesPerRing; ++i)
{
float angle = i * angleStep;
float sampleX = centerX + currentRadius * cos(angle);
float sampleY = centerY + currentRadius * sin(angle);
float height = map->GetHeight(phaseMask, sampleX, sampleY, centerZ);

if (height > maxHeight)
maxHeight = height;
}
}

return maxHeight;
}
```

The question is how we can improve it?
rektbyfaith
02-20-2025, 08:25 PM #1

Archived author: walkline • Posted: 2025-02-20T20:25:19.334000+00:00
Original source

Here is naive collision test (as a radius I'm using GetCollisionRadius() of the player):
```
float GetMaxHeightInCircle(Map* map, uint32 phaseMask, float centerX, float centerY, float centerZ, float radius, int numRings, int numSamplesPerRing)
{
float maxHeight = centerZ; // Start with the center height as the initial max

// Check the center point
maxHeight = std::max(maxHeight, map->GetHeight(phaseMask, centerX, centerY, centerZ));

// Loop through rings from the center outward
for (int ring = 1; ring <= numRings; ++ring)
{
float currentRadius = (radius * ring) / numRings; // Distribute points inside the circle
float angleStep = 2.0f * M_PI / numSamplesPerRing;

for (int i = 0; i < numSamplesPerRing; ++i)
{
float angle = i * angleStep;
float sampleX = centerX + currentRadius * cos(angle);
float sampleY = centerY + currentRadius * sin(angle);
float height = map->GetHeight(phaseMask, sampleX, sampleY, centerZ);

if (height > maxHeight)
maxHeight = height;
}
}

return maxHeight;
}
```

The question is how we can improve it?

rektbyfaith
Administrator
0
02-20-2025, 08:34 PM
#2
Archived author: walkline • Posted: 2025-02-20T20:34:19.067000+00:00
Original source

Or this naive implementation would fit the need?
rektbyfaith
02-20-2025, 08:34 PM #2

Archived author: walkline • Posted: 2025-02-20T20:34:19.067000+00:00
Original source

Or this naive implementation would fit the need?

rektbyfaith
Administrator
0
02-20-2025, 08:47 PM
#3
Archived author: walkline • Posted: 2025-02-20T20:47:05.747000+00:00
Original source

Another observation. This approach is 100% accurate with the client when using vmaps data. But with `GetGridHeight(x, y)` (maps?), it is less accurate, I’m not sure why.
rektbyfaith
02-20-2025, 08:47 PM #3

Archived author: walkline • Posted: 2025-02-20T20:47:05.747000+00:00
Original source

Another observation. This approach is 100% accurate with the client when using vmaps data. But with `GetGridHeight(x, y)` (maps?), it is less accurate, I’m not sure why.

rektbyfaith
Administrator
0
02-20-2025, 09:12 PM
#4
Archived author: Pursche • Posted: 2025-02-20T21:12:19.517000+00:00
Original source

I'm not a big fan of that implementation. I would rather implement a GetHeightAccurate() function in map which has to:
1. Take the same actions as GetHeight to figure out what we need to test against, terrain, WMO, vmap etc. Ideally this should give you one or several triangles, but this is where I'm not 100% sure since I don't do emulation.
2. Once it has one (or more) triangles to test against, it needs to run something like this:

```c++
struct Vec3 {
float x, y, z;
};

float BarycentricHeight(const Vec3 &p, const Vec3 &a, const Vec3 &b, const Vec3 &c)
{
// Project point p onto the triangle’s XY plane and compute barycentric
// coordinates relative to vertices a, b, c.
float det = (b.y - c.y) * (a.x - c.x) + (c.x - b.x) * (a.y - c.y);
float l1 = ((b.y - c.y) * (p.x - c.x) + (c.x - b.x) * (p.y - c.y)) / det;
float l2 = ((c.y - a.y) * (p.x - c.x) + (a.x - c.x) * (p.y - c.y)) / det;
float l3 = 1.0f - l1 - l2;
// Interpolate the Z height of the triangle at point p.
return l1 * a.z + l2 * b.z + l3 * c.z;
}

float GetHeightAccurate(float centerX, float centerY, float centerZ, float radius,
const Vec3 &triA, const Vec3 &triB, const Vec3 &triC)
{
// Use the sphere's horizontal position (centerX, centerY) to find the terrain height.
Vec3 pos = { centerX, centerY, 0.0f };
float terrainHeight = BarycentricHeight(pos, triA, triB, triC);

// If the bottom of the sphere is below the terrain,
// move the sphere up so that it just touches the triangle.
if (centerZ - radius < terrainHeight)
return terrainHeight + radius;

// Otherwise, no adjustment is needed.
return centerZ;
}
```
rektbyfaith
02-20-2025, 09:12 PM #4

Archived author: Pursche • Posted: 2025-02-20T21:12:19.517000+00:00
Original source

I'm not a big fan of that implementation. I would rather implement a GetHeightAccurate() function in map which has to:
1. Take the same actions as GetHeight to figure out what we need to test against, terrain, WMO, vmap etc. Ideally this should give you one or several triangles, but this is where I'm not 100% sure since I don't do emulation.
2. Once it has one (or more) triangles to test against, it needs to run something like this:

```c++
struct Vec3 {
float x, y, z;
};

float BarycentricHeight(const Vec3 &p, const Vec3 &a, const Vec3 &b, const Vec3 &c)
{
// Project point p onto the triangle’s XY plane and compute barycentric
// coordinates relative to vertices a, b, c.
float det = (b.y - c.y) * (a.x - c.x) + (c.x - b.x) * (a.y - c.y);
float l1 = ((b.y - c.y) * (p.x - c.x) + (c.x - b.x) * (p.y - c.y)) / det;
float l2 = ((c.y - a.y) * (p.x - c.x) + (a.x - c.x) * (p.y - c.y)) / det;
float l3 = 1.0f - l1 - l2;
// Interpolate the Z height of the triangle at point p.
return l1 * a.z + l2 * b.z + l3 * c.z;
}

float GetHeightAccurate(float centerX, float centerY, float centerZ, float radius,
const Vec3 &triA, const Vec3 &triB, const Vec3 &triC)
{
// Use the sphere's horizontal position (centerX, centerY) to find the terrain height.
Vec3 pos = { centerX, centerY, 0.0f };
float terrainHeight = BarycentricHeight(pos, triA, triB, triC);

// If the bottom of the sphere is below the terrain,
// move the sphere up so that it just touches the triangle.
if (centerZ - radius < terrainHeight)
return terrainHeight + radius;

// Otherwise, no adjustment is needed.
return centerZ;
}
```

rektbyfaith
Administrator
0
02-20-2025, 09:12 PM
#5
Archived author: walkline • Posted: 2025-02-20T21:12:20.413000+00:00
Original source

Oh wait, I'm dumb.
rektbyfaith
02-20-2025, 09:12 PM #5

Archived author: walkline • Posted: 2025-02-20T21:12:20.413000+00:00
Original source

Oh wait, I'm dumb.

rektbyfaith
Administrator
0
02-20-2025, 09:12 PM
#6
Archived author: Pursche • Posted: 2025-02-20T21:12:54.788000+00:00
Original source

This uses barycentric interpolation to figure out the height of the triangle at poing P inside the triangle.
rektbyfaith
02-20-2025, 09:12 PM #6

Archived author: Pursche • Posted: 2025-02-20T21:12:54.788000+00:00
Original source

This uses barycentric interpolation to figure out the height of the triangle at poing P inside the triangle.

rektbyfaith
Administrator
0
02-20-2025, 09:13 PM
#7
Archived author: walkline • Posted: 2025-02-20T21:13:07.550000+00:00
Original source

It's "accurate" because if this code <:kek:1065379143887372398> :
```
float maxHeight = centerZ; // Start with the center height as the initial max

// Check the center point
maxHeight = std::max(maxHeight, map->GetHeight(phaseMask, centerX, centerY, centerZ));
```
rektbyfaith
02-20-2025, 09:13 PM #7

Archived author: walkline • Posted: 2025-02-20T21:13:07.550000+00:00
Original source

It's "accurate" because if this code <:kek:1065379143887372398> :
```
float maxHeight = centerZ; // Start with the center height as the initial max

// Check the center point
maxHeight = std::max(maxHeight, map->GetHeight(phaseMask, centerX, centerY, centerZ));
```

rektbyfaith
Administrator
0
02-20-2025, 09:15 PM
#8
Archived author: Pursche • Posted: 2025-02-20T21:15:21.613000+00:00
Original source

Then you want to offset that position up with whatever the radius of the sphere you're testing, to make sure the bottom of that sphere barely touches the terrain.
rektbyfaith
02-20-2025, 09:15 PM #8

Archived author: Pursche • Posted: 2025-02-20T21:15:21.613000+00:00
Original source

Then you want to offset that position up with whatever the radius of the sphere you're testing, to make sure the bottom of that sphere barely touches the terrain.

rektbyfaith
Administrator
0
02-20-2025, 09:17 PM
#9
Archived author: Pursche • Posted: 2025-02-20T21:17:08.229000+00:00
Original source

This should be 100% accurate if you're certain about the triangle you're on, but there is still the edgecase of if there's neighboring triangles which have a steeper incline that could intersect with the sphere.
rektbyfaith
02-20-2025, 09:17 PM #9

Archived author: Pursche • Posted: 2025-02-20T21:17:08.229000+00:00
Original source

This should be 100% accurate if you're certain about the triangle you're on, but there is still the edgecase of if there's neighboring triangles which have a steeper incline that could intersect with the sphere.

rektbyfaith
Administrator
0
02-20-2025, 09:20 PM
#10
Archived author: Pursche • Posted: 2025-02-20T21:20:56.861000+00:00
Original source

Red dot is the center position (centerXYZ)
Red circle is the collider you're testing based on the radius you pass in
Blue circle is where that collider will be if you use the result of GetHeightAccurate to override centerZ

What we ultimately want to get to is the green circle, but one step at a time first, make sure you understand the first part of the problem first.
[Image: image.png?ex=690c6878&is=690b16f8&hm=a56...af87fa1ba&]
rektbyfaith
02-20-2025, 09:20 PM #10

Archived author: Pursche • Posted: 2025-02-20T21:20:56.861000+00:00
Original source

Red dot is the center position (centerXYZ)
Red circle is the collider you're testing based on the radius you pass in
Blue circle is where that collider will be if you use the result of GetHeightAccurate to override centerZ

What we ultimately want to get to is the green circle, but one step at a time first, make sure you understand the first part of the problem first.
[Image: image.png?ex=690c6878&is=690b16f8&hm=a56...af87fa1ba&]

Pages (2): 1 2 Next
Recently Browsing
 1 Guest(s)
Recently Browsing
 1 Guest(s)