Here is my implementation for a simple 3D move gizmo
The main file:
#include "ctrlgizmo3d.agc"
SetErrorMode(2)
SetWindowTitle("3Dgizmo")
SetWindowSize(1024, 768, 0)
SetSyncRate(60, 0)
UseNewDefaultFonts(1)
gizmo as _CtrlGizmo3D
global cube1 as integer
global cube2 as integer
global plane as integer
global pick as integer
global object_hit as integer
SetCameraPosition(1, 2.0, 3.0, -15.0)
SetCameraRotation(1, 0.0, 0.0, 0.0)
gizom3D_Create(gizmo, 2.0)
cube1 = CreateObjectBox(1.0, 1.0, 1.0)
SetObjectColor(cube1, 0, 0, 255, 255)
SetObjectPosition(cube1, -5.0, 0.0, 0.0)
cube2 = CreateObjectBox(1.0, 1.0, 1.0)
SetObjectColor(cube2, 0, 255, 0, 255)
SetObjectPosition(cube2, 5.0, 0.0, 0.0)
plane = CreateObjectPlane(10.0, 10.0)
SetObjectRotation(plane, -90.0, 0.0, 0.0)
SetObjectTransparency(plane, 1)
SetObjectColor(plane, 255, 0, 0, 64)
pick = 0
do
// Camera Move: W,A,S,D,Q,E, Camera Turn:1,3
update_camera()
gizmo3D_Update(gizmo)
if GetPointerPressed()
worldX# = Get3DVectorXFromScreen(GetPointerX(), GetPointerY()) * 800
worldY# = Get3DVectorYFromScreen(GetPointerX(), GetPointerY()) * 800
worldZ# = Get3DVectorZFromScreen(GetPointerX(), GetPointerY()) * 800
worldX# = worldX# + GetCameraX(1)
worldY# = worldY# + GetCameraY(1)
worldZ# = worldZ# + GetCameraZ(1)
object_hit = ObjectRayCast(cube1, GetCameraX(1), GetCameraY(1), GetCameraZ(1), worldX#, worldY#, worldZ#)
if object_hit > 0
pick = cube1
else
object_hit = ObjectRayCast(cube2, GetCameraX(1), GetCameraY(1), GetCameraZ(1), worldX#, worldY#, worldZ#)
if object_hit > 0 then pick = cube2
endif
if object_hit > 0 then gizmo3D_SetPosition(gizmo, GetObjectX(pick), GetObjectY(pick), GetObjectZ(pick))
endif
if pick <> 0 then SetObjectPosition(pick, gizmo.p.x, gizmo.p.y, gizmo.p.z)
Sync()
loop
function update_camera()
if GetRawKeyState(87)
MoveCameraLocalZ(1, 0.1)
endif
if GetRawKeyState(83)
MoveCameraLocalZ(1, -0.1)
endif
if GetRawKeyState(65)
MoveCameraLocalX(1, -0.1)
endif
if GetRawKeyState(68)
MoveCameraLocalX(1, 0.1)
endif
if GetRawKeyState(81)
MoveCameraLocalY(1, 0.1)
endif
if GetRawKeyState(69)
MoveCameraLocalY(1, -0.1)
endif
if GetRawKeyState(49)
RotateCameraGlobalY(1, 1.0)
endif
if GetRawKeyState(51)
RotateCameraGlobalY(1, -1.0)
endif
endfunction
and the include file
#constant Axis_None -1
#constant Axis_X 0
#constant Axis_Y 2
#constant Axis_Z 3
#constant Axis_XY 4
#constant Axis_XZ 5
#constant Axis_YZ 6
type _Rect2D
l as float ` left
t as float ` top
r as float ` right
b as float ` bottom
endtype
type _Vector3
name as string
x as float
y as float
z as float
n as float
endtype
type _CtrlGizmo3D
p as _Vector3 ` origin of gizmo
p0 as _Vector3 ` origin of gizmo on first grab event
v0 as _Vector3 ` coordinates of the gizmo on first grab event
dv as _Vector3 ` distance of current pointer pick from v0
h_l as float ` length of gizmo handles
h_t as float ` thickness of gizmo handles
h_x as _Rect2D
h_y as _Rect2D
h_z as _Rect2D
h_xz as _Rect2D
h_xy as _Rect2D
h_yz as _Rect2D
sel as integer ` global selection flag of gizmo handles
s_x as integer ` selection flags of gizmo handles
s_y as integer
s_z as integer
s_xz as integer
s_xy as integer
s_yz as integer
v1 as _Vector3 ` helper point
v2 as _Vector3 ` helper point
v3 as _Vector3 ` helper point
grab as integer
endtype
function gizom3D_Create(g ref as _CtrlGizmo3D, l as float)
g.h_l = Abs(l)
if g.h_l < 0.5 then g.h_l = 0.5
g.h_t = 0.25
gizmo3D_Layout(g)
endfunction
function gizmo3D_Update(g ref as _CtrlGizmo3D)
` pick a point on the XZ plane
g.v1 = GetXZFromPointer(g.p.y)
` pick a point on the XY plane
g.v2 = GetXYFromPointer(g.p.z)
` pick a point on the YZ plane
g.v3 = GetYZFromPointer(g.p.x)
if GetPointerState() = 0
` unselect any gizmo handle if no touch is detected
if g.sel = 1 then ctrlgizmo3D_SelectAxis(g, Axis_None)
if PointIsInRect(g.v1.x, g.v1.z, g.h_xz) ` check if the pointer is hovering the xz-axis of gizmo
g.s_xz = 1
elseif PointIsInRect(g.v2.x, g.v2.y, g.h_xy) ` check if the pointer is hovering the xy-axis of gizmo
g.s_xy = 1
elseif PointIsInRect(g.v3.z, g.v3.y, g.h_yz) ` check if the pointer is hovering the yz-axis of gizmo
g.s_yz = 1
elseif PointIsInRect(g.v1.x, g.v1.z, g.h_x) = 1 ` check if the pointer is hovering the x-axis of gizmo
if g.s_x = 0 then ctrlgizmo3D_SelectAxis(g, Axis_X)
elseif PointIsInRect(g.v1.x, g.v1.z, g.h_z) = 1 ` check if the pointer is hovering the z-axis of gizmo
if g.s_x = 0 then ctrlgizmo3D_SelectAxis(g, Axis_Z)
elseif PointIsInRect(g.v3.z, g.v3.y, g.h_y) = 1 ` check if the pointer is hovering the y-axis of gizmo
if g.s_y = 0 then ctrlgizmo3D_SelectAxis(g, Axis_Y)
endif
endif
g.sel = g.s_x or g.s_y or g.s_z or g.s_xz or g.s_xy or g.s_yz
if g.sel
` the user has grabbed the gizmo
if GetPointerPressed() = 1
g.grab = 1
g.p0.x = g.p.x
g.p0.y = g.p.y
g.p0.z = g.p.z
` store the initial position of the grab event
select g.sel
case g.s_x
g.v0.x = g.v1.x
endcase
case g.s_y
g.v0.y = g.v2.y
endcase
case g.s_z
g.v0.z = g.v1.z
endcase
case g.s_xy
g.v0.x = g.v2.x
g.v0.y = g.v2.y
endcase
case g.s_xz
g.v0.x = g.v1.x
g.v0.z = g.v1.z
endcase
case g.s_yz
g.v0.y = g.v3.y
g.v0.z = g.v3.z
endcase
endselect
else
` the user is dragging the gizmo, calculate the current distance of the grab event from the initial event
if GetPointerState() = 1
select g.sel
case g.s_x
g.dv.x = g.v1.x - g.v0.x
gizmo3D_SetPosition(g, g.p0.x + g.dv.x, g.p0.y, g.p0.z)
endcase
case g.s_y
g.dv.y = g.v2.y - g.v0.y
gizmo3D_SetPosition(g, g.p0.x, g.p0.y + g.dv.y, g.p0.z)
endcase
case g.s_z
g.dv.z = g.v1.z - g.v0.z
gizmo3D_SetPosition(g, g.p0.x, g.p0.y, g.p0.z + g.dv.z)
endcase
case g.s_xy
g.dv.x = g.v2.x - g.v0.x
g.dv.y = g.v2.y - g.v0.y
gizmo3D_SetPosition(g, g.p0.x + g.dv.x, g.p0.y + g.dv.y, g.p0.z)
endcase
case g.s_xz
g.dv.x = g.v1.x - g.v0.x
g.dv.z = g.v1.z - g.v0.z
gizmo3D_SetPosition(g, g.p0.x + g.dv.x, g.p0.y, g.p0.z + g.dv.z)
endcase
case g.s_yz
g.dv.y = g.v3.y - g.v0.y
g.dv.z = g.v3.z - g.v0.z
gizmo3D_SetPosition(g, g.p0.x, g.p0.y + g.dv.y, g.p0.z + g.dv.z)
endcase
endselect
endif
endif
endif
gizmo3D_Draw(g)
endfunction
function gizmo3D_Draw(g ref as _CtrlGizmo3D)
x1 as float
y1 as float
x2 as float
y2 as float
color as integer
x1 = GetScreenXFrom3D(g.p.x, g.p.y, g.p.z)
y1 = GetScreenYFrom3D(g.p.x, g.p.y, g.p.z)
x2 = GetScreenXFrom3D(g.p.x + g.h_l, g.p.y, g.p.z)
y2 = GetScreenYFrom3D(g.p.x + g.h_l, g.p.y, g.p.z)
if g.s_x = 1 then color = MakeColor(255, 255, 255) else color = MakeColor(255, 0, 0)
DrawLine(x1, y1, x2, y2, color, color)
if g.s_y = 1 then color = MakeColor(255, 255, 255) else color = MakeColor(0, 255, 0)
x2 = GetScreenXFrom3D(g.p.x, g.p.y + g.h_l, g.p.z)
y2 = GetScreenYFrom3D(g.p.x, g.p.y + g.h_l, g.p.z)
DrawLine(x1, y1, x2, y2, color, color)
x2 = GetScreenXFrom3D(g.p.x, g.p.y, g.p.z + g.h_l)
y2 = GetScreenYFrom3D(g.p.x, g.p.y, g.p.z + g.h_l)
if g.s_z = 1 then color = MakeColor(255, 255, 255) else color = MakeColor(0, 0, 255)
DrawLine(x1, y1, x2, y2, color, color)
` draw the XZ plane handle
x1 = GetScreenXFrom3D(g.h_xz.r, g.p.y, g.h_xz.b)
y1 = GetScreenYFrom3D(g.h_xz.r, g.p.y, g.h_xz.b)
x2 = GetScreenXFrom3D(g.h_xz.r, g.p.y, g.h_xz.t)
y2 = GetScreenYFrom3D(g.h_xz.r, g.p.y, g.h_xz.t)
if g.s_xz = 1 then color = MakeColor(255, 255, 255) else color = MakeColor(255, 0, 0)
DrawLine(x1, y1, x2, y2, color, color)
x1 = GetScreenXFrom3D(g.h_xz.l, g.p.y, g.h_xz.t)
y1 = GetScreenYFrom3D(g.h_xz.l, g.p.y, g.h_xz.t)
x2 = GetScreenXFrom3D(g.h_xz.r, g.p.y, g.h_xz.t)
y2 = GetScreenYFrom3D(g.h_xz.r, g.p.y, g.h_xz.t)
DrawLine(x1, y1, x2, y2, color, color)
` draw the XY plane handle
x1 = GetScreenXFrom3D(g.h_xz.r, g.h_xy.b, g.p.z)
y1 = GetScreenYFrom3D(g.h_xz.r, g.h_xy.b, g.p.z)
x2 = GetScreenXFrom3D(g.h_xz.r, g.h_xy.t, g.p.z)
y2 = GetScreenYFrom3D(g.h_xz.r, g.h_xy.t, g.p.z)
if g.s_xy = 1 then color = MakeColor(255, 255, 255) else color = MakeColor(0, 255, 0)
DrawLine(x1, y1, x2, y2, color, color)
x1 = GetScreenXFrom3D(g.h_xz.l, g.h_xy.t, g.p.z)
y1 = GetScreenYFrom3D(g.h_xz.l, g.h_xy.t, g.p.z)
x2 = GetScreenXFrom3D(g.h_xz.r, g.h_xy.t, g.p.z)
y2 = GetScreenYFrom3D(g.h_xz.r, g.h_xy.t, g.p.z)
DrawLine(x1, y1, x2, y2, color, color)
` draw the YZ plane handle
x1 = GetScreenXFrom3D(g.p.x, g.h_yz.b, g.h_yz.r)
y1 = GetScreenYFrom3D(g.p.x, g.h_yz.b, g.h_yz.r)
x2 = GetScreenXFrom3D(g.p.x, g.h_yz.t, g.h_yz.r)
y2 = GetScreenYFrom3D(g.p.x, g.h_yz.t, g.h_yz.r)
if g.s_yz = 1 then color = MakeColor(255, 255, 255) else color = MakeColor(0, 0, 255)
DrawLine(x1, y1, x2, y2, color, color)
x1 = GetScreenXFrom3D(g.p.x, g.h_yz.t, g.h_yz.l)
y1 = GetScreenYFrom3D(g.p.x, g.h_yz.t, g.h_yz.l)
x2 = GetScreenXFrom3D(g.p.x, g.h_yz.t, g.h_yz.r)
y2 = GetScreenYFrom3D(g.p.x, g.h_yz.t, g.h_yz.r)
DrawLine(x1, y1, x2, y2, color, color)
endfunction
function gizmo3D_Layout(g ref as _CtrlGizmo3D)
g.h_x.l = g.p.x
g.h_x.t = g.p.z + g.h_t * 0.5
g.h_x.r = g.p.x + g.h_l
g.h_x.b = g.p.z - g.h_t * 0.5
g.h_y.l = g.p.z - g.h_t * 0.5
g.h_y.t = g.p.y + g.h_l
g.h_y.r = g.p.z + g.h_t * 0.5
g.h_y.b = g.p.y
g.h_z.l = g.p.x - g.h_t * 0.5
g.h_z.t = g.p.z + g.h_l
g.h_z.r = g.p.x + g.h_t * 0.5
g.h_z.b = g.p.z
g.h_xz.l = g.p.x
g.h_xz.t = g.p.z + g.h_l * 0.1
g.h_xz.r = g.p.x + g.h_l * 0.1
g.h_xz.b = g.p.z
g.h_xy.l = g.p.x
g.h_xy.t = g.p.y + g.h_l * 0.1
g.h_xy.r = g.p.x + g.h_l * 0.1
g.h_xy.b = g.p.y
g.h_yz.l = g.p.z
g.h_yz.t = g.p.y + g.h_l * 0.1
g.h_yz.r = g.p.z + g.h_l * 0.1
g.h_yz.b = g.p.y
endfunction
function ctrlgizmo3D_SelectAxis(g ref as _CtrlGizmo3D, axis as integer)
g.s_x = 0
g.s_y = 0
g.s_z = 0
g.s_xz = 0
g.s_xy = 0
g.s_yz = 0
select axis
case Axis_X
g.s_x = 1
endcase
case Axis_Y
g.s_y = 1
endcase
case Axis_Z
g.s_z = 1
endcase
case Axis_XZ
g.s_xz = 1
endcase
case Axis_XY
g.s_xy = 1
endcase
case Axis_YZ
g.s_yz = 1
endcase
endselect
endfunction
function gizmo3D_SetPosition(g ref as _CtrlGizmo3D, x as float, y as float, z as float)
g.p.x = x
g.p.y = y
g.p.z = z
gizmo3D_Layout(g)
endfunction
function PointIsInRect(x as float, y as float, rect ref as _Rect2D)
l as float
t as float
r as float
b as float
l = fMin(rect.l, rect.r)
r = fMax(rect.l, rect.r)
t = fMin(rect.t, rect.b)
b = fMax(rect.t, rect.b)
if x >= l and x <= r and y >= t and y <= b then exitfunction 1
endfunction 0
function fMin(f1 as float, f2 as float)
if f1 < f2 then exitfunction f1
endfunction f2
function fMax(f1 as float, f2 as float)
if f1 > f2 then exitfunction f1
endfunction f2
function GetXZFromPointer(y_3D as float)
rx as float
ry as float
rz as float
l as float
v as _Vector3
rx = Get3DVectorXFromScreen(GetPointerX(), GetPointerY())
ry = Get3DVectorYFromScreen(GetPointerX(), GetPointerY())
rz = Get3DVectorZFromScreen(GetPointerX(), GetPointerY())
l = (y_3D -GetCameraY(1)) / ry
v.x = GetCameraX(1) + rx * l
v.y = GetCameraY(1) + ry * l
v.z = GetCameraZ(1) + rz * l
endfunction v
function GetXYFromPointer(z_3D as float)
rx as float
ry as float
rz as float
l as float
v as _Vector3
rx = Get3DVectorXFromScreen(GetPointerX(), GetPointerY())
ry = Get3DVectorYFromScreen(GetPointerX(), GetPointerY())
rz = Get3DVectorZFromScreen(GetPointerX(), GetPointerY())
l = (z_3D -GetCameraZ(1)) / rz
v.x = GetCameraX(1) + rx * l
v.y = GetCameraY(1) + ry * l
v.z = GetCameraZ(1) + rz * l
endfunction v
function GetYZFromPointer(x_3D as float)
rx as float
ry as float
rz as float
l as float
v as _Vector3
rx = Get3DVectorXFromScreen(GetPointerX(), GetPointerY())
ry = Get3DVectorYFromScreen(GetPointerX(), GetPointerY())
rz = Get3DVectorZFromScreen(GetPointerX(), GetPointerY())
l = (x_3D -GetCameraX(1)) / rx
v.x = GetCameraX(1) + rx * l
v.y = GetCameraY(1) + ry * l
v.z = GetCameraZ(1) + rz * l
endfunction v
I hope it will be useful to someone