This example show off the new RotateVertexList (support XYZ & ZYX rotations) command (playBASIC V1.10). These commands, as you might have guessed rotates a set of vertexes (stored in memory).
The demo creates a set of random vertexes rotates them, the draws them as a set of shaded pixels to the scene buffer for rendering.
Even with 5000 vertex on my duron 800 it's still running 35+ fps. And about 19/20 FPS with 10000 vertex.
[pbcode]
MakeBitmapfont 1,$ffffff
SizeX=1000
SizeY=1000
SizeZ=1000
Max=5000
VertSize =12
SrcBank=NewBank((Max+1)*VertSize)
DEstBank=NewBank((Max+1)*VertSize)
SrcAddress =getbankptr(SrcBank)
DestAddress =getbankptr(SrcBank)
for lp=0 to Max
Pokefloat SrcAddress,float(rndrange(-sizex,sizex))
Pokefloat SrcAddress+4,float(rndrange(-sizey,sizey))
Pokefloat SrcAddress+8,float(rndrange(-sizez,sizez))
SrcAddress=SrcAddress+12
next
projectionx#=300
projectiony#=300
basex#=0
basey#=0
basez#=1000
Dim ShadeBufferBuffer(20000)
maxdepth#=3000
scaler#=100/maxdepth#
col=$8fff3f
col=rgb(255,255,255)
For lp=0 to maxdepth#
; if mod(lp,1000)=0 then col=rndrgb()
ShadeBufferBuffer(lp)=rgbfade(col,(maxdepth#-lp)*scaler#)
next
createcamera 1
Do
capturetoscene
clsscene
; Rotate vertex list (with XYZ rotation order)
SrcAddress =getbankptr(SrcBank)
DestAddress =getbankptr(destBank)
RotateVertexListXYZ SrcAddress,DestAddress,12,12,baseX#,basey#,baseZ#,ax#,ay#,az#,max
t=timer()
Address =getbankptr(DestBank)
counter=max
do
z#=Peekfloat(Address+8)
if z#>10
dotc 400+((Peekfloat(Address)*projectionx#)/z#),300+((Peekfloat(Address+4)*projectiony#)/z#),ShadeBufferBuffer(z#)
endif
address=address+12
decloop counter
t=timer()-t
drawcamera 1
setcursor 0,0
speed#=10
if upkey() then basez#=basez#+speed#
if downkey() then basez#=basez#-speed#
ax#=wrapangle(ax#,0.01)
ay#=wrapangle(ay#,0.02)
az#=wrapangle(az#,0)
Print "Rotated Vertex Lists"
print str$(max)+" Shaded Z buffered Vertex"
print fps()
Sync
loop
[/pbcode]
Hi!
Where can I get PB1.10 ? :unsure:
Greetings
stef
I'll be building the V1.10 patch later on today/tonight. It's not great deal different from V1.089 at this point, but a few critical VM bugs have been fixed. And of course while i'm here i'm adding some new toys for good measure :)
See->[plink]PlayBASIC Developer Blog (http://www.underwaredesign.com/forums/index.php?topic=338.0)[/plink] (OLD INFO) as of 2023 go to home PlayBASIC home page to download PlayBASIC Updates (https://playbasic.com)
While were here, the above rotation commands have already change (different parameters). Now you pass the routines a pointer to a simple object structure which olds the (axis position/rotation/scale and projection flags). It's too many parameters to be passing a function. In the future the user will pass a pointer to Type, rather than a bank pointer. But anyway. So the current implementation is subject to change.
I'm also adding a translate to viewer style rotation command. This will rotate the vertex on their local access and then rotate/project them to a viewer. This will allow your to build your own software 3D engine (like uw3d) easier, with much faster results.
Although it should be noted that polygon clipping (to the z near and far z planes) will still have to be performed by the user.
As mentioned, I've changed the above functions a little and have now finally got the RotateVertexListToCamera working. This command rotates a vertex list(s) to a viewers perspective.
The tech demo is runnnig a 30 plus FPS with 7000 depth shaded, Z sorted points on my crusty old Duron 800.
The viewer can move around with Arrow keys and look using the mouse. ie. standard fps controls.
Note: Was developed in and requires at least PlayBASIC V1.10 (2006)
Object Include
[pbcode]
// Define 'Object' Structure for RotateVertexLIst commands
Constant PB_RotationObject_iStatus =0
Constant PB_RotationObject_fXpos =4
Constant PB_RotationObject_fYpos =8
Constant PB_RotationObject_fZpos =12
Constant PB_RotationObject_fXAngle =16
Constant PB_RotationObject_fYAngle =20
Constant PB_RotationObject_fZAngle =24
Constant PB_RotationObject_fXScale =28
Constant PB_RotationObject_fYScale =32
Constant PB_RotationObject_fZScale =36
Constant PB_RotationObject_iRotationMode =40
Constant PB_RotationObject_iProjectionMode =44
Constant PB_RotationObject_fXProjection =48
Constant PB_RotationObject_fYProjection =52
Constant PB_RotationObject_StructSize =56
Function CreateVertexObject(Xpos#,Ypos#,Zpos#)
VertexObject=NewBank(PB_RotationObject_StructSize)
; seed Object Structure
PokeBankint VertexObject,PB_RotationObject_iStatus,true
PositionVertexObject(VertexObject,Xpos#,Ypos#,Zpos#)
RotateVertexObject(VertexObject,0,0,0)
ScaleVertexObject(VertexObject,1,1,1)
VertexObjectRotationMode(VertexObject,0)
VertexObjectProjectionMode(VertexObject,off,0,0)
EndFunction VertexObject
Function VertexObjectRotationMode(VertexObject,mode)
if GetBankStatus(VertexObject)
PokeBankInt VertexObject,PB_RotationObject_iRotationMode,Mode
endif
EndFunction
Function VertexObjectProjectionMode(VertexObject,State,ProjectX#,ProjectY#)
if GetBankStatus(VertexObject)
PokeBankInt VertexObject,PB_RotationObject_iProjectionMode,state
PokeBankFloat VertexObject,PB_RotationObject_fXProjection,ProjectX#
PokeBankFloat VertexObject,PB_RotationObject_fYProjection,ProjectY# ; default X projection
endif
EndFunction
Function PositionVertexObject(VertexObject,Xpos#,Ypos#,Zpos#)
if GetBankStatus(VertexObject)
; seed Object Structure
PokeBankFloat VertexObject,PB_RotationObject_fXpos,Xpos#
PokeBankFloat VertexObject,PB_RotationObject_fYpos,Ypos#
PokeBankFloat VertexObject,PB_RotationObject_fZpos,Zpos#
endif
EndFunction
Function GetVertexObjectPosition(VertexObject)
if GetBankStatus(VertexObject)
; seed Object Structure
xpos#=PeekBankFloat(VertexObject,PB_RotationObject_fXpos)
ypos#=PeekBankFloat(VertexObject,PB_RotationObject_fYpos)
zpos#=PeekBankFloat(VertexObject,PB_RotationObject_fZpos)
endif
EndFunction Xpos#,YPos#,Zpos#
Function RotateVertexObject(VertexObject,Xangle#,Yangle#,Zangle#)
if GetBankStatus(VertexObject)
; seed Object Structure
PokeBankFloat VertexObject,PB_RotationObject_fXAngle,Xangle#
PokeBankFloat VertexObject,PB_RotationObject_fYAngle,Yangle#
PokeBankFloat VertexObject,PB_RotationObject_fZAngle,Zangle#
endif
EndFunction
Function GetVertexObjectRotation(VertexObject)
if GetBankStatus(VertexObject)
; seed Object Structure
Xangle#=PeekBankFloat(VertexObject,PB_RotationObject_fXAngle)
Yangle#=PeekBankFloat(VertexObject,PB_RotationObject_fYAngle)
Zangle#=PeekBankFloat(VertexObject,PB_RotationObject_fZAngle)
endif
EndFunction Xangle#,Yangle#,Zangle#
Function ScaleVertexObject(VertexObject,Xscale#,Yscale#,Zscale#)
if GetBankStatus(VertexObject)
; seed Object Structure
PokeBankFloat VertexObject,PB_RotationObject_fXScale,Xscale#
PokeBankFloat VertexObject,PB_RotationObject_fYScale,Yscale#
PokeBankFloat VertexObject,PB_RotationObject_fZScale,Zscale#
endif
EndFunction
[/pbcode]
demo
[pbcode]
MakeBitmapfont 1,$ffffff
ProjectionX#=300
ProjectionY#=300
; Init the Size of the Source and rotated Vertexs
constant SrcVertSize =12
Constant DestVertSize =20
Type tObject
status
; Object Bank
ObjectBank
; Vertex Bank
VertexBank
; Rotation Speeds for this object
RotSpeedX#
RotSpeedY#
RotSpeedZ#
NumberOFVerts
EndType
Dim Object(10) as tObject
NumberOfVertex=1000
Obj=1
; ==================================
; make the corner pillars
; ==================================
x=800
z=800
sizex=100
Sizey=650
sizez=100
NewObject(obj,x,sizey,z,SizeX,SizeY,SizeZ,1000)
object(obj).rotspeedy#=1.5
inc obj
NewObject(obj,-x,sizey,z,SizeX,SizeY,SizeZ,1000)
inc obj
NewObject(obj,-x,sizey,-z,SizeX,SizeY,SizeZ,1000)
inc obj
NewObject(obj,x,sizey,-z,SizeX,SizeY,SizeZ,1000)
inc obj
; create the ceiling plane
NewObject(obj,0,sizey*2,0,X,50,Z,1000)
inc obj
; create a bigger floor plane
NewObject(obj,0,0,0,2000,50,2000,2000)
inc obj
; Create Camera Object
; =====================================
CameraObject=CreateVertexObject(0,0,-2000)
VertexObjectProjectionMode(CameraObject,1,ProjectionX#,ProjectionY#)
; =====================================
; Create Desitnation Vertex Buffer
; =====================================
DestVertexBank=NewBank(20000*DestVertSize)
; =======================================================
; Pre-calc the shading
; =======================================================
Dim ShadeBufferBuffer(20000)
NumberOfVertexdepth#=3000
scaler#=100/NumberOfVertexdepth#
col=rgb(255,255,255)
For lp=0 to NumberOfVertexdepth#
ShadeBufferBuffer(lp)=rgbfade(col,(NumberOfVertexdepth#-lp)*scaler#)
next
createcamera 1
Do
capturetoscene
clsscene
; Rotate vertex list (with XYZ rotation order)
CameraAddress=getbankptr(CameraObject)
ObjectAddress=getbankptr(VertexObject)
DestVertexbufferAddress =GetBankPtr(DestVertexBank)
TotalNumberOFVertexs=0
For Obj=0 to GetarrayElements(Object().tObject,1)
if Object(obj).status=true
ThisObject=Object(obj).ObjectBank
ax#,ay#,az#=GetVertexObjectRotation(ThisObject)
ax#=wrapangle(ax#,object(obj).rotspeedx)
ay#=wrapangle(ay#,object(obj).rotspeedy)
az#=wrapangle(az#,object(obj).rotspeedz)
RotateVertexObject ThisObject,ax#,ay#,az#
ObjectAddress=GetBankPtr(ThisObject)
SrcVertexBufferAddress=getBankPtr(Object(obj).vertexbank)
NumberOfVertex=object(obj).NumberOFVerts
TotalNumberOFVertexs=TotalNumberOFVertexs+NumberOFVertex
RotateVertexListToCamera CameraAddress,ObjectAddress,SrcVertexBufferAddress,SrcVertSize,DestVertexbufferAddress,DestVertSize,NumberOfVertex
Address =DestVertexbufferAddress+8
do
z#=Peekfloat(Address)
if z#>10
capturedepth z#
dotc 400+Peekfloat(Address+4),300+Peekfloat(Address+8),ShadeBufferBuffer(z#)
endif
address=address+destVertSize
decloop NumberOfVertex
endif
next
drawcamera 1
setcursor 0,0
speed#=10
Control_Camera(CameraObject,20)
; ax#=wrapangle(ax#,0.22)
; ay#=wrapangle(ay#,0.42)
; az#=wrapangle(az#,0.9)
if KeyPressed=false
if scancode()<>0 then KeyPressed=true
if spacekey()
DemoMOde=1-demoMOde
endif
else
if scancode()=0 then KeyPressed=False
endif
Print "Rotating Vertex Lists To Viewer/Camera"
print str$(TotalNumberOFVertexs)+" Shaded Z buffered Vertex"
print "Fps:"+str$(fps())
Sync
loop
Function NewObject(obj,x,y,z,SizeX,SizeY,SizeZ,Verts)
Object(obj).status=true
VertexObject=CreateVertexObject(x,y,z)
Object(obj).ObjectBank=VertexObject
; create Vertex Obejct Structure
VertexObjectRotationMode(VertexObject,0); ZYX
Object(obj).VertexBank=Make_Random_Vertex_region(sizex,sizey,sizez,Verts)
object(obj).NumberOFVerts=Verts
EndFUnction
Function Make_Random_Vertex_region(sizex,sizey,sizez,NumberOfVertex)
; Create Vertex Buffers
VertexBank=NewBank((NumberOfVertex+1)*SrcVertSize)
Address =getbankptr(VertexBank)
for lp=0 to NumberOfVertex
Pokefloat Address,float(rndrange(-sizex,sizex))
Pokefloat Address+4,float(rndrange(-sizey,sizey))
Pokefloat Address+8,float(rndrange(-sizez,sizez))
Address=Address+SrcVertSize
next
EndFUnction VertexBank
Psub Control_Camera(CameraObject,camspeed#)
W=GetScreenWidth()
H=GetScreenHeight()
x1=GetScreenXpos()
Y1=GetScreenYpos()
x2=x1+w
y2=y1+h
MMX#=MouseMoveX()
MMY#=MouseMoveY()
x#=x1+MouseX()
y#=y1+MouseY()
flag=0
If x#=<(x1+75) Then x#=x1+(w/2): flag=1
If x#=>(x2-75) And flag=0 Then x#=x1+(w/2): flag=1
If y#=<(y1+75) Then y#=y1+(h/2): flag=1
If y#=>(y2-75) Then y#=y1+(h/2): flag=1
If flag=1
SetMouse x#,y#
MMX2#=MouseMoveX()
MMY2#=MouseMoveY()
SetMouse x#,y#
EndIf
camf#=0
camx#=WrapAngle(camx#,Mmy#*0.7)
camy#=WrapAngle(camy#,mmx#*0.7)
acamx#=CurveAngle(camx#,acamx#,2.1)
acamy#=CurveAngle(camy#,acamy#,2.1)
; Rotate_Camera acamx#,acamy#,0
RotateVertexObject(CameraObject,acamx#,acamy#,0)
If UpKey()=1 Then camf#=camf#+camspeed#
If DownKey()=1 Then camf#=camf#-camspeed#
` if camf#<>0 then move camera camf#
If camf#<>0
movementx#,movementy#,movementz#=CalcMovement(acamx#,acamy#,0.0,Camf#)
X#,Y#,Z#=GetVertexObjectPosition(CameraObject)
x#=x#+movementx#
y#=y#+movementy#
z#=z#+movementz#
; clip the camera to 20 on y axis
if y#<20 then y#=20
PositionVertexObject(CameraObject,x#,y#,z#)
EndIf
EndPsub
Function CalcMovement(Anglex#,angley#,anglez#,Speed#)
` invert angles
anglex#=360-anglex#
angley#=WrapAngle(90,-angley#)
anglez#=360-anglez#
` precalc cos+sin for rotation
cx#=Cos(anglex#)
sx#=Sin(anglex#)
cy#=Cos(angley#)
sy#=Sin(angley#)
; cz#=Cos(anglez#)
; sz#=Sin(anglez#)
; xpos#=0
; Ypos#=0
Zpos#=Speed#
z#=(cx#*Zpos#)
y#=(sx#*zpos#)
` Around Y axis
x2#=(cY#*Z#)-(sy#*X#)
z#=((cy#*X#)+(sy#*Z#))
EndFunction x2#,y#,z#
[/pbcode]
Just toying with vertex lists for a tech demo. Here's some shots rendering a wall of circles within the vertex world.
and another
Cool :)
Nah that's not cool..
But this is ! :)
Seriously! :D
I actually saw a web remake of Super Mario Bros done like that. :)
I also saw ManicMiner3D a while back. (Don't forget to check out the 3D Dizzy mock-up too - it's really cool).
That was basically the the plan. Well, port the existing platformer demo in at least.