vertexbuffer.monkey2 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. Namespace mojo.graphics
  2. #rem monkeydoc @hidden
  3. #end
  4. Class VertexFormat
  5. Method New()
  6. End
  7. Property Pitch:Int() Virtual
  8. Return 0
  9. End
  10. Method UpdateGLAttribs() Virtual
  11. End
  12. End
  13. #rem
  14. Vertex buffers can 'grow' stack-like.
  15. Use Resize or AddVertices to grow a vertex buffer.
  16. #end
  17. Class VertexBuffer Extends Resource
  18. Method New( format:VertexFormat,length:Int=0 )
  19. _format=format
  20. _length=length
  21. _pitch=_format.Pitch
  22. _managed=New UByte[_length*_pitch]
  23. _dirtyMin=_length
  24. _dirtyMax=0
  25. End
  26. Method New( vertices:Vertex3f[] )
  27. Self.New( Vertex3f.Format,vertices.Length )
  28. SetVertices( vertices.Data,0,vertices.Length )
  29. End
  30. Property Format:VertexFormat()
  31. Return _format
  32. End
  33. Property Length:Int()
  34. Return _length
  35. End
  36. Property Pitch:Int()
  37. Return _pitch
  38. End
  39. #rem monkeydoc Resizes the vertex buffer.
  40. #end
  41. Method Resize( length:Int )
  42. If length=_length Return
  43. Local managed:=New UByte[length*_pitch]
  44. Local n:=Min( length,_length )
  45. If n libc.memcpy( managed.Data,_managed.Data,n*_pitch )
  46. _managed=managed
  47. _length=length
  48. If _glSeq=glGraphicsSeq glDeleteBuffers( 1,Varptr _glBuffer )
  49. _glSeq=0
  50. End
  51. #rem monkeydoc Sets a range of vertices.
  52. #end
  53. Method SetVertices( vertices:Void Ptr,first:Int,count:Int )
  54. DebugAssert( Not _locked,"VertexBuffer is locked" )
  55. DebugAssert( first>=0 And count>=0 And first<=_length And first+count<=_length,"Invalid vertex range" )
  56. libc.memcpy( _managed.Data+first*_pitch,vertices,count*_pitch )
  57. Invalidate( first,count )
  58. End
  59. #rem monkeydoc Locks vertices.
  60. Make sure to invalidate any vertices you modify by using [[Invalidate]].
  61. #end
  62. Method Lock:UByte ptr()
  63. DebugAssert( Not _locked,"VertexBuffer is already locked" )
  64. _locked=_managed.Data
  65. Return _locked
  66. End
  67. #rem onkeydoc Invalidates vertices.
  68. You should use this method to invalidate any vertices you have modified by writing to a locked vertex buffer.
  69. #End
  70. Method Invalidate( first:Int,count:Int )
  71. ' DebugAssert( _locked,"Vertex buffer is not locked" )
  72. DebugAssert( first>=0 And count>=0 And first<=_length And first+count<=_length,"Invalid vertex range" )
  73. _dirtyMin=Min( _dirtyMin,first )
  74. _dirtyMax=Max( _dirtyMax,first+count )
  75. End
  76. Method Invalidate()
  77. Invalidate( 0,_length )
  78. End
  79. #rem monkeydoc Unlocks vertices.
  80. #end
  81. Method Unlock:Void()
  82. DebugAssert( _locked,"Vertex buffer is not locked" )
  83. _locked=Null
  84. End
  85. Protected
  86. Method OnDiscard() Override
  87. If _glSeq=glGraphicsSeq glDeleteBuffers( 1,Varptr _glBuffer )
  88. _glSeq=-1
  89. End
  90. Method OnFinalize() Override
  91. If _glSeq=glGraphicsSeq glDeleteBuffers( 1,Varptr _glBuffer )
  92. End
  93. Internal
  94. Method Bind()
  95. DebugAssert( Not _locked,"VertexBuffer.Bind() failed, VertexBuffer is locked" )
  96. If _glSeq<>glGraphicsSeq
  97. glGenBuffers( 1,Varptr _glBuffer )
  98. glBindBuffer( GL_ARRAY_BUFFER,_glBuffer )
  99. glBufferData( GL_ARRAY_BUFFER,_length*_pitch,_managed.Data,GL_DYNAMIC_DRAW )
  100. _dirtyMin=_length
  101. _dirtyMax=0
  102. _glSeq=glGraphicsSeq
  103. Else
  104. glBindBuffer( GL_ARRAY_BUFFER,_glBuffer )
  105. Endif
  106. If _format _format.UpdateGLAttribs()
  107. End
  108. Method Validate()
  109. If _dirtyMax>_dirtyMin
  110. glBufferSubData( GL_ARRAY_BUFFER,_dirtyMin*_pitch,(_dirtyMax-_dirtyMin)*_pitch,_managed.Data )
  111. _dirtyMin=_length
  112. _dirtyMax=0
  113. Endif
  114. End
  115. Private
  116. Field _format:VertexFormat
  117. Field _length:Int
  118. Field _pitch:Int
  119. Field _managed:UByte[]
  120. Field _dirtyMin:Int
  121. Field _dirtyMax:Int
  122. Field _locked:UByte Ptr
  123. Field _glSeq:Int
  124. Field _glBuffer:GLuint
  125. End