Plane normal
Plane normal
For my quad-based terrain node I need to calculate the normals. I am not much experienced with 3d-maths so I feel a bit lost.
What I basically have is grid of vertices, that get rendered via QUADS (or later QUAD_STRIP).
So I have 8 vertices surrounding each vertex. How can I calculate a normal (and tangent) of this plane?
greets,
Halan
What I basically have is grid of vertices, that get rendered via QUADS (or later QUAD_STRIP).
So I have 8 vertices surrounding each vertex. How can I calculate a normal (and tangent) of this plane?
greets,
Halan
My Blog: http://www.freakybytes.org
I think the easiest way is to calculate the normals of all the triangles surrounding the vertex, and then average them out.
So for each triangle create a triangle3df and call getNormal() (This basically just does a cross product to get the plane normal.), and then average those out. For the quads you can just use any 3 vertices and pretend it's a triangle.
Cheers
So for each triangle create a triangle3df and call getNormal() (This basically just does a cross product to get the plane normal.), and then average those out. For the quads you can just use any 3 vertices and pretend it's a triangle.
Cheers
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Alright. I know that you can do a cross-product with 2 vectors but how with a quad or triangle?
My Blog: http://www.freakybytes.org
interesting...
but somehow I can't really figure how the third vertex could be irrelevant when trying to calculate a vector perpendicular to a plane... By all means, doesn't a plane consists of at least 3 vertices ?
And what about concave quads, don't they have to be split into two triangles first ?
And since that is, and always will be quite a fundematal thing can someone point to, or post, already existing code ? Would be greatly appreciated...
EDIT:
By averaging do you mean
x=(x1+x2+x3) / 3
y=(y1+y2+y3) / 3
z=(z1+z2+z3) / 3
?
EDIT2:
maybe take a look in the hillplane mesh ?
but somehow I can't really figure how the third vertex could be irrelevant when trying to calculate a vector perpendicular to a plane... By all means, doesn't a plane consists of at least 3 vertices ?
And what about concave quads, don't they have to be split into two triangles first ?
And since that is, and always will be quite a fundematal thing can someone point to, or post, already existing code ? Would be greatly appreciated...
EDIT:
By averaging do you mean
x=(x1+x2+x3) / 3
y=(y1+y2+y3) / 3
z=(z1+z2+z3) / 3
?
EDIT2:
maybe take a look in the hillplane mesh ?
-
- Admin
- Posts: 14143
- Joined: Wed Apr 19, 2006 9:20 pm
- Location: Oldenburg(Oldb), Germany
- Contact:
Funny ideas
You need two vectors which span a plane. So you cannot use two vectors from two vertices, but you need to take the vectors AB and BC (or AB AC, or AC BC - guess you get it by now). Taking a perpendicular vector from those two vectors will give you the normal.
And yes, looking at the Irrlicht source would help, but only terrain has smoothing (as well as the mesh manipulator). Oh, for the simple normal calculation just take plane2d.
You need two vectors which span a plane. So you cannot use two vectors from two vertices, but you need to take the vectors AB and BC (or AB AC, or AC BC - guess you get it by now). Taking a perpendicular vector from those two vectors will give you the normal.
And yes, looking at the Irrlicht source would help, but only terrain has smoothing (as well as the mesh manipulator). Oh, for the simple normal calculation just take plane2d.
okay so ill try to do so. My last problem is i want a normal that faces up (z-Axis) but theoretically the normals could all face downwards...
edit: Oh there is plane2d. Thanks hybrid
edit2: well i guess you meant plane3d
edit: Oh there is plane2d. Thanks hybrid
edit2: well i guess you meant plane3d
My Blog: http://www.freakybytes.org
okay i didn't work on this for some time.
My code looks like this:
The result is this:
You can see that on the edges the normals are broken.
Greets,
Halan
My code looks like this:
Code: Select all
//! Calculate normal of the 4 ajusting planes (cross-product)
irr::core::vector3df normals[4];
normals[0] = irr::core::vector3df(-1,-1, terrain->getHeight(Position(x,y) + pos)-terrain->getHeight(Position(x-1,y-1) + pos))
.crossProduct(irr::core::vector3df(0, 0, terrain->getHeight(Position(x+1,y+1) + pos)-terrain->getHeight(Position(x,y) + pos)));
normals[1] = irr::core::vector3df(-1, 0, terrain->getHeight(Position(x,y) + pos)-terrain->getHeight(Position(x-1,y) + pos))
.crossProduct(irr::core::vector3df(0, 1, terrain->getHeight(Position(x+1,y+2) + pos)-terrain->getHeight(Position(x,y+1) + pos)));
normals[2] = irr::core::vector3df(0, 0, terrain->getHeight(Position(x,y) + pos)-terrain->getHeight(Position(x,y) + pos))
.crossProduct(irr::core::vector3df(1, 1, terrain->getHeight(Position(x+2,y+2) + pos)-terrain->getHeight(Position(x+1,y+1) + pos)));
normals[1] = irr::core::vector3df(0, -1, terrain->getHeight(Position(x,y) + pos)-terrain->getHeight(Position(x,y-1) + pos))
.crossProduct(irr::core::vector3df(1, 0, terrain->getHeight(Position(x+2,y+1) + pos)-terrain->getHeight(Position(x+1,y) + pos)));
//! Now we take the average
vertices[x*VIEW_RANGE*2 + y].Normal = normals[0] + normals[1] + normals[2] + normals[3];
vertices[x*VIEW_RANGE*2 + y].Normal.normalize();
You can see that on the edges the normals are broken.
Greets,
Halan
My Blog: http://www.freakybytes.org
This is strait from my terrain. It does what Blindside told you to do, that is to calculate normals of triangles around:
Code: Select all
// recalculate normal at terrain coordinates
void ShTlTerrainSceneNode::recalculateNormal(s32 w, s32 h)
{
core::vector3df v0, v1;
core::vector3df n0, n1, n2, n3, n4, n5;
// calculate vector to point 0,-1
if(h > 0) // check if not out of array
v0 = core::vector3df(0, getHeight(w,h-1)-getHeight(w,h), -TileSize);
else
v0 = core::vector3df(0, 0, -TileSize);
// calculate vector to point -1,-1
if(w > 0 && h > 0) // check if not out of array
v1 = core::vector3df(-TileSize, getHeight(w-1,h-1)-getHeight(w,h), -TileSize);
else
v1 = core::vector3df(-TileSize, 0, -TileSize);
n0 = v0.crossProduct(v1);
// calculate vector to point -1,-1
v0 = v1;
// calculate vector to point -1,0
if(w > 0)
v1 = core::vector3df(-TileSize, getHeight(w-1,h)-getHeight(w,h), 0);
else
v1 = core::vector3df(-TileSize, 0, 0);
n1 = v0.crossProduct(v1);
// calculate vector to point -1,0
v0 = v1;
// calculate vector to point 0,1
if(h < Size.Height)
v1 = core::vector3df(0, getHeight(w,h+1)-getHeight(w,h), TileSize);
else
v1 = core::vector3df(0, 0, TileSize);
n2 = v0.crossProduct(v1);
// calculate vector to point 0,1
v0 = v1;
// calculate vector to point 1,1
if(w < Size.Width && h < Size.Height)
v1 = core::vector3df(TileSize, getHeight(w+1,h+1)-getHeight(w,h), TileSize);
else
v1 = core::vector3df(TileSize, 0, TileSize);
n3 = v0.crossProduct(v1);
// calculate vector to point 1,1
v0 = v1;
// calculate vector to point 1,0
if(w < Size.Width)
v1 = core::vector3df(TileSize, getHeight(w+1,h)-getHeight(w,h), 0);
else
v1 = core::vector3df(TileSize, 0, 0);
n4 = v0.crossProduct(v1);
// calculate vector to point 1,0
v0 = v1;
// calculate vector to point 0,-1
if(h > 0)
v1 = core::vector3df(0, getHeight(w,h-1)-getHeight(w,h), -TileSize);
else
v1 = core::vector3df(0, 0, -TileSize);
n5 = v0.crossProduct(v1);
// calculate normals of 4 tiles around point
core::vector3df m0, m1, m2, m3;
m0 = (n1 - n0) /2 + n0;
m1 = n2;
m2 = (n4 - n3) /2 + n3;
m3 = n5;
// calculate normals between oposing tiles
core::vector3df k0, k1;
k0 = (m2 - m0) /2 + m0;
k1 = (m3 - m1) /2 + m1;
// calculate normal of point
core::vector3df n = (k1 - k0) /2 + k0;
n.normalize();
setNormal(w,h,n);
}
edit: Oh there is plane2d. Thanks hybrid
Code: Select all
typedef line2df plane2df
Although Arras already provided a solution, for learning purposes your code should look more like:
Code: Select all
(Assuming pos is the vector3df position of the vertex)
vector3df v1 = pos, v2 = pos, v3 = pos;
v1.Y = terrain->getHeight(Position(x, y) + pos);
v2.X += 1.0f;
v2.Y = terrain->getHeight(Position(x + 1, y) + pos);
v3.Z += 1.0f;
v3.Y = terrain->getHeight(Position(x, y + 1) + pos);
// So what we want is 3 3d positions on the surface.
// One at our current position and 2 offset in different directions. Then we do...
normals[0] = (v1 - v2).crossProduct(v1 - v3);
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net