Still pottering away on this. Have realised there is a bug of sorts in above code (spherical cam) The cam viewing the matrix/hyperbola object should be positioned differently. Currently it's not angle and circle preserving like i thought- maybe for first order. Anyway i've fixed it and it works, and seems a little less disorientating. Here's some working code. Bit messy but anyway. Holding the "shift" key shows how the old version looked.
Rem Project: spherical camera
Rem Created: 13/11/2008 15:11:16
Rem ***** Main Source File *****
`by Ed Filby aka Mr Tank
`13th Nov 2008
`this is something i hacked together with educated guesswork
`it's an angle preserving spherical camera
`it renders a standard camera (camera 1) to an image
`this image is spread over a matrix shaped as a hyperbola
`then another camera (camera 0) takes a picture of the hyperbola, and shows this on the screen.
#constant mesh_memblocknum 1
sync on
sync rate 100 `twice what really want- since using 2 cameras!
set display mode 1024,768,32
dim temp_vert_pos#(6,2)
color backdrop 0
autocam off
hide mouse
set normalization on
REMSTART
matsf#=100.0 `scale whole matrix by a # - since seems use whole # sizes
matsizew#=4.0
matsizeh#=3.0
`for test image fov 90, size (vert) should go as 2*tan45
`guess no scale factor required - so use 2..
`matsizew#=2.667
`matsizeh#=2.0
`but 90 deg fov should be less than full possible hyperbola in view..
`guess work- 90 deg fov should mean that half height of view of possible circle
`is used.. this view seems about right!!
`matsizew#=1.333*sqrt(2)
`matsizeh#=1.0*sqrt(2)
`assuming the above is right, if we use a 140 deg fov...
`should be-
`matsizew#=1.333*sqrt(2)*tan(70)
matsizeh#=sqrt(2)*tan(70)
matsizew#=matsizeh# `MAKE A SQUARE CAMERA! - will need to set camera aspect for cam 1 to 1
matdivs=15
matsqw#=matsizew#/(1.0*matdivs)
matsqh#=matsizeh#/(1.0*matdivs)
make matrix 1,matsizew#*matsf#,matsizeh#*matsf#,matdivs,matdivs
set matrix 1,1,0,1,1,0,0,0
`make a hyperbolic surface....
for m=0 to matdivs
for n=0 to matdivs
x#=(m-0.5*matdivs)*matsqw#
y#=(n-0.5*matdivs)*matsqh#
h#=sqrt(1.0+x#*x#+y#*y#)
set matrix height 1,m,n,0.0-h#*matsf#
next n
next m
position matrix 1,-0.5*matsizew#*matsf#,0.0,-0.5*matsizeh#*matsf#
update matrix 1
REMEND
make_hyperbola_matrix(0) `makes obj 2000- for view centred at hyperbola origin
make_hyperbola_matrix(1) `makes obj 2001- for view centred on opposite hyperbola part.
`SCENE
numboxes=200
load image "cratetop.jpg",2
`load image "baked04.JPG",2
for n=1 to numboxes
`make object cube n,1
if n=1
make object cube n,1
scale object n,100,100,4000 `5000
texture object n,2
else
instance object n,1
scale object n,100,100,4000 `5000
endif
`position object n,rnd(80)-40,rnd(40),rnd(80)-40
position object n,rnd(80)-40,rnd(80)-40,rnd(80)-40
point object n,0,0,0
`color object n,rgb(rnd(250),rnd(250),rnd(250))
`set object light n,0
`set object ambient n,0
`rotate object n,rnd(359),rnd(359),rnd(359)
`rotate object n,90*rnd(3),90*rnd(3),90*rnd(3)
next n
make object cube 1000,125
`scale object 1000,100,-100,100
texture object 1000,2
`scale object texture 1000,80,80
scale object texture 1000,20,20
set object cull 1000,0
`set object light 1000,0
`set object ambient 1000,0
make object sphere 1001,10,20,20
`texture object 1001,2
set directional light 0,0.2,1,0
make light 1
set directional light 1,-0.2,-1,0
color light 1,-50,-50,-50
set ambient light 100
color ambient light rgb(150,150,150)
color light 0,150,150,150
fog on
fog distance 10,350
fog color rgb(200,200,200)
`CAMERA TO TAKE PIC OF WORLD
make camera 1
set camera to image 1,1,1024,1024 `needs to be power of 2 to work - at least on my computer
`set camera to image 1,1,2048,1024
position camera 1,0,0,0
pitch camera up 1,90
set camera fov 1,90
`set camera fov 1,140 `wider angle..
set camera fov 1,150
`set camera fov 1,80
set camera range 1,0.05,250
set camera aspect 1,1 `so can use square camera - otherwise is 1.333 by default
`set camera aspect 1,2
color backdrop 1,rgb(255,0,0)
do
hide object 2000
hide object 2001
for n=1 to numboxes:show object n:next n
show object 1000
show object 1001
pitch camera down 1,mousemovey()
turn camera right 1,mousemovex()
mc=mouseclick()
move camera 1,0.2*((mc&&%1)-((mc&&%10)>>1))
if controlkey():save image "test.bmp",1:endif
sync mask 2:sync
`have to reprepare matrix texture and update!
`hellaciously slow- should use memblock object instead of matrix, but a pain in the bum to make...
REMSTART
prepare matrix texture 1,1,matdivs,matdivs
tile=1
for n=matdivs-1 to 0 step -1:for m=0 to matdivs-1
set matrix tile 1,m,n,tile
inc tile
next n:next m
update matrix 1
REMEND
view=1-shiftkey()
viewobj=2000+view
texture object viewobj,1 `retexture call necessary??
`if spacekey() then set matrix wireframe on 1 else set matrix wireframe off 1
set object wireframe viewobj,spacekey()
show object viewobj
for n=1 to numboxes:hide object n:next n
hide object 1000
hide object 1001
text 0,0,str$(screen fps())
`test whether orienting camera has any effect on what
`view looks like. i suspect it might just move view around (although cam range clipping
`wont work the same..)
`actually perhaps not that simple - but may be able to use multiple cams to break 180 deg
`fov limit for 1 camera.
`should solve for lower dimensions first- ie for cylindrical camera...
`won't be simple rotation- since final cam only sees max of hemisphere..
`along#=curvevalue(10.0*(leftkey()-rightkey()),along#,10.0)
`zrotate camera 0,along#
along#=curvevalue(1.0*(leftkey()-rightkey()),along#,10.0)
roll camera left 1,along#
`THINK MAY HAVE MADE SMALL ERROR IN CALCULATION FOR POSITION OF ZEROTH CAMERA.
`SHOULD CHECK THIS OUT..
if view
position camera 0,0,100.0,0
`set camera fov 45
set camera fov 56.25
else
position camera 0,0,0,0
`set camera fov 80 `NB HAVE CHANGED MESH SO WILL NOT LOOK RIGHT ANYMORE,
`, IF EVER ACTUALLY WAS RIGHT!
set camera fov 100
endif
set camera range 0,10,1000
`^^NEW position (shift pressed) doesn't seem to be angle preserving- so
`new code must have a mistake somewhere! :(
sync mask 1:sync
loop
end
function make_hyperbola_matrix(viewtype)
matsf#=100.0 `scale whole matrix by a # - since seems use whole # sizes
`matsizeh#=sqrt(2)*tan(70)
matsizeh#=sqrt(2)*tan(75)
matsizew#=matsizeh# `MAKE A SQUARE CAMERA! - will need to set camera aspect for cam 1 to 1
`matsizeh#=sqrt(2)*tan(40)
`matsizeh#=sqrt(2)*tan(40)
`matsizew#=2*matsizeh# `long camera!
`matdivs=15
matdivs=20
matsqw#=matsizew#/(1.0*matdivs)
matsqh#=matsizeh#/(1.0*matdivs)
REMSTART
make matrix 1,matsizew#*matsf#,matsizeh#*matsf#,matdivs,matdivs
set matrix 1,1,0,1,1,0,0,0
`make a hyperbolic surface....
for m=0 to matdivs
for n=0 to matdivs
x#=(m-0.5*matdivs)*matsqw#
y#=(n-0.5*matdivs)*matsqh#
h#=sqrt(1.0+x#*x#+y#*y#)
set matrix height 1,m,n,0.0-h#*matsf#
next n
next m
position matrix 1,-0.5*matsizew#*matsf#,0.0,-0.5*matsizeh#*matsf#
update matrix 1
REMEND
num_vertices=6*matdivs*matdivs `6 per square- since a square is 2 triangles
mesh_memblocksize=12+36*num_vertices
make memblock mesh_memblocknum, mesh_memblocksize
write memblock dword mesh_memblocknum,0,338
write memblock dword mesh_memblocknum,4,36
write memblock dword mesh_memblocknum,8,num_vertices
mycolour as dword `vertex colour. NB there is deffo another memblock mesh format that doesn't have vert colour in it.
mycolour=0xFFFFFFFF
memblock_pos=12 `next position to write
for m=0 to matdivs-1
for n=0 to matdivs-1
xin#=-0.5*matsizew# + matsqw#*m
yin#=-0.5*matsizeh# + matsqh#*n
xout#=xin#+matsqw#
yout#=yin#+matsqh#
temp_vert_pos#(1,0)=xin# ` *matsf#
temp_vert_pos#(1,1)=yin# ` *matsf#
temp_vert_pos#(2,0)=xout# ` *matsf#
temp_vert_pos#(2,1)=yout# ` *matsf#
temp_vert_pos#(3,0)=xin# ` *matsf#
temp_vert_pos#(3,1)=yout# ` *matsf#
temp_vert_pos#(4,0)=xin# ` *matsf#
temp_vert_pos#(4,1)=yin# ` *matsf#
temp_vert_pos#(5,0)=xout# ` *matsf#
temp_vert_pos#(5,1)=yin# ` *matsf#
temp_vert_pos#(6,0)=xout# ` *matsf#
temp_vert_pos#(6,1)=yout# ` *matsf#
for t=1 to 6
a#=temp_vert_pos#(t,0) ` / matsf#
b#=temp_vert_pos#(t,1) ` / matsf
if viewtype=0
`h#=sqrt(1.0+a#*a#+b#*b#)
h#=sqrt(1.0+0.707*(a#*a#+b#*b#)) `seems to make look ALMOST the same as below
else
h#=sqrt(1.0+2.0*(a#*a#+b#*b#)) `APPEARS TO MAKE MOVED BACK CAM ANGLE PRESERVING?!!
`also circle preserving- not sure why need the constant?!!
`ie one with cam centre at 0,1,0 facing down at hyperbola...
endif
temp_vert_pos#(t,2)=0.0-h# `*matsf#
next t
for t=1 to 6
`VERTEX COORDS
write memblock float mesh_memblocknum,memblock_pos,temp_vert_pos#(t,0)*matsf#
inc memblock_pos,4
write memblock float mesh_memblocknum,memblock_pos,temp_vert_pos#(t,2)*matsf#
inc memblock_pos,4
write memblock float mesh_memblocknum,memblock_pos,temp_vert_pos#(t,1)*matsf# `was just 0.0 before added height variable..
inc memblock_pos,4
`NORMALS
write memblock float mesh_memblocknum,memblock_pos,0.0 `temp_vert_pos#(t,3)
inc memblock_pos,4
write memblock float mesh_memblocknum,memblock_pos,1.0 `temp_vert_pos#(t,4)
inc memblock_pos,4
write memblock float mesh_memblocknum,memblock_pos,0.0 `temp_vert_pos#(t,5)
inc memblock_pos,4
`VERT COLOUR
write memblock dword mesh_memblocknum,memblock_pos,mycolour
inc memblock_pos,4
`UV COORDS - set as just x and y
uvscale#=0.1
write memblock float mesh_memblocknum,memblock_pos,temp_vert_pos#(t,0)/matsizew#-0.5 `uvscale#*temp_vert_pos#(t,0)
inc memblock_pos,4
write memblock float mesh_memblocknum,memblock_pos,0.5-temp_vert_pos#(t,1)/matsizeh# `uvscale#*temp_vert_pos#(t,1)
inc memblock_pos,4
next t
next n
next m
`if object exist(track_objnum) then delete object track_objnum
meshnum=1
make mesh from memblock meshnum, mesh_memblocknum
delete memblock mesh_memblocknum
if viewtype=0
make object 2000,meshnum,1 `track_imagenum
set object 2000,1,0,0,1,0,0,0
else
make object 2001,meshnum,1 `track_imagenum
set object 2001,1,0,0,1,0,0,0
endif
delete mesh meshnum
`position object 2000,0,-0.6,0 `make a little behind ordinary one
`texture object 2000,1
position camera 0,0,0
point camera 0,-1,0
`for a circular camera - set max range to depth of hyperbola at centre of edge..
x#=(0.5*matdivs)*matsqw#
maxrange#=sqrt(1.0+x#*x#)*matsf#
set camera range 90,maxrange# `maxrange is for circle view.. `300
set camera fov 90
`guess that, for small alpha, fov should be proportional to the area (viewed from above)
`of matrix projected onto (the fov of the original normal camera image). guess that
`the area (or rather , side length) should scale with the picture size- ie not the fov,
`but as 2*tan(fov/2).
`test smaller fov now- how cam would be used in actual game..
`set camera fov 48
`set camera fov 60 `GOOD FOR 140 - almost no black on screen..
set camera fov 83 `GOOD FOR 140 - whole circle in view
`set camera fov 87 `good for 150...
`set camera fov 65.2
`set camera fov 60
endfunction
I came to find this whilst thinking about the multicam spherical camera. I have solved for 1 axis. Hopefully can get it running soon. Then i'll hopefully produce a tidier, more understandable/usable version with variables etc so people can hopefully use this in their games.