Have a look here. Madbit has a very simple and elegant solution
I have done some additional work on it here. Either my math or my theory didn't hold up
// Project: test27
// Created: 2019-03-19
// show all errors
SetErrorMode(2)
// set window properties
SetWindowTitle( "test27" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window
// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts
SetSunActive(1)
SetSunDirection(0.5, -1, 0.5)
SetSunColor(0x80, 0x80, 0x80)
SetambientColor(0x80, 0x80, 0x80)
id = CreateObjectBox(1, 1, 3)
//SetObjectVisible(id, 0)
b = CReateObjectPlane(0.1, 0.1)
SetObjectColor(b, 0, 0xff, 0, 0xff)
FixObjectToObject(b, id)
text as string
//text = getClipboardText()
text = "Robert M"+chr(0xFC)+"ller"
SetClipboardText(text)
text = GetClipboardText()
h as String
h = hex(asc(text))
type point
x as float
y as float
z as float
endtype
SetCameraPosition(1, 0, 2, -5)
bounds as integer[]
b = CReateObjectPlane(0.1, 0.1)
SetObjectPosition(b, GetObjectSizeMinX(id), GetObjectSizeMinY(id), GetObjectSizeMinZ(id))
bounds.insert(b)
b = CReateObjectPlane(0.1, 0.1)
SetObjectPosition(b, GetObjectSizeMinX(id), GetObjectSizeMaxY(id), GetObjectSizeMinZ(id))
bounds.insert(b)
b = CReateObjectPlane(0.1, 0.1)
SetObjectPosition(b, GetObjectSizeMaxX(id), GetObjectSizeMaxY(id), GetObjectSizeMinZ(id))
bounds.insert(b)
b = CReateObjectPlane(0.1, 0.1)
SetObjectPosition(b, GetObjectSizeMaxX(id), GetObjectSizeMinY(id), GetObjectSizeMinZ(id))
bounds.insert(b)
b = CReateObjectPlane(0.1, 0.1)
SetObjectPosition(b, GetObjectSizeMinX(id), GetObjectSizeMinY(id), GetObjectSizemaxZ(id))
bounds.insert(b)
b = CReateObjectPlane(0.1, 0.1)
SetObjectPosition(b, GetObjectSizeMinX(id), GetObjectSizeMaxY(id), GetObjectSizemaxZ(id))
bounds.insert(b)
b = CReateObjectPlane(0.1, 0.1)
SetObjectPosition(b, GetObjectSizeMaxX(id), GetObjectSizeMaxY(id), GetObjectSizemaxZ(id))
bounds.insert(b)
b = CReateObjectPlane(0.1, 0.1)
SetObjectPosition(b, GetObjectSizeMaxX(id), GetObjectSizeMinY(id), GetObjectSizemaxZ(id))
bounds.insert(b)
for i=0 to bounds.length
FixObjectToObject(bounds[i], id)
next
bb as integer[]
for i=0 to 3
b = CreateObjectPlane(0.1, 0.1)
SetObjectColor(b, 0, 0xff, 0, 0xff)
bb.insert(b)
next
SetCameraPosition(1, -2, 2, -4)
SetCameraLookAt(1, 0, 0, 0, 0)
RotateObjectGlobalY(id, random(1, 360))
RotateObjectGlobalZ(id, random(1, 360))
global largest as integer
do
if GetRawKeyPressed(38)
MoveCameraLocalZ(1, 0.1)
endif
if GetRawKeyPressed(40)
MoveCameraLocalZ(1, -0.1)
endif
if GetRawKeyPressed(asc("T"))
RotateObjectGlobalY(id, random(1, 360))
RotateObjectGlobalZ(id, random(1, 360))
endif
if GetRawKeyPressed(asc("R"))
SetCameraPosition(1, -2, 2, -4)
SetCameraLookAt(1, 0, 0, 0, 0)
endif
if GetRawKeyPressed(32)
checkbounds(id, bounds, bb, 1)
else
checkbounds(id, bounds, bb, 0)
endif
print("SPACE-To frame object, T-Rotate object R-Reset camera")
Sync()
loop
function CheckBounds(id as integer, bounds as integer[], bb as integer[], fct as integer)
p as point
f as point
t as point
d as float
x as integer
rp as point
lp as point
bp as point
tp as point
ip as float[]
mp as point
op as point
a as float
f.x = 99999999
f.y = 99999999
t.x = -99999999
t.y = -99999999
for i=0 to bounds.length
p.x = GetScreenXFrom3D(GetObjectWorldX(bounds[i]), GetObjectWorldY(bounds[i]), GetObjectWorldZ(bounds[i]))
p.y = GetScreenYFrom3D(GetObjectWorldX(bounds[i]), GetObjectWorldY(bounds[i]), GetObjectWorldZ(bounds[i]))
if p.x < f.x
f.x = p.x
endif
if p.x > t.x
t.x = p.x
endif
if p.y < f.y
f.y = p.y
endif
if p.y > t.y
t.y = p.y
endif
next
d = Distance3D(GetObjectPos(id), GetCameraPos(1))
op = GetObjectPos(id)
mp.x = Get3DVectorXFromScreen( f.x + (t.x - f.x) / 2, f.y + (t.y - f.y) / 2) * d + GetCameraX(1)
mp.y = Get3DVectorYFromScreen( f.x + (t.x - f.x) / 2, f.y + (t.y - f.y) / 2) * d + GetCameraY(1)
mp.z = Get3DVectorZFromScreen( f.x + (t.x - f.x) / 2, f.y + (t.y - f.y) / 2) * d + GetCameraZ(1)
rp.x = Get3DVectorXFromScreen( f.x, f.y + (t.y - f.y) / 2) * d + GetCameraX(1)
rp.y = Get3DVectorYFromScreen( f.x, f.y + (t.y - f.y) / 2) * d + GetCameraY(1)
rp.z = Get3DVectorZFromScreen( f.x, f.y + (t.y - f.y) / 2) * d + GetCameraZ(1)
lp.x = Get3DVectorXFromScreen( t.x, f.y + (t.y - f.y) / 2) * d + GetCameraX(1)
lp.y = Get3DVectorYFromScreen( t.x, f.y + (t.y - f.y) / 2) * d + GetCameraY(1)
lp.z = Get3DVectorZFromScreen( t.x, f.y + (t.y - f.y) / 2) * d + GetCameraZ(1)
bp.x = Get3DVectorXFromScreen( f.x + (t.x - f.x) / 2, t.y ) * d + GetCameraX(1)
bp.y = Get3DVectorYFromScreen( f.x + (t.x - f.x) / 2, t.y ) * d + GetCameraY(1)
bp.z = Get3DVectorZFromScreen( f.x + (t.x - f.x) / 2, t.y ) * d + GetCameraZ(1)
tp.x = Get3DVectorXFromScreen( f.x + (t.x - f.x) / 2, f.y ) * d + GetCameraX(1)
tp.y = Get3DVectorYFromScreen( f.x + (t.x - f.x) / 2, f.y ) * d + GetCameraY(1)
tp.z = Get3DVectorZFromScreen( f.x + (t.x - f.x) / 2, f.y ) * d + GetCameraZ(1)
if fct = 1
d = 0
ip.insert(Distance3D(lp, rp) * 0.8)
ip.insert(Distance3D(tp, bp) * 0.8)
for x=0 to ip.length
if ip[x] > d
d = ip[x]
largest=x
endif
next
a = GetCameraFOV(1) / 2
d = d / tan(a)
SetCameraLookAt(1, mp.x, mp.y, mp.z, 0)
SetCameraPosition(1, mp.x, mp.y, mp.z)
MoveCameraLocalZ(1, -d)
endif
SetObjectPosition(bb[0], tp.x, tp.y, tp.z)
SetObjectLookAt(bb[0], GetCameraX(1), GetCameraY(1), GetCameraZ(1), 0)
SetObjectPosition(bb[1], lp.x, lp.y, lp.z)
SetObjectLookAt(bb[1], GetCameraX(1), GetCameraY(1), GetCameraZ(1), 0)
SetObjectPosition(bb[2], bp.x, bp.y, bp.z)
SetObjectLookAt(bb[2], GetCameraX(1), GetCameraY(1), GetCameraZ(1), 0)
SetObjectPosition(bb[3], rp.x, rp.y, rp.z)
SetObjectLookAt(bb[3], GetCameraX(1), GetCameraY(1), GetCameraZ(1), 0)
DrawBox(f.x, f.y, t.x, t.y, 0x808080, 0x808080, 0x808080, 0x808080, 0)
DrawLine(f.x, f.y + (t.y - f.y) / 2, f.x + (t.x - f.x) / 2, f.y + (t.y - f.y) / 2, 0x0000ff, 0x0000ff, 0)
DrawLine(f.x + (t.x - f.x) / 2, f.y + (t.y - f.y) / 2, f.x + (t.x - f.x) / 2, t.y, 0x0000ff, 0x0000ff, 0)
endfunction
function Distance3D(fp as point, tp as point)
dist as float
dist = sqrt((fp.x - tp.x)^2 + (fp.y - tp.y)^2 + (fp.z - tp.z)^2 )
endfunction dist
function GetCameraPos(id as integer)
p as point
p.x = GetCameraX(id)
p.y = GetCameraY(id)
p.z = GetCameraZ(id)
endfunction p
function GetObjectPos(id as integer)
p as point
p.x = GetObjectX(id)
p.y = GetObjectY(id)
p.z = GetObjectZ(id)
endfunction p