Rotate Vertex List Directly Into Arrays
Since array accesses have a higher precedence (faster) in Vm1/Vm2 than pointer and bank accesses, then if you're dealing with lots of vertex /rotation stuff, it makes more sense to rotate your vertex buffers into a 2D array. Then access the rotated verts through the array interface.
Here's version the Rotation demo fro the example pack that uses this method.
[pbcode]
; include the Vertex Objects expansion library
#include "VertexObjects"
MakeBitmapFont 1,$ffffff
SceneProjectionX#=300
SceneProjectionY#=300
// Size of the vertex cube
ObjectSizeX=1000
ObjectSizeY=1000
ObjectSizeZ=1000
NumberOfVertex=5000
// Size of a single vertex (XYZ)
SrcVertSize =12
DestVertSize =20
// Array to hold the none rotated vertex
Dim Vertex#(2 ,(NumberOfVertex+1))
// Array to hold the rotated vertex
Dim RotatedVertex#(4,(NumberOfVertex+1))
// Randomly Init the none rotated vertex
For lp=0 To NumberOfVertex-1
Vertex#(0,lp)=RndRange#(-ObjectSizex,ObjectSizex) // X
Vertex#(1,lp)=RndRange#(-ObjectSizey,ObjectSizey) // Y
Vertex#(2,lp)=RndRange#(-ObjectSizez,ObjectSizez) // Z
Next
// Objects Base X/Y position
basex#=0
basey#=0
basez#=1000
// Precalc the Depth que shade array to shade the dots based upon the dots depth from the viewer
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
// Create a camera to draw the scene (with depth ordering)
CreateCamera 1
// Turn CLS off in the camera. This allows us to perform an Asycn CLS while the
// vertex are being rotataed
CameraCls 1,off
// --------------------------------------------------------------------------------
// Main loop ---------------------------------------------------------------------
// --------------------------------------------------------------------------------
Do
// Clear the screen to black
Cls rgb(0,0,0)
// Tell PB to capture draw commands to the Scene buffer
CaptureToScene
// Clear the scene at start of the frame, so there's no left over junk in there from a previous frame
ClsScene
// Get Address of Array source vertex
SrcAddress =GetArrayPtr(Vertex#())+PBArraystruct_Size
// Get address of rotated vertex (none projected)
DestAddress =GetArrayPtr(RotatedVertex#())+PBArraystruct_Size
// Rotated the vertex list
RotateVertexListXYZ SrcAddress,SrcVertSize,DestAddress,DestVertSize,baseX#,basey#,baseZ#,ax#,ay#,az#,NumberOfVertex
// Draw the list of camera. So they can drawn in order when the
t=Timer()
For vert=0 to NumberOfVertex-1
z#=RotatedVertex#(2,Vert)
If z#>10
Capturedepth z#
X#=400+(RotatedVertex#(0,Vert)*SceneProjectionx#)/z#
Y#=300+(RotatedVertex#(1,Vert)*SceneProjectiony#)/z#
DotC x#,y#,ShadeBufferBuffer(z#)
endif
next
t=Timer()-t
// draw the scene
DrawCamera 1
SetCursor 0,0
speed#=10
If UpKey() Then basez#=basez#-speed#
If DownKey() Then basez#=basez#+speed#
If basez#>3000 Then Basez#=3000
If basez#<-3000 Then Basez#=-3000
ax#=WrapAngle(ax#,1.01)
ay#=WrapAngle(ay#,0.42)
az#=WrapAngle(az#,0.9)
Print "Rotated Vertex Lists"
Print Str$(NumberOfVertex)+" Shaded Z buffered Vertex"
Print "draw time:"+Str$(t)
Print FPS()
Sync
Loop
[/pbcode]
Lerp Vertex Animation (Linear Interpolation between two vertex arrays)
This is variation of the demo above, but this one includes vertex animation via linear interpolation. So the demo generates two vertex arrays. Frame1 has the vertex positions randomly within a cubic space, and frame2 see the vertex randomly positioned on the surface of a sphere. The LERP function then lets us calculate transistion between the two frames. If your wondering this is how old school 3d animation works.
[pbcode]
; include the Vertex Objects expansion library
#include "VertexObjects"
openscreen 800,600,32,2
screenvsync on
SceneProjectionX#=300
SceneProjectionY#=300
// Size of the vertex cube
ObjectSizeX=500
ObjectSizeY=500
ObjectSizeZ=500
NumberOfVertex=5000
// Size of a single vertex (XYZ)
SrcVertSize =12
DestVertSize =20
// Array to hold the two frames of vertex data
Dim VertexFrame1#(2 ,(NumberOfVertex+1))
Dim VertexFrame2#(2 ,(NumberOfVertex+1))
// Array to hold the distance between each vertex in frane1 and frame2
Dim VertexDeltas#(2 ,(NumberOfVertex+1))
// array to hold the interpolation frame of vertex data (transistional state)
Dim LerpVertexFrame#(2 ,(NumberOfVertex+1))
// Array to hold the rotated vertex
Dim RotatedVertex#(4,(NumberOfVertex+1))
// Randomly Init the none rotated vertex (FRAME1 the random cube shaped vertex array)
For lp=0 To NumberOfVertex-1
VertexFrame1#(0,lp)=RndRange#(-ObjectSizex,ObjectSizex) // X
VertexFrame1#(1,lp)=RndRange#(-ObjectSizey,ObjectSizey) // Y
VertexFrame1#(2,lp)=RndRange#(-ObjectSizez,ObjectSizez) // Z
Next
// Randomly generate vertex on the sphere as frame 2
for t= 0 To NumberOfVertex
xd = Rndrange(-90,90)
x0 = (Cos(xd) * 10) * (Cos(t) * 10)
y0 = (Cos(xd) * 10) * (Sin(t) * 10)
z0 = Sin(xd) * 100
VertexFrame2#(0,t)=x0*6
VertexFrame2#(1,t)=y0*6
VertexFrame2#(2,t)=z0*6
Next
// Calc the difference between each vertex
CalcVertexDeltas(NumberOfVertex)
// Objects Base X/Y position
basex#=0
basey#=0
basez#=1000
// Precalc the Depth que shade array to shade the dots based upon the dots depth from the viewer
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
// Create a camera to draw the scene (with depth ordering)
CreateCamera 1
// Turn CLS off in the camera. This allows us to perform an Asyns CLS while the
// vertex are being rotated
CameraCls 1,off
// --------------------------------------------------------------------------------
// Main loop ---------------------------------------------------------------------
// --------------------------------------------------------------------------------
Do
// Clear the screen to black
Cls rgb(0,0,0)
// Tell PB to capture draw commands to the Scene buffer
CaptureToScene
// Clear the scene at start of the frame, so there's no left over junk in there from a previous frame
ClsScene
// Lerp between the Frame 1 and Frame
Lerp(NumberOfVertex,Scaler#)
if spacekey() or kev=0
Scaler# =cos(ScalerAngle#)*3
Scaler# =cliprange#(Scaler#,0,1)
ScalerAngle#=wrapangle(ScalerAngle#,0.4)
endif
// Get Address of Array source vertex
SrcAddress =GetArrayPtr(LerpVertexFrame#())+PBArraystruct_Size
// Get address of rotated vertex (none projected)
DestAddress =GetArrayPtr(RotatedVertex#())+PBArraystruct_Size
// Rotated the vertex list
RotateVertexListXYZ SrcAddress,SrcVertSize,DestAddress,DestVertSize,baseX#,basey#,baseZ#,ax#,ay#,az#,NumberOfVertex
// Draw the list to camera. So they can drawn in Z order when the camera is drawn
t=Timer()
For vert=0 to NumberOfVertex-1
z#=RotatedVertex#(2,Vert)
If z#>10
Capturedepth z# // Set this dots Z depth in the scene
X#=400+(RotatedVertex#(0,Vert)*SceneProjectionx#)/z#
Y#=300+(RotatedVertex#(1,Vert)*SceneProjectiony#)/z#
DotC x#,y#,ShadeBufferBuffer(z#)
endif
next
t=Timer()-t
// draw the scene
DrawCamera 1
// Set the text cursor to position 0,0 (top left) on the screem
SetCursor 0,0
// Check if the user is pressing the Arrow to move the scene in/out
speed#=10
If UpKey() Then basez#=basez#-speed#
If DownKey() Then basez#=basez#+speed#
If basez#>3000 Then Basez#=3000
If basez#<-3000 Then Basez#=-3000
// Bump objects rotation angles
ax#=WrapAngle(ax#,1.01)
ay#=WrapAngle(ay#,0.72)
az#=WrapAngle(az#,0.9)
// Display the vertex lists
Print "Rotated Vertex Lists"
Print Str$(NumberOfVertex)+" Shaded Z buffered Vertex"
Print "draw time:"+Str$(t)
Print FPS()
Sync
Loop
Psub CalcVertexDeltas(NumberOfVertex)
// Calc the diff between each vertex in the two frames
For lp=0 To NumberOfVertex-1
VertexDeltas#(0,lp)=VertexFrame2#(0,lp)-VertexFrame1#(0,lp)
VertexDeltas#(1,lp)=VertexFrame2#(1,lp)-VertexFrame1#(1,lp)
VertexDeltas#(2,lp)=VertexFrame2#(2,lp)-VertexFrame1#(2,lp)
next
EndPsub
Psub Lerp(NumberOfVertex,Scaler#)
// Linearly Interpolate the vertexs
For lp=0 To NumberOfVertex-1
LerpVertexFrame#(0,lp)=VertexFrame1#(0,lp)+(VertexDeltas#(0,lp)*Scaler#)
LerpVertexFrame#(1,lp)=VertexFrame1#(1,lp)+(VertexDeltas#(1,lp)*Scaler#)
LerpVertexFrame#(2,lp)=VertexFrame1#(2,lp)+(VertexDeltas#(2,lp)*Scaler#)
Next
EndPsub
[/pbcode]
Lerp Vertex Here's the version used to created the screen shots bellow.
requires
PlayBasic V1.64j8 or higher
[pbcode]
; include the Vertex Objects expansion library
#include "VertexObjects"
MakeBitmapFont 1,$ffffff
SceneProjectionX# =300
SceneProjectionY# =300
// Size of the vertex cube
ObjectSizeX =500
ObjectSizeY =500
ObjectSizeZ =500
NumberOfVertex =2500
// Size of a single vertex (XYZ)
SrcVertSize =12
DestVertSize =20
// Array to hold the none rotated vertex
Dim VertexFrame1#(2 ,(NumberOfVertex+1))
Dim VertexFrame2#(2 ,(NumberOfVertex+1))
Dim LerpVertexFrame#(2 ,(NumberOfVertex+1))
// Array to hold the rotated vertex
Dim RotatedVertex#(4,(NumberOfVertex+1))
// Randomly Init the none rotated vertex
For lp=0 To NumberOfVertex-1
VertexFrame1#(0,lp)=RndRange#(-ObjectSizex,ObjectSizex) // X
VertexFrame1#(1,lp)=RndRange#(-ObjectSizey,ObjectSizey) // Y
VertexFrame1#(2,lp)=RndRange#(-ObjectSizez,ObjectSizez) // Z
Next
for t= 0 To NumberOfVertex
xd = Rndrange(-90,90)
x0 = (Cos(xd) * 10) * (Cos(t) * 10)
y0 = (Cos(xd) * 10) * (Sin(t) * 10)
z0 = Sin(xd) * 100
VertexFrame2#(0,t)=x0*6
VertexFrame2#(1,t)=y0*6
VertexFrame2#(2,t)=z0*6
Next
// Objects Base X/Y position
basex#=0
basey#=0
basez#=1000
// Precalc the Depth que shade array to shade the dots based upon the dots depth from the viewer
Dim ShadeBufferBuffer(20000)
NumberOfVertexdepth#=3000
scaler#=100/NumberOfVertexdepth#
col=rndrgb()
;RGB(255,125,055)
For lp=0 To NumberOfVertexdepth#
ShadeBufferBuffer(lp)=RGBFade(col,(NumberOfVertexdepth#-lp)*scaler#)
Next
// Create a camera to draw the scene (with depth ordering)
CreateCamera 1
// Turn CLS off in the camera. This allows us to perform an Asycn CLS while the
// vertex are being rotataed
CameraCls 1,off
// --------------------------------------------------------------------------------
// Main loop ---------------------------------------------------------------------
// --------------------------------------------------------------------------------
Do
// Clear the screen to black
Cls rgb(0,0,0)
// Tell PB to capture draw commands to the Scene buffer
CaptureToScene
// Clear the scene at start of the frame, so there's no left over junk in there from a previous frame
ClsScene
// Lerp between the Frame 1 and Frame
Frame1Address =GetArrayPtr(VertexFrame1#())+PBArraystruct_Size
Frame2Address =GetArrayPtr(VertexFrame2#())+PBArraystruct_Size
DestAddress =GetArrayPtr(LerpVertexFrame#())+PBArraystruct_Size
LerpVertexList(Frame1Address,SrcVertSize,Frame2Address, SrcVertSize,DestAddress,SrcVertSize, NumberOfVertex, Scaler# )
if spacekey() or kev=0
Scaler#=(cos(ScalerAngle#)*5)
Scaler#=cliprange#(Scaler#,0,1)
ScalerAngle#=wrapangle(ScalerAngle#,0.1)
endif
// Get Address of Array source vertex
SrcAddress =GetArrayPtr(LerpVertexFrame#())+PBArraystruct_Size
// Get address of rotated vertex (none projected)
DestAddress =GetArrayPtr(RotatedVertex#())+PBArraystruct_Size
// Rotated the vertex list
RotateVertexListXYZ SrcAddress,SrcVertSize,DestAddress,DestVertSize,baseX#,basey#,baseZ#,ax#,ay#,az#,NumberOfVertex
// Draw the list of camera. So they can drawn in order when the
For vert=0 to NumberOfVertex-1
z#=RotatedVertex#(2,Vert)
If z#>10
Capturedepth z#
X#=400+(RotatedVertex#(0,Vert)*SceneProjectionx#)/z#
Y#=300+(RotatedVertex#(1,Vert)*SceneProjectiony#)/z#
CircleC x#,y#,16,true,ShadeBufferBuffer(z#)
endif
next
// draw the scene
DrawCamera 1
SetCursor 0,0
speed#=10
If UpKey() Then basez#=basez#-speed#
If DownKey() Then basez#=basez#+speed#
If basez#>3000 Then Basez#=3000
If basez#<-3000 Then Basez#=-3000
ax#=WrapAngle(ax#,1.01)
ay#=WrapAngle(ay#,0.42)
az#=WrapAngle(az#,0.9)
Print FPS()
Sync
Loop
[/pbcode]
Video (http://www.underwaredesign.com/forums/index.php?action=dlattach;topic=2610.0;attach=2584;image) - (http://www.underwaredesign.com/forums/index.php?action=dlattach;topic=2610.0;attach=2586;image)
and video
http://www.youtube.com/watch?v=FmNVJ9gDa8k&feature=channel_video_title