Page 1 of 1

Question on MeshVertexPosition()'s speed.

Posted: Sun Mar 24, 2013 3:12 am
by Samuel
I haven't done much work with the latest version of PB. So, I figured maybe someone could give me a heads up on this.

I know that you can now update your vertex position, but can it compete with giving your entity a skeleton?
I've seen the newest demos, like the flag one, and they look pretty fast, but how well would this work on a more complicated mesh?

I asking because I'm starting a little project and I would like to manipulate my meshes just using PB commands, but I'm just not sure how well
it can handle it. My meshes won't be to big. Most will just have a 100 or 200 points, but some may get near a 1000.

I can give more info if needed. Thanks!

Re: Question on MeshVertexPosition()'s speed.

Posted: Sun Mar 24, 2013 8:44 am
by applePi
Hi Samuel
about the skeleton i have'nt studied the subject yet, but about changing and updating the vertex position i have some ideas i get by stripping down the official example MeshManualParametrics.pb until i leave no math.
i have asked myself how to change MeshVertexPosition(x,y,z) if it adds index internaly ie there is no MeshVertexPosition(index,x,y,z) so to manipulate the position dynamically after mesh creation it is only available for MeshFace and MeshIndex functions and not for MeshVertexPosition. but there is UpdateMesh() to put the internal index again at the beginning to recalculate the positions again.
you said what about complex mesh ?? the good news is that we don't need to contineously calculating the positions inside main loop repeat ... untill exit
since the graphics are persistent and the mesh are there exit and alive in memory. so only we calculate the positions on demand. but of course i wish like you a MeshVertexPosition(index,x,y,z) version. the MeshIndex works like MeshFace but on arbitrary vertices it can weave connections between more than 3 vertices unlike meshface() as demonstrated in example MeshManual2.pb
the following example demonstrate how to update a vertice position continuously by pressing keys and without inserting the update process inside the main loop and this relieves the cpu from the continuous heavy tasks.
press the arrow keys to move one vertex ,press f3 for solid, f2 for wire.
i am still researching the subject.

Code: Select all

Global Epsilon2.f = 5
Global Epsilon1.f = 1

#Scale = 0.4

IncludeFile "Screen3DRequester.pb"

Define.f KeyX, KeyY

Declare CreatePoly()
Declare UpdatePoly()
Declare Poly()
Declare Poly3()

