All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scaffold.libs_as.starling.display.MeshBatch.as Maven / Gradle / Ivy

// =================================================================================================
//
//	Starling Framework
//	Copyright 2011-2015 Gamua. All Rights Reserved.
//
//	This program is free software. You can redistribute and/or modify it
//	in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================

package starling.display
{
    import flash.geom.Matrix;

    import starling.rendering.IndexData;
    import starling.rendering.MeshEffect;
    import starling.rendering.MeshStyle;
    import starling.rendering.Painter;
    import starling.rendering.VertexData;
    import starling.utils.MeshSubset;

    /** Combines a number of meshes to one display object and renders them efficiently.
     *
     *  

The most basic tangible (non-container) display object in Starling is the Mesh. * However, a mesh typically does not render itself; it just holds the data describing its * geometry. Rendering is orchestrated by the "MeshBatch" class. As its name suggests, it * acts as a batch for an arbitrary number of Mesh instances; add meshes to a batch and they * are all rendered together, in one draw call.

* *

You can only batch meshes that share similar properties, e.g. they need to have the * same texture and the same blend mode. The first object you add to a batch will decide * this state; call canAddMesh to find out if a new mesh shares that state. * To reset the current state, you can call clear; this will also remove all * geometry that has been added thus far.

* *

Starling will use MeshBatch instances (or compatible objects) for all rendering. * However, you can also instantiate MeshBatch instances yourself and add them to the display * tree. That makes sense for an object containing a large number of meshes; that way, that * object can be created once and then rendered very efficiently, without having to copy its * vertices and indices between buffers and GPU memory.

* * @see Mesh * @see Sprite */ public class MeshBatch extends Mesh { /** The maximum number of vertices that fit into one MeshBatch. */ public static const MAX_NUM_VERTICES:int = 65535; private var _effect:MeshEffect; private var _batchable:Boolean; private var _vertexSyncRequired:Boolean; private var _indexSyncRequired:Boolean; // helper object private static var sFullMeshSubset:MeshSubset = new MeshSubset(); /** Creates a new, empty MeshBatch instance. */ public function MeshBatch() { var vertexData:VertexData = new VertexData(); var indexData:IndexData = new IndexData(); super(vertexData, indexData); _batchable = true; } // display object overrides /** @inheritDoc */ override public function dispose():void { if (_effect) _effect.dispose(); super.dispose(); } /** @inheritDoc */ override protected function get supportsRenderCache():Boolean { return _batchable && super.supportsRenderCache; } private function setVertexAndIndexDataChanged():void { _vertexSyncRequired = _indexSyncRequired = true; } private function syncVertexBuffer():void { _effect.uploadVertexData(_vertexData); _vertexSyncRequired = false; } private function syncIndexBuffer():void { _effect.uploadIndexData(_indexData); _indexSyncRequired = false; } /** Removes all geometry. */ public function clear():void { _vertexData.numVertices = 0; _indexData.numIndices = 0; _vertexSyncRequired = true; _indexSyncRequired = true; } /** Adds a mesh to the batch by appending its vertices and indices. * * @param mesh the mesh to add to the batch. * @param matrix transform all vertex positions with a certain matrix. If this * parameter is omitted, mesh.transformationMatrix * will be used instead (except if the last parameter is enabled). * @param alpha will be multiplied with each vertex' alpha value. * @param subset the subset of the mesh you want to add, or null for * the complete mesh. * @param ignoreTransformations when enabled, the mesh's vertices will be added * without transforming them in any way (no matter the value of the * matrix parameter). */ public function addMesh(mesh:Mesh, matrix:Matrix=null, alpha:Number=1.0, subset:MeshSubset=null, ignoreTransformations:Boolean=false):void { if (ignoreTransformations) matrix = null; else if (matrix == null) matrix = mesh.transformationMatrix; if (subset == null) subset = sFullMeshSubset; var targetVertexID:int = _vertexData.numVertices; var targetIndexID:int = _indexData.numIndices; var meshStyle:MeshStyle = mesh._style; if (targetVertexID == 0) setupFor(mesh); meshStyle.copyVertexDataTo(_vertexData, targetVertexID, matrix, subset.vertexID, subset.numVertices); meshStyle.copyIndexDataTo(_indexData, targetIndexID, targetVertexID - subset.vertexID, subset.indexID, subset.numIndices); if (alpha != 1.0) _vertexData.scaleAlphas("color", alpha, targetVertexID, subset.numVertices); if (_batchable) setRequiresRedraw(); _indexSyncRequired = _vertexSyncRequired = true; } /** Adds a mesh to the batch by copying its vertices and indices to the given positions. * Beware that you need to check for yourself if those positions make sense; for example, * you need to make sure that they are aligned within the 3-indices groups making up * the mesh's triangles. * *

It's easiest to only add objects with an identical setup, e.g. only quads. * For the latter, indices are aligned in groups of 6 (one quad requires six indices), * and the vertices in groups of 4 (one vertex for every corner).

*/ public function addMeshAt(mesh:Mesh, indexID:int, vertexID:int):void { var numIndices:int = mesh.numIndices; var numVertices:int = mesh.numVertices; var matrix:Matrix = mesh.transformationMatrix; var meshStyle:MeshStyle = mesh._style; if (_vertexData.numVertices == 0) setupFor(mesh); meshStyle.copyVertexDataTo(_vertexData, vertexID, matrix, 0, numVertices); meshStyle.copyIndexDataTo(_indexData, indexID, vertexID, 0, numIndices); if (alpha != 1.0) _vertexData.scaleAlphas("color", alpha, vertexID, numVertices); if (_batchable) setRequiresRedraw(); _indexSyncRequired = _vertexSyncRequired = true; } private function setupFor(mesh:Mesh):void { var meshStyle:MeshStyle = mesh._style; var meshStyleType:Class = meshStyle.type; if (_style.type != meshStyleType) setStyle(new meshStyleType() as MeshStyle, false); _style.copyFrom(meshStyle); } /** Indicates if the given mesh instance fits to the current state of the batch. * Will always return true for the first added mesh; later calls * will check if the style matches and if the maximum number of vertices is not * exceeded. * * @param mesh the mesh to add to the batch. * @param numVertices if -1, mesh.numVertices will be used */ public function canAddMesh(mesh:Mesh, numVertices:int=-1):Boolean { var currentNumVertices:int = _vertexData.numVertices; if (currentNumVertices == 0) return true; if (numVertices < 0) numVertices = mesh.numVertices; if (numVertices == 0) return true; if (numVertices + currentNumVertices > MAX_NUM_VERTICES) return false; return _style.canBatchWith(mesh._style); } /** If the batchable property is enabled, this method will add the batch * to the painter's current batch. Otherwise, this will actually do the drawing. */ override public function render(painter:Painter):void { if (_vertexData.numVertices == 0) { // nothing to do =) } else if (_batchable) { painter.batchMesh(this); } else { painter.finishMeshBatch(); painter.drawCount += 1; painter.prepareToDraw(); if (_vertexSyncRequired) syncVertexBuffer(); if (_indexSyncRequired) syncIndexBuffer(); _style.updateEffect(_effect, painter.state); _effect.render(0, _indexData.numTriangles); } } /** @inheritDoc */ override public function setStyle(meshStyle:MeshStyle=null, mergeWithPredecessor:Boolean=true):void { super.setStyle(meshStyle, mergeWithPredecessor); if (_effect) _effect.dispose(); _effect = style.createEffect(); _effect.onRestore = setVertexAndIndexDataChanged; } /** The total number of vertices in the mesh. If you change this to a smaller value, * the surplus will be deleted. Make sure that no indices reference those deleted * vertices! */ public function set numVertices(value:int):void { _vertexData.numVertices = value; _vertexSyncRequired = true; } /** The total number of indices in the mesh. If you change this to a smaller value, * the surplus will be deleted. Always make sure that the number of indices * is a multiple of three! */ public function set numIndices(value:int):void { _indexData.numIndices = value; _indexSyncRequired = true; } /** Indicates if this object will be added to the painter's batch on rendering, * or if it will draw itself right away. * *

Only batchable meshes can profit from the render cache; but batching large meshes * may take up a lot of CPU time. Thus, for meshes that contain a large number of vertices * or are constantly changing (i.e. can't use the render cache anyway), it makes * sense to deactivate batching.

* * @default true */ public function get batchable():Boolean { return _batchable; } public function set batchable(value:Boolean):void { if (value != _batchable) // self-rendering must disrupt the render cache { _batchable = value; updateSupportsRenderCache(); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy