PageRenderTime 78ms CodeModel.GetById 12ms RepoModel.GetById 2ms app.codeStats 0ms

/src/de/nulldesign/nd2d/materials/AMaterial.as

https://bitbucket.org/HopeSky/mars_nd2d
ActionScript | 267 lines | 171 code | 59 blank | 37 comment | 33 complexity | f591b52eca8fd36af3a053c2f665eee3 MD5 | raw file
  1. /*
  2. * ND2D - A Flash Molehill GPU accelerated 2D engine
  3. *
  4. * Author: Lars Gerckens
  5. * Copyright (c) nulldesign 2011
  6. * Repository URL: http://github.com/nulldesign/nd2d
  7. * Getting started: https://github.com/nulldesign/nd2d/wiki
  8. *
  9. *
  10. * Licence Agreement
  11. *
  12. * Permission is hereby granted, free of charge, to any person obtaining a copy
  13. * of this software and associated documentation files (the "Software"), to deal
  14. * in the Software without restriction, including without limitation the rights
  15. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  16. * copies of the Software, and to permit persons to whom the Software is
  17. * furnished to do so, subject to the following conditions:
  18. *
  19. * The above copyright notice and this permission notice shall be included in
  20. * all copies or substantial portions of the Software.
  21. *
  22. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  23. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  24. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  25. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  26. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  27. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  28. * THE SOFTWARE.
  29. */
  30. package de.nulldesign.nd2d.materials {
  31. import de.nulldesign.nd2d.geom.Face;
  32. import de.nulldesign.nd2d.geom.UV;
  33. import de.nulldesign.nd2d.geom.Vertex;
  34. import de.nulldesign.nd2d.materials.shader.Shader2D;
  35. import de.nulldesign.nd2d.utils.NodeBlendMode;
  36. import flash.display.Shader;
  37. import flash.display3D.Context3D;
  38. import flash.display3D.Context3DVertexBufferFormat;
  39. import flash.display3D.IndexBuffer3D;
  40. import flash.display3D.VertexBuffer3D;
  41. import flash.geom.Matrix3D;
  42. import flash.utils.Dictionary;
  43. public class AMaterial {
  44. // cameras view projectionmatrix
  45. public var viewProjectionMatrix:Matrix3D;
  46. // models modelmatrix
  47. public var modelMatrix:Matrix3D;
  48. public var clipSpaceMatrix:Matrix3D = new Matrix3D();
  49. public var numTris:int = 0;
  50. public var drawCalls:int = 0;
  51. public var blendMode:NodeBlendMode = BlendModePresets.NORMAL_PREMULTIPLIED_ALPHA;
  52. public var needUploadVertexBuffer:Boolean = false;
  53. protected var indexBuffer:IndexBuffer3D;
  54. protected var vertexBuffer:VertexBuffer3D;
  55. protected var mIndexBuffer:Vector.<uint>;
  56. protected var mVertexBuffer:Vector.<Number>;
  57. protected var shaderData:Shader2D;
  58. protected var programConstVector:Vector.<Number> = new Vector.<Number>(4);
  59. public var nodeTinted:Boolean = false;
  60. protected var previousTintedState:Boolean = false;
  61. public static const VERTEX_POSITION:String = "PB3D_POSITION";
  62. public static const VERTEX_UV:String = "PB3D_UV";
  63. public static const VERTEX_COLOR:String = "PB3D_COLOR";
  64. public function AMaterial() {
  65. }
  66. protected function generateBufferData(context:Context3D, faceList:Vector.<Face>):void {
  67. if(vertexBuffer) {
  68. return;
  69. }
  70. initProgram(context);
  71. var i:int;
  72. const numFaces:int = faceList.length;
  73. var numIndices:int;
  74. mIndexBuffer = new Vector.<uint>();
  75. mVertexBuffer = new Vector.<Number>();
  76. var duplicateCheck:Dictionary = new Dictionary();
  77. var tmpUID:String;
  78. var indexBufferIdx:uint = 0;
  79. var face:Face;
  80. // generate index + vertexbuffer
  81. // integrated check if the vertex / uv combination is already in the buffer and skip these vertices
  82. for(i = 0; i < numFaces; i++) {
  83. face = faceList[i];
  84. tmpUID = face.v1.uid + "." + face.uv1.uid;
  85. if(duplicateCheck[tmpUID] == undefined) {
  86. addVertex(context, mVertexBuffer, face.v1, face.uv1, face);
  87. duplicateCheck[tmpUID] = indexBufferIdx;
  88. mIndexBuffer.push(indexBufferIdx);
  89. face.v1.bufferIdx = indexBufferIdx;
  90. ++indexBufferIdx;
  91. } else {
  92. mIndexBuffer.push(duplicateCheck[tmpUID]);
  93. }
  94. tmpUID = face.v2.uid + "." + face.uv2.uid;
  95. if(duplicateCheck[tmpUID] == undefined) {
  96. addVertex(context, mVertexBuffer, face.v2, face.uv2, face);
  97. duplicateCheck[tmpUID] = indexBufferIdx;
  98. mIndexBuffer.push(indexBufferIdx);
  99. face.v2.bufferIdx = indexBufferIdx;
  100. ++indexBufferIdx;
  101. } else {
  102. mIndexBuffer.push(duplicateCheck[tmpUID]);
  103. }
  104. tmpUID = face.v3.uid + "." + face.uv3.uid;
  105. if(duplicateCheck[tmpUID] == undefined) {
  106. addVertex(context, mVertexBuffer, face.v3, face.uv3, face);
  107. duplicateCheck[tmpUID] = indexBufferIdx;
  108. mIndexBuffer.push(indexBufferIdx);
  109. face.v3.bufferIdx = indexBufferIdx;
  110. ++indexBufferIdx;
  111. } else {
  112. mIndexBuffer.push(duplicateCheck[tmpUID]);
  113. }
  114. }
  115. duplicateCheck = null;
  116. numIndices = mVertexBuffer.length / shaderData.numFloatsPerVertex;
  117. // GENERATE BUFFERS
  118. vertexBuffer = context.createVertexBuffer(numIndices, shaderData.numFloatsPerVertex);
  119. vertexBuffer.uploadFromVector(mVertexBuffer, 0, numIndices);
  120. if(!indexBuffer) {
  121. const mIndexBuffer_length:int = mIndexBuffer.length;
  122. indexBuffer = context.createIndexBuffer(mIndexBuffer_length);
  123. indexBuffer.uploadFromVector(mIndexBuffer, 0, mIndexBuffer_length);
  124. numTris = int(mIndexBuffer_length / 3);
  125. }
  126. }
  127. protected function prepareForRender(context:Context3D):void {
  128. if(previousTintedState != nodeTinted) {
  129. shaderData = null;
  130. initProgram(context);
  131. previousTintedState = nodeTinted;
  132. }
  133. context.setProgram(shaderData.shader);
  134. context.setBlendFactors(blendMode.src, blendMode.dst);
  135. if(needUploadVertexBuffer) {
  136. needUploadVertexBuffer = false;
  137. vertexBuffer.uploadFromVector(mVertexBuffer, 0, mVertexBuffer.length / shaderData.numFloatsPerVertex);
  138. }
  139. }
  140. public function handleDeviceLoss():void {
  141. indexBuffer = null;
  142. vertexBuffer = null;
  143. mIndexBuffer = null;
  144. mVertexBuffer = null;
  145. shaderData = null;
  146. needUploadVertexBuffer = true;
  147. }
  148. public function render(context:Context3D, faceList:Vector.<Face>, startTri:uint, numTris:uint):void {
  149. generateBufferData(context, faceList);
  150. prepareForRender(context);
  151. context.drawTriangles(indexBuffer, startTri * 3, numTris);
  152. clearAfterRender(context);
  153. }
  154. protected function clearAfterRender(context:Context3D):void {
  155. // implement in concrete material
  156. throw new Error("You have to implement clearAfterRender for your material");
  157. }
  158. protected function initProgram(context:Context3D):void {
  159. // implement in concrete material
  160. throw new Error("You have to implement initProgram for your material");
  161. }
  162. protected function refreshClipspaceMatrix():Matrix3D {
  163. clipSpaceMatrix.identity();
  164. clipSpaceMatrix.append(modelMatrix);
  165. clipSpaceMatrix.append(viewProjectionMatrix);
  166. return clipSpaceMatrix;
  167. }
  168. protected function addVertex(context:Context3D, buffer:Vector.<Number>, v:Vertex, uv:UV, face:Face):void {
  169. // implement in concrete material
  170. throw new Error("You have to implement addVertex for your material");
  171. }
  172. protected function fillBuffer(buffer:Vector.<Number>, v:Vertex, uv:UV, face:Face, semanticsID:String, floatFormat:int):void {
  173. if(semanticsID == VERTEX_POSITION) {
  174. buffer.push(v.x, v.y);
  175. if(floatFormat >= 3)
  176. buffer.push(v.z);
  177. if(floatFormat == 4)
  178. buffer.push(v.w);
  179. }
  180. if(semanticsID == VERTEX_UV) {
  181. buffer.push(uv.u, uv.v);
  182. if(floatFormat == 3)
  183. buffer.push(0.0);
  184. if(floatFormat == 4)
  185. buffer.push(0.0, 0.0);
  186. }
  187. if(semanticsID == VERTEX_COLOR) {
  188. buffer.push(v.r, v.g, v.b);
  189. if(floatFormat == 4)
  190. buffer.push(v.a);
  191. }
  192. }
  193. public function dispose():void
  194. {
  195. if(indexBuffer) {
  196. indexBuffer.dispose();
  197. indexBuffer = null;
  198. }
  199. if(vertexBuffer) {
  200. vertexBuffer.dispose();
  201. vertexBuffer = null;
  202. }
  203. if(shaderData) {
  204. shaderData = null;
  205. }
  206. }
  207. }
  208. }