If InitEngine3D()
  
  Add3DArchive("/", #PB_3DArchive_FileSystem)
  Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Textures", #PB_3DArchive_FileSystem)
  Add3DArchive(#PB_Compiler_Home + "Examples/Sources\Data", #PB_3DArchive_FileSystem)
  
  InitSprite()
  InitKeyboard()
    
  If Screen3DRequester()
    
    CreatePoly()
    CreateMaterial(0, LoadTexture(0, "White.jpg"))
    DisableMaterialLighting(0, #True)
    MaterialShadingMode(0, #PB_Material_Wireframe )
    MaterialCullingMode(0, #PB_Material_NoCulling)
    
    SetMeshMaterial(0, MaterialID(0))
    
    node = CreateNode(#PB_Any)
    AttachNodeObject(node, MeshID(0))
    ScaleNode(node, #scale, #scale, #scale)
    
    CreateCamera(0, 0, 0, 100, 100)
    MoveCamera(0, 0, 0, 50, #PB_Absolute)
    CameraFOV(0, 40)
    CameraBackColor(0, $330000)
    CameraLookAt(0,0,0,0)
        
    CreateLight(0, RGB(255,255,255), 10, 60, -10)
    AmbientColor(RGB(90, 90, 90))
       
    Repeat
      Screen3DEvents()
            
      If ExamineKeyboard()
        
        If KeyboardReleased(#PB_Key_F2)
          MaterialShadingMode(0, #PB_Material_Wireframe)
        ElseIf KeyboardReleased(#PB_Key_F3)
          MaterialShadingMode(0, #PB_Material_Solid)
        EndIf
        
        If KeyboardPushed(#PB_Key_Right)
          Epsilon2 + 0.4 :Poly3()
        ElseIf KeyboardPushed(#PB_Key_Left) 
          Epsilon2 - 0.4 :Poly3()
        EndIf
        
        If KeyboardPushed(#PB_Key_Up)
          Epsilon1 + 0.4:Poly3()
        ElseIf KeyboardPushed(#PB_Key_Down)
          Epsilon1 - 0.4 :Poly3()
        
        EndIf
        
      EndIf
      rot.f+0.6
      ;UpdatePoly() ; no need here
      ;RotateNode(node,0,rot,0)
      RenderWorld()
      ;Screen3DStats()      
      FlipBuffers()
      
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
  EndIf
  
Else
  MessageRequester("Error", "The 3D Engine can't be initialized", 0)
EndIf

End

Procedure CreatePoly()
  CreateMesh(0, #PB_Mesh_TriangleList, #PB_Mesh_Dynamic)
  Poly()
  FinishMesh(#False)
EndProcedure

Procedure UpdatePoly()
  UpdateMesh(0, 0)
  Poly()
  FinishMesh(#False)
EndProcedure

Procedure Poly()
    MeshVertexPosition(-Epsilon2, Epsilon1, -20)
    MeshVertexColor(RGB(255, 255, 0))
    MeshVertexPosition(30, 30, -30)
    MeshVertexColor(RGB(255, 255, 0))
    MeshVertexPosition(15, -55, -15)
    MeshVertexColor(RGB(255, 255, 0))
        
    MeshVertexPosition(2, 1,0)
    MeshFace(0, 1, 2)
    MeshFace(1, 2, 3)
  
  EndProcedure
  
 
Procedure Poly3()
  UpdateMesh(0, 0)
  ;MeshIndex(2)
    MeshVertexPosition(-Epsilon2, Epsilon1, -20)
    MeshVertexColor(RGB(255, 0, 0))
   
    MeshVertexPosition(30, 30, -30)
    MeshVertexColor(RGB(255, 255, 0))
    
    MeshVertexPosition(15, -55, -15)
    MeshVertexColor(RGB(0, 255, 0))
        
    MeshVertexPosition(2, 1,0)
    MeshVertexColor(RGB(0, 255, 250))
    MeshFace(0, 1, 2)
    MeshFace(1, 2, 3)
  FinishMesh(#False)
EndProcedure

Re: Question on MeshVertexPosition()'s speed.

Posted: Sun Mar 24, 2013 9:05 am
by DarkDragon
Skeletons can be hardware accelerated through vertex shaders. You'll loose this advantage through manual vertex animation.

Re: Question on MeshVertexPosition()'s speed.

Posted: Sun Mar 24, 2013 4:03 pm
by applePi
another experiment, i will use a sphere made from circles which are made from points like this:
Image

Code: Select all

Enumeration
   #MESH
   #LIGHT
   #CAMERA_ONE
   #BUTTON
   #mainwin
 EndEnumeration

Quit.b = #False
rot.l=1 
xs.f = 0.3:ys.f = 0.3:zs.f = 0.3
x.f: y.f :z.f: x0.f: y0.f=1 :z0.f
rotx.f:roty.f=0.5:rotz.f :rotx0.f: roty0.f: rotz0.f
up.f = 1.8: depth.f=0

ExamineDesktops()
If OpenWindow(#mainwin, 0, 0, DesktopWidth(0), DesktopHeight(0), " sphere from circles ", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

;Initialize environment
InitEngine3D()
InitSprite()
OpenWindowedScreen(WindowID(#mainwin), 0, 0, DesktopWidth(0), DesktopHeight(0)-70, 0, 0, 0)

InitKeyboard()
SetFrameRate(60)

CreateLight(0,RGB(255,255,255),-100,40,30)
AmbientColor(RGB(100,100,100))

CreateCamera(#CAMERA_ONE, 0, 0, 400, 400)
MoveCamera(#CAMERA_ONE, 0, 4, 9)
CameraLookAt(#CAMERA_ONE, 0, 2, 0)

RotateCamera(#CAMERA_ONE, -15, 0, 0)
EndIf


;SkyDome("clouds.jpg", 100) ;for blue color background

;- Mesh 
CreateTexture(0,32,32)
  StartDrawing(TextureOutput(0))
    Box(0,0,32,32,RGB(255,255,255))
  StopDrawing()
CreateMaterial(0,TextureID(0))
DisableMaterialLighting(0, #True)
CreateMesh(1, #PB_Mesh_PointList, #PB_Mesh_Static)
DisableMaterialLighting(0, #True)
SetMeshMaterial(1, MaterialID(0))

      x.f: y.f :z.f : u.f: v.f: r.f
      majorOrbit.l = 100 : minorOrbit.l = 100
      majorStep.f   = 2 * #PI / majorOrbit
      minorStep.f   = 2 * #PI / minorOrbit
      i.l: j.l
 
      For i = 0 To 100
        u = i * majorStep
        For j = 0 To minorOrbit
          v = j * minorStep
          r = 4 * (1 - (Cos(u)/2))
        
          x = Cos(u)  * Cos(v)
          y = Sin(u) * Cos(v)
          z.f = Sin(v)
          MeshVertexPosition(x, y, z);
          MeshVertexColor(RGB(0,255,0))
          
        Next
      Next
      
    NormalizeMesh(1)
    FinishMesh(#True)
    CreateEntity(1, MeshID(1), MaterialID(0))  
    ScaleEntity(1,3, 3, 3)
  ;Main loop
  MoveEntity(1,0,up,depth,#PB_Absolute) 
  x = 180: y=0: z=0 : h.f
Repeat
  Event = WindowEvent()
  
    x + rotx
    y + roty
    z + rotz
    
   RotateEntity(1, x, y, z)
   
   RenderWorld()
   FlipBuffers()

  ExamineKeyboard()
  
   If KeyboardPushed(#PB_Key_Escape)
      Quit = #True
    EndIf
    
    
  Until Quit = #True Or Event = #PB_Event_CloseWindow
  
and then attach triangles between the points on every circle and the points on the next circle then make texturing, i have copied the procedure from my previous klein and mobius examples, so the texturing are not correct and flicker , but the purpose is to show that morphing speed are good even on the huge number of vertices (here it is 1500 ) and that depends on the heavy usage of sin,cos,tan etc functions. you can try other morphing equations.
the morphing are inside morph() procedure ,press W to toggle wire/solid
Image

Code: Select all

Enumeration
   #MESH
   #LIGHT
   #CAMERA_ONE
   #BUTTON
   #mainwin
 EndEnumeration
 Declare morph()
Global Epsilon2.f = 5
Global Epsilon1.f = 1
Global amplitude.f = 5
Global freq.f = 1.0
Quit.b = #False : wireFrame.b = 1
rot.l=1 :stopFlag = 1
xs.f = 0.3:ys.f = 0.3:zs.f = 0.3
x.f: y.f :z.f: x0.f: y0.f=1 :z0.f
rotx.f:roty.f=0.5:rotz.f :rotx0.f: roty0.f: rotz0.f
up.f = 1.8: depth.f=0

ExamineDesktops()
If OpenWindow(#mainwin, 0, 0, DesktopWidth(0), DesktopHeight(0), "PgUp PgD scale mesh..Arrows for rotation, space: stop/rotate,  QA far/near, key_pad R/L/U/D", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ButtonGadget(#BUTTON, 0, DesktopHeight(0)-60, 60, 30, "rotate/stop") 

;Initialize environment
InitEngine3D()
InitSprite()
OpenWindowedScreen(WindowID(#mainwin), 0, 0, DesktopWidth(0), DesktopHeight(0)-70, 0, 0, 0)
;WorldShadows(#PB_Shadow_Additive)

InitKeyboard()
SetFrameRate(60)

Add3DArchive("/", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Textures", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "Examples/Sources\Data", #PB_3DArchive_FileSystem)


CreateLight(0,RGB(255,255,255),-100,40,30)
AmbientColor(RGB(100,100,100))

CreateCamera(#CAMERA_ONE, 0, 0, 400, 400)
MoveCamera(#CAMERA_ONE, 0, 4, 9)
CameraLookAt(#CAMERA_ONE, 0, 2, 0)

RotateCamera(#CAMERA_ONE, -15, 0, 0)
EndIf

SetActiveGadget(#BUTTON)
;SkyDome("clouds.jpg", 100) ;for blue color background

;- Mesh 

CreateMaterial(0, LoadTexture(0, "terrain_texture.jpg"))
MaterialShadingMode(0, #PB_Material_Wireframe)
MaterialCullingMode(0, #PB_Material_NoCulling)

CreateMesh(1, #PB_Mesh_TriangleList, #PB_Mesh_Static)
DisableMaterialLighting(0, #True)
SetMeshMaterial(1, MaterialID(0))
node = CreateNode(#PB_Any)
AttachNodeObject(node, MeshID(1))
ScaleNode(node, 1, 1, 1)
      x.f: y.f :z.f : u.f: v.f: r.f
      majorOrbit.l = 50 : minorOrbit.l = 30
      majorStep.f   = 2 * #PI / majorOrbit
      minorStep.f   = 2 * #PI / minorOrbit
      i.l: j.l :txu.f : txv.f
 
      For i = 0 To majorOrbit
        v = i * majorStep
        For j = 0 To minorOrbit
          u = j * minorStep
          r = 4 * (1 - (Cos(u)/2))
          x = Cos(u)  * Cos(v)
          y = Sin(u) * Cos(v)
          z.f = Sin(v)
          
          MeshVertexPosition(x, y, z);
          MeshVertexTextureCoordinate(txu, txv)
          MeshVertexNormal(x, y, z)
          ;texture the whole sphere with one picture stretched
          txv = txv + 1/minorOrbit ; 
          
        Next
        txv = 0
        txu = txu + 1/majorOrbit 
      Next
      ;vv.l = MeshVertexCount(1,0) 
      t=0
      For i = 0 To majorOrbit-1
      For j = 0 To minorOrbit
          MeshFace(t,t+1,t + minorOrbit+1)
          MeshFace(t + minorOrbit+1,t + minorOrbit+2,t+1 )
          If i=majorOrbit-1 And j=minorOrbit-1 ;bypass the last triangle
            minorOrbit-1
          EndIf 
          t + 1   
          
     Next
     
   Next  
      
    NormalizeMesh(1)
    FinishMesh(#False)
   ;Debug MeshVertexCount(1,0) 
  ;Main loop
  MoveNode(node,0,up,depth,#PB_Absolute) 
  x = 180: y=0: z=0 : h.f
Repeat
  Event = WindowEvent()
  If Event = #PB_Event_Gadget
    Select EventGadget()
      Case #BUTTON
        If rot = 0
          rot = 1
          rotx= rotx0:roty=roty0:rotz=rotz0 ; restore rotation status
          stopFlag = 1
          
        Else
          rot = 0
          rotx0= rotx:roty0=roty:rotz0=rotz ;back up rotation status
          rotx=0:roty=0:rotz=0
          stopFlag = 0
          
        EndIf
                    
    EndSelect
  EndIf 
  If stopFlag=1
    x + rotx
    y + roty
    z + rotz
  EndIf
  morph()
   RotateNode(node, x, y, z)
   
   RenderWorld()
   FlipBuffers()

  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Up)  ; rotate left
    rotx=1:roty=0:rotz=0
    rotx0 = rotx: roty0 = roty :rotz0 = rotz
    x + rotx
    y + roty
    z + rotz
    stopFlag=0
    rot = 0
  ElseIf KeyboardPushed(#PB_Key_Down) ; rotate right
    rotx=-1:roty=0:rotz=0
    rotx0 = rotx: roty0 = roty :rotz0 = rotz
    x + rotx
    y + roty
    z + rotz
    stopFlag=0
    rot = 0
  ElseIf KeyboardPushed(#PB_Key_Right)   ; rotate up
    rotx=0:roty=1:rotz=0
    rotx0 = rotx: roty0 = roty :rotz0 = rotz
    x + rotx
    y + roty
    z + rotz
    stopFlag=0
    rot = 0
  ElseIf KeyboardPushed(#PB_Key_Left) ; rotate down
    rotx=0:roty=-1:rotz=0 
    rotx0 = rotx: roty0 = roty :rotz0 = rotz
    x + rotx
    y + roty
    z + rotz
    stopFlag=0
    rot = 0
  EndIf 
  
  If KeyboardPushed(#PB_Key_PageUp) ; scale up model
    xs.f = 1.1:ys.f = 1.1:zs.f = 1.1
    ScaleNode(node,xs,ys,zs)
    
  ElseIf KeyboardPushed(#PB_Key_PageDown) ; scale down model
    xs = 0.9:ys = 0.9:zs= 0.9
    ScaleNode(node,xs,ys,zs)
  ElseIf KeyboardReleased(#PB_Key_W) ; display wire frame for the material
      If wireFrame=0
      MaterialShadingMode(0, #PB_Material_Wireframe)
      wireFrame ! 1
         ElseIf wireFrame=1
           MaterialShadingMode(0, #PB_Material_Solid)
           wireFrame ! 1
      EndIf  
    
  EndIf
  If KeyboardPushed(#PB_Key_Pad8) ; up move
    up + 0.1
    MoveNode(node,h,up,depth,#PB_Absolute)
   ElseIf KeyboardPushed(#PB_Key_Pad2) ; down move
    up - 0.1
    MoveNode(node,h,up,depth,#PB_Absolute)
  ElseIf KeyboardPushed(#PB_Key_Pad6)
    h + 0.1
    MoveNode(node,h,up,depth,#PB_Absolute)
    ElseIf KeyboardPushed(#PB_Key_Pad4)
    h - 0.1
    MoveNode(node,h,up,depth,#PB_Absolute)
    
    ElseIf KeyboardPushed(#PB_Key_Q) ; forward move
    depth - 0.1
    MoveNode(node,h,up,depth,#PB_Absolute)
    ElseIf KeyboardPushed(#PB_Key_A) ; inward move
    depth + 0.1
    MoveNode(node,h,up,depth,#PB_Absolute)

  EndIf
   If KeyboardPushed(#PB_Key_Escape)
      Quit = #True
    EndIf
    
    
  Until Quit = #True Or Event = #PB_Event_CloseWindow
  Procedure morph()
    x.f: y.f :z.f : u.f: v.f: r.f
      majorOrbit.l = 50 : minorOrbit.l = 30
      majorStep.f   = 2 * #PI / majorOrbit
      minorStep.f   = 2 * #PI / minorOrbit
      i.l: j.l :txu.f : txv.f
  UpdateMesh(1, 0)
  ;warping a sphere
  
  ;dtime.f=ElapsedMilliseconds()/1200
  
      ;--------------------------------
    ;morphing equations:
    ;--------------------------------
    ;vx.f = amplitude * Sin(dtime*freq)
    ;vy.f = amplitude * Cos(dtime*freq)
    ;vz.f = amplitude * Sin(dtime*freq)
        
    For i = 0 To majorOrbit
        v = i * majorStep
        For j = 0 To minorOrbit
          u = j * minorStep
          ;r = 4 * (1 - (Cos(u)/2))
          dtime.f=ElapsedMilliseconds()/1200
  
      ;--------------------------------
    ;morphing equations:
    ;--------------------------------
          vx.f = amplitude * Sin(dtime*freq)
          vy.f = amplitude * Cos(dtime*freq)
          vz.f = amplitude * Sin(dtime*freq)
          
          x = Cos(u)  * Cos(v) *vx
          y = Sin(u) * Cos(v) *vy
          z.f = Sin(v) *vz
          
          MeshVertexPosition(x, y, z);
          MeshVertexTextureCoordinate(txu, txv)
          MeshVertexNormal(x, y, z)
          ;texture the whole sphere with one picture stretched
          txv = txv + 1/minorOrbit ; 
          
        Next
        txv = 0
        txu = txu + 1/majorOrbit 
      Next
      ;vv.l = MeshVertexCount(1,0) 
      t=0
      For i = 0 To majorOrbit-1
      For j = 0 To minorOrbit
          MeshFace(t,t+1,t + minorOrbit+1)
          MeshFace(t + minorOrbit+1,t + minorOrbit+2,t+1 )
          If i=majorOrbit-1 And j=minorOrbit-1 ;bypass the last triangle
            minorOrbit-1
          EndIf 
          t + 1   
          
     Next
     
   Next  
      
    NormalizeMesh(1)
    FinishMesh(#False)
    
  EndProcedure
  

Re: Question on MeshVertexPosition()'s speed.

Posted: Sun Mar 24, 2013 5:23 pm
by Samuel
Thank you DarkDragon for the link. I have very little experience when it comes to shaders. I suppose I should start working with them more often.

ApplePi, thanks for those nice examples. I think the best thing I can do is give manual vertex animation a try and hopefully
my calculations won't slow them down to much.
If nothing else I may be able to combine manual and skeletal animations together. That may be the better route, but I think I'll give your way a try first.

Thanks again to both of you!