Emilie_Blue
Member
Hello everyone !
I recently had the idea to use normals to make , for example a car follow the 3D ground and rotating accordingly.
Since I'm bad at maths , I decided to learn from scratch how I could implement it in GML. Fortunately , I found some
ressources online to help me
I managed to make something that works by finding the average normal of the 2 normals found in these 2 triangles :
So here's the issue I have :
Depending of the slope I'm on , there is a slight offset from what the object is supposed to have :
But on the other slopes , it seems to work well :
These are the differents scripts used related to this problem :
And this is used in the draw event of the object :
I don't know if this is the better way to achieve it so I'm open for your suggestions.
Is the issue related to maths ? Or is it related to something else ?
I'm out of ideas...
I recently had the idea to use normals to make , for example a car follow the 3D ground and rotating accordingly.
Since I'm bad at maths , I decided to learn from scratch how I could implement it in GML. Fortunately , I found some
ressources online to help me
I managed to make something that works by finding the average normal of the 2 normals found in these 2 triangles :
So here's the issue I have :
Depending of the slope I'm on , there is a slight offset from what the object is supposed to have :
But on the other slopes , it seems to work well :
These are the differents scripts used related to this problem :
GML:
///math_triangle_normal_x(x1,y1,z1,x2,y2,z2,x3,y3,y3,axis,invert)
//Returns the specified axis normal of the specified triangle
//var axv,ayv,azv,axn,ayn,azn,bxv,byv,bzv,cxv,cyv,czv,cxn,cyn,czn,dista,distb,distc,nx,ny,nz;
axv = argument3-argument0
ayv = argument4-argument1
azv = argument5-argument2
dista = point_distance_3d(argument0,argument1,argument2,argument3,argument4,argument5)
axn = axv/dista //Normals of a
ayn = ayv/dista
azn = azv/dista
bxv = argument6-argument3
byv = argument7-argument4
bzv = argument8-argument5
distb = point_distance_3d(argument3,argument4,argument5,argument6,argument7,argument8)
bxn = bxv/distb //Normals of b
byn = byv/distb
bzn = bzv/distb
cxv = argument0-argument6
cyv = argument1-argument7
czv = argument2-argument8
distc = point_distance_3d(argument6,argument7,argument8,argument0,argument1,argument2)
cxn = cxv/distc //Normals of c
cyn = cyv/distc
czn = czv/distc
if argument10 = 1
{
if argument9 = 0 {return (ayn*bzn)-(azn*byn)}
if argument9 = 1 {return (azn*bxn)-(axn*bzn)}
if argument9 = 2 {return (axn*byn)-(ayn*bxn)}
}
if argument10 = -1
{
if argument9 = 0 {return (ayn*czn)-(azn*cyn)}
if argument9 = 1 {return (azn*cxn)-(axn*czn)}
if argument9 = 2 {return (axn*cyn)-(ayn*cxn)}
}
GML:
///math_get_normal(x,y,axis,triangle size)
/*
return surface normal along the specified axis(x , y or z)
argument0 = x
argument1 = y
argument2 = 0,1 or 2 for x,y or z
argument3 = size of surface on
*/
var x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4;
x1 = argument0-argument3
y1 = argument1-argument3
z1 = terrain_get_z(argument0-argument3,argument1-argument3)
x2 = argument0+argument3
y2 = argument1-argument3
z2 = terrain_get_z(argument0+argument3,argument1-argument3)
x3 = argument0-argument3
y3 = argument1+argument3
z3 = terrain_get_z(argument0-argument3,argument1+argument3)
x4 = argument0+argument3
y4 = argument1+argument3
z4 = terrain_get_z(argument0+argument3,argument1+argument3)
var normalX,normalY,normalZ;
normalX = math_triangle_normal(x1,y1,z1,x2,y2,z2,x3,y3,z3,0,1)
normalY = math_triangle_normal(x1,y1,z1,x2,y2,z2,x3,y3,z3,1,1)
normalZ = math_triangle_normal(x1,y1,z1,x2,y2,z2,x3,y3,z3,2,1)
var normalX2,normalY2,normalZ2;
normalX2 = math_triangle_normal(x3,y3,z3,x2,y2,z4,x4,y4,z4,0,1)
normalY2 = math_triangle_normal(x3,y3,z3,x2,y2,z4,x4,y4,z4,1,1)
normalZ2 = math_triangle_normal(x3,y3,z3,x2,y2,z4,x4,y4,z4,2,1)
//Sum of the two vectors
var normalX3,normalY3,normalZ3;
normalX3 = normalX+normalX2
normalY3 = normalY+normalY2
normalZ3 = normalZ+normalZ2
//Normalize it
var normal3Magnitude;
normal3Magnitude = sqrt(normalX3*normalX3+normalY3*normalY3+normalZ3*normalZ3)
normalX3 /= normal3Magnitude
normalY3 /= normal3Magnitude
normalZ3 /= normal3Magnitude
if argument2 = 0 {return normalX3}
if argument2 = 1 {return normalY3}
if argument2 = 2 {return normalZ3}
GML:
var rotx,roty,rotz;
rotx=radtodeg(arccos(math_get_normal(x,y,0,.1)))
roty=radtodeg(arcsin(math_get_normal(x,y,1,.1)))
rotz=radtodeg(arcsin(math_get_normal(x,y,2,.1)))
d3d_transform_add_scaling(.3,.3,.3);
d3d_transform_add_rotation_y(-90)
d3d_transform_add_rotation_x(direction)
d3d_transform_add_rotation_axis(0,rotz,-roty,rotx)
d3d_transform_add_translation(x,y,z)
d3d_draw_block(-2,-2,4,2,2,0,-1,1,1)
d3d_set_lighting(false)
d3d_model_draw(mod_lines,0,0,.01,-1)
d3d_set_lighting(true)
d3d_transform_set_identity()
I don't know if this is the better way to achieve it so I'm open for your suggestions.
Is the issue related to maths ? Or is it related to something else ?
I'm out of ideas...
Attachments
-
62.4 KB Views: 1
Last edited: