diff --git a/away3d/core/base/CompactSubGeometry.hx b/away3d/core/base/CompactSubGeometry.hx index 9bff9af2..c30c4e32 100644 --- a/away3d/core/base/CompactSubGeometry.hx +++ b/away3d/core/base/CompactSubGeometry.hx @@ -1,6 +1,6 @@ package away3d.core.base; - +import away3d.core.base.data.VertexDefinition; import away3d.core.managers.Stage3DProxy; import openfl.display3D.Context3D; @@ -12,10 +12,12 @@ import openfl.Vector; class CompactSubGeometry extends SubGeometryBase implements ISubGeometry { + public var definition(default, null):VertexDefinition; + public var numVertices(get, never):Int; public var secondaryUVStride(get, never):Int; public var secondaryUVOffset(get, never):Int; - + private var _vertexDataInvalid:Vector = new Vector(8, true); private var _vertexBuffer:Vector = new Vector(8); private var _bufferContext:Vector = new Vector(8); @@ -26,19 +28,20 @@ class CompactSubGeometry extends SubGeometryBase implements ISubGeometry private var _activeDataInvalid:Bool; private var _isolatedVertexPositionData:Vector; private var _isolatedVertexPositionDataDirty:Bool; - - public function new() + + public function new(?definition:VertexDefinition) { super(); _autoDeriveVertexNormals = false; _autoDeriveVertexTangents = false; + this.definition = definition != null ? definition : VertexDefinition.defaultVertexDefinition; } - + private function get_numVertices():Int { return _numVertices; } - + /** * Updates the vertex data. All vertex properties are contained in a single Vector, and the order is as follows: * 0 - 2: vertex position X, Y, Z @@ -53,123 +56,90 @@ class CompactSubGeometry extends SubGeometryBase implements ISubGeometry _vertexNormalsDirty = true; if (_autoDeriveVertexTangents) _vertexTangentsDirty = true; - + _faceNormalsDirty = true; _faceTangentsDirty = true; _isolatedVertexPositionDataDirty = true; - + _vertexData = data; - var numVertices:Int = Std.int(_vertexData.length/13); + var numVertices:Int = Std.int(_vertexData.length/definition.length); if (numVertices != _numVertices) disposeVertexBuffers(_vertexBuffer); _numVertices = numVertices; - + if (_numVertices == 0) throw new Error("Bad data: geometry can't have zero triangles"); - + invalidateBuffers(_vertexDataInvalid); - + invalidateBounds(); } - + public function activateVertexBuffer(index:Int, stage3DProxy:Stage3DProxy):Void { - var contextIndex:Int = stage3DProxy._stage3DIndex; - var context:Context3D = stage3DProxy._context3D; - - if (contextIndex != _contextIndex) - updateActiveBuffer(contextIndex); - - if (_activeBuffer == null || _activeContext != context) - createBuffer(contextIndex, context, stage3DProxy); - if (_activeDataInvalid) - uploadData(contextIndex); - - context.setVertexBufferAt(index, _activeBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); + activateSpecificVertexBuffer("position", index, stage3DProxy); } - + public function activateUVBuffer(index:Int, stage3DProxy:Stage3DProxy):Void { - var contextIndex:Int = stage3DProxy._stage3DIndex; - var context:Context3D = stage3DProxy._context3D; - if (_uvsDirty && _autoGenerateUVs) { _vertexData = updateDummyUVs(_vertexData); invalidateBuffers(_vertexDataInvalid); } - - if (contextIndex != _contextIndex) - updateActiveBuffer(contextIndex); - - if (_activeBuffer == null || _activeContext != context) - createBuffer(contextIndex, context, stage3DProxy); - if (_activeDataInvalid) - uploadData(contextIndex); - - context.setVertexBufferAt(index, _activeBuffer, 9, Context3DVertexBufferFormat.FLOAT_2); + + activateSpecificVertexBuffer("UV", index, stage3DProxy); } - + public function activateSecondaryUVBuffer(index:Int, stage3DProxy:Stage3DProxy):Void { - var contextIndex:Int = stage3DProxy._stage3DIndex; - var context:Context3D = stage3DProxy._context3D; - - if (contextIndex != _contextIndex) - updateActiveBuffer(contextIndex); - - if (_activeBuffer == null || _activeContext != context) - createBuffer(contextIndex, context, stage3DProxy); - if (_activeDataInvalid) - uploadData(contextIndex); - - context.setVertexBufferAt(index, _activeBuffer, 11, Context3DVertexBufferFormat.FLOAT_2); + activateSpecificVertexBuffer("secondaryUV", index, stage3DProxy); } - + private function uploadData(contextIndex:Int):Void { _activeBuffer.uploadFromVector(_vertexData, 0, _numVertices); _vertexDataInvalid[contextIndex] = _activeDataInvalid = false; } - + public function activateVertexNormalBuffer(index:Int, stage3DProxy:Stage3DProxy):Void { - var contextIndex:Int = stage3DProxy._stage3DIndex; - var context:Context3D = stage3DProxy._context3D; - - if (contextIndex != _contextIndex) - updateActiveBuffer(contextIndex); - - if (_activeBuffer == null || _activeContext != context) - createBuffer(contextIndex, context, stage3DProxy); - if (_activeDataInvalid) - uploadData(contextIndex); - - context.setVertexBufferAt(index, _activeBuffer, 3, Context3DVertexBufferFormat.FLOAT_3); + activateSpecificVertexBuffer("normal", index, stage3DProxy); } - + public function activateVertexTangentBuffer(index:Int, stage3DProxy:Stage3DProxy):Void { + activateSpecificVertexBuffer("tangent", index, stage3DProxy); + } + + public function activateSpecificVertexBuffer(attributeName:String, index:Int, stage3DProxy:Stage3DProxy):Void + { + var attribute:AttributeDefinition = definition.get(attributeName); + if (attribute == null) + { + return; + } + var contextIndex:Int = stage3DProxy._stage3DIndex; var context:Context3D = stage3DProxy._context3D; - + if (contextIndex != _contextIndex) updateActiveBuffer(contextIndex); - + if (_activeBuffer == null || _activeContext != context) createBuffer(contextIndex, context, stage3DProxy); if (_activeDataInvalid) uploadData(contextIndex); - - context.setVertexBufferAt(index, _activeBuffer, 6, Context3DVertexBufferFormat.FLOAT_3); + + context.setVertexBufferAt(index, _activeBuffer, attribute.offset, attribute.vertexBufferFormat); } - + private function createBuffer(contextIndex:Int, context:Context3D, stage3DProxy:Stage3DProxy):Void { - _vertexBuffer[contextIndex] = _activeBuffer = stage3DProxy.createVertexBuffer(_numVertices, 13); + _vertexBuffer[contextIndex] = _activeBuffer = stage3DProxy.createVertexBuffer(_numVertices, definition.length); _bufferContext[contextIndex] = _activeContext = context; _vertexDataInvalid[contextIndex] = _activeDataInvalid = true; } - + private function updateActiveBuffer(contextIndex:Int):Void { _contextIndex = contextIndex; @@ -177,7 +147,7 @@ class CompactSubGeometry extends SubGeometryBase implements ISubGeometry _activeBuffer = _vertexBuffer[contextIndex]; _activeContext = _bufferContext[contextIndex]; } - + override private function get_vertexData():Vector { if (_autoDeriveVertexNormals && _vertexNormalsDirty) @@ -188,13 +158,13 @@ class CompactSubGeometry extends SubGeometryBase implements ISubGeometry _vertexData = updateDummyUVs(_vertexData); return _vertexData; } - + override private function updateVertexNormals(target:Vector):Vector { invalidateBuffers(_vertexDataInvalid); return super.updateVertexNormals(target); } - + override private function updateVertexTangents(target:Vector):Vector { if (_vertexNormalsDirty) @@ -202,22 +172,22 @@ class CompactSubGeometry extends SubGeometryBase implements ISubGeometry invalidateBuffers(_vertexDataInvalid); return super.updateVertexTangents(target); } - + override private function get_vertexNormalData():Vector { if (_autoDeriveVertexNormals && _vertexNormalsDirty) _vertexData = updateVertexNormals(_vertexData); - + return _vertexData; } - + override private function get_vertexTangentData():Vector { if (_autoDeriveVertexTangents && _vertexTangentsDirty) _vertexData = updateVertexTangents(_vertexData); return _vertexData; } - + override private function get_UVData():Vector { if (_uvsDirty && _autoGenerateUVs) { @@ -226,207 +196,244 @@ class CompactSubGeometry extends SubGeometryBase implements ISubGeometry } return _vertexData; } - + override public function applyTransformation(transform:Matrix3D):Void { super.applyTransformation(transform); invalidateBuffers(_vertexDataInvalid); } - + override public function scale(scale:Float):Void { super.scale(scale); invalidateBuffers(_vertexDataInvalid); } - + public function clone():ISubGeometry { - var clone:CompactSubGeometry = new CompactSubGeometry(); + var clone:CompactSubGeometry = new CompactSubGeometry(definition); clone._autoDeriveVertexNormals = _autoDeriveVertexNormals; clone._autoDeriveVertexTangents = _autoDeriveVertexTangents; clone.updateData(_vertexData.concat()); clone.updateIndexData(_indices.concat()); return clone; } - + override public function scaleUV(scaleU:Float = 1, scaleV:Float = 1):Void { super.scaleUV(scaleU, scaleV); invalidateBuffers(_vertexDataInvalid); } - + override private function get_vertexStride():Int { - return 13; + return definition.length; } - + override private function get_vertexNormalStride():Int { - return 13; + return definition.length; } - + override private function get_vertexTangentStride():Int { - return 13; + return definition.length; } - + override private function get_UVStride():Int { - return 13; + return definition.length; } - + private function get_secondaryUVStride():Int { - return 13; + return definition.length; } - + override private function get_vertexOffset():Int { - return 0; + return getAttributeOffset("position"); } - + override private function get_vertexNormalOffset():Int { - return 3; + return getAttributeOffset("normal"); } - + override private function get_vertexTangentOffset():Int { - return 6; + return getAttributeOffset("tangent"); } - + override private function get_UVOffset():Int { - return 9; + return getAttributeOffset("UV"); } - + private function get_secondaryUVOffset():Int { - return 11; + return getAttributeOffset("secondaryUV"); } - + + private inline function getAttributeOffset(attributeName:String):Int + { + var attribute:AttributeDefinition = definition.get(attributeName); + return attribute != null ? attribute.offset : 0; + } + override public function dispose():Void { super.dispose(); disposeVertexBuffers(_vertexBuffer); _vertexBuffer = null; } - + override private function disposeVertexBuffers(buffers:Vector):Void { super.disposeVertexBuffers(buffers); _activeBuffer = null; } - + override private function invalidateBuffers(invalid:Vector):Void { super.invalidateBuffers(invalid); _activeDataInvalid = true; } - + public function cloneWithSeperateBuffers():SubGeometry { var clone:SubGeometry = new SubGeometry(); - clone.updateVertexData(_isolatedVertexPositionData != null? _isolatedVertexPositionData : _isolatedVertexPositionData = stripBuffer(0, 3)); + clone.updateVertexData(get_vertexPositionData()); clone.autoDeriveVertexNormals = _autoDeriveVertexNormals; clone.autoDeriveVertexTangents = _autoDeriveVertexTangents; if (!_autoDeriveVertexNormals) - clone.updateVertexNormalData(stripBuffer(3, 3)); + clone.updateVertexNormalData(isolateAttribute("normal")); if (!_autoDeriveVertexTangents) - clone.updateVertexTangentData(stripBuffer(6, 3)); - clone.updateUVData(stripBuffer(9, 2)); - clone.updateSecondaryUVData(stripBuffer(11, 2)); + clone.updateVertexTangentData(isolateAttribute("tangent")); + clone.updateUVData(isolateAttribute("UV")); + clone.updateSecondaryUVData(isolateAttribute("secondaryUV")); clone.updateIndexData(indexData.concat()); return clone; } - + override private function get_vertexPositionData():Vector { if (_isolatedVertexPositionDataDirty || _isolatedVertexPositionData == null) { - _isolatedVertexPositionData = stripBuffer(0, 3); + _isolatedVertexPositionData = isolateAttribute("position"); _isolatedVertexPositionDataDirty = false; } return _isolatedVertexPositionData; } - + + /** + * Isolates and returns all data for the attribute with the given name, + * typically one of "position", "normal", "tangent", "UV", or "secondaryUV". + */ + public function isolateAttribute(name:String):Vector + { + var attribute:AttributeDefinition = definition.get(name); + if (attribute != null) + { + return stripBuffer(attribute.offset, attribute.length); + } + else + { + return null; + } + } + /** - * Isolate and returns a Vector.Number of a specific buffer type - * - * - stripBuffer(0, 3), return only the vertices - * - stripBuffer(3, 3): return only the normals - * - stripBuffer(6, 3): return only the tangents - * - stripBuffer(9, 2): return only the uv's - * - stripBuffer(11, 2): return only the secondary uv's + * Isolates and returns a specific subset of this geometry. + * @see `isolateAttribute` */ public function stripBuffer(offset:Int, numEntries:Int):Vector { var data:Vector = new Vector(_numVertices*numEntries); var i:Int = 0, j:Int = offset; - var skip:Int = 13 - numEntries; - + var skip:Int = definition.length - numEntries; + for (v in 0..._numVertices) { for (k in 0...numEntries) data[i++] = _vertexData[j++]; j += skip; } - + return data; } - - public function fromVectors(verts:Vector, uvs:Vector, normals:Vector, tangents:Vector):Void - { - var vertLen:Int = Std.int(verts.length/3*13); - - var index:Int = 0; - var v:Int = 0; - var n:Int = 0; - var t:Int = 0; - var u:Int = 0; - - var data:Vector = new Vector(vertLen, true); - - while (index < vertLen) { - data[index++] = verts[v++]; - data[index++] = verts[v++]; - data[index++] = verts[v++]; - - if (normals != null && normals.length > 0) { - data[index++] = normals[n++]; - data[index++] = normals[n++]; - data[index++] = normals[n++]; - } else { - data[index++] = 0; - data[index++] = 0; - data[index++] = 0; + + public function setAttributeData(attributeName:String, data:Vector):Void + { + if (_setAttributeData(attributeName, data)) + { + updateData(_vertexData); + } + } + + private function _setAttributeData(attributeName:String, data:Vector):Bool + { + var attribute:AttributeDefinition = definition.get(attributeName); + if (data == null || attribute == null) + { + return false; + } + + if (_vertexData == null) + { + _vertexData = new Vector(definition.length * Std.int(data.length / attribute.length)); + } + + var attributeLength:Int = attribute.length; + var vertexLength:Int = _vertexData.length; + + var inputIndex:Int = 0; + var outputIndex:Int = attribute.offset; + while (inputIndex + attributeLength < data.length + && outputIndex + attributeLength < _vertexData.length) + { + for (i in 0...attributeLength) + { + _vertexData[outputIndex + i] = data[inputIndex + i]; } - - if (tangents != null && tangents.length > 0) { - data[index++] = tangents[t++]; - data[index++] = tangents[t++]; - data[index++] = tangents[t++]; - } else { - data[index++] = 0; - data[index++] = 0; - data[index++] = 0; + + inputIndex += attributeLength; + outputIndex += vertexLength; + } + + return true; + } + + public function fromVectors(positions:Vector, uvs:Vector, normals:Vector, tangents:Vector):Void + { + if (positions != null) + { + var newLength:Int = Std.int(positions.length / 3 * definition.length); + var oldLength:Int = _vertexData != null ? _vertexData.length : 0; + if (newLength < oldLength) + { + _vertexData = _vertexData.slice(0, newLength); } - - if (uvs != null && uvs.length > 0) { - data[index++] = uvs[u]; - data[index++] = uvs[u + 1]; - // use same secondary uvs as primary - data[index++] = uvs[u++]; - data[index++] = uvs[u++]; - } else { - data[index++] = 0; - data[index++] = 0; - data[index++] = 0; - data[index++] = 0; + else if (newLength > oldLength) + { + var newData:Vector = new Vector(newLength, true); + for (i in 0...oldLength) + { + newData[i] = _vertexData[i]; + } + _vertexData = newData; } + + _setAttributeData("position", positions); } - + + _setAttributeData("normal", normals); autoDeriveVertexNormals = !(normals != null && normals.length > 0); + + _setAttributeData("tangent", tangents); autoDeriveVertexTangents = !(tangents != null && tangents.length > 0); + + _setAttributeData("UV", uvs); autoGenerateDummyUVs = !(uvs != null && uvs.length > 0); - updateData(data); + + updateData(_vertexData); } -} \ No newline at end of file +} diff --git a/away3d/core/base/data/VertexDefinition.hx b/away3d/core/base/data/VertexDefinition.hx new file mode 100644 index 00000000..abe890d5 --- /dev/null +++ b/away3d/core/base/data/VertexDefinition.hx @@ -0,0 +1,141 @@ +package away3d.core.base.data; + +import openfl.display3D.Context3DVertexBufferFormat; + +#if haxe4 +import haxe.ds.ReadOnlyArray; +#end + +using Lambda; + +/** + * The contents of a single vertex in a `CompactSubGeometry`. + */ +class VertexDefinition +{ + /** + * The default attributes used by `CompactSubGeometry`: position, normal, + * tangent, UV, and secondaryUV. + */ + public static var defaultAttributes(default, null):ReadOnlyArray = [ + new AttributeDefinition("position", 3), + new AttributeDefinition("normal", 3), + new AttributeDefinition("tangent", 3), + new AttributeDefinition("UV", 2), + new AttributeDefinition("secondaryUV", 2) + ]; + + /** + * A definition using `defaultAttributes`: position, normal, tangent, UV, + * and secondaryUV. + */ + public static var defaultVertexDefinition(default, null):VertexDefinition = new VertexDefinition(defaultAttributes); + + public var attributes(default, null):ReadOnlyArray; + + /** + * The combined length of all attributes; the total number of float values + * stored per vertex. + */ + public var length(default, null):Int; + + public function new(attributes:ReadOnlyArray) + { + var attributes:Array = attributes.copy(); + var length:Int = 0; + + for (index in 0...attributes.length) + { + var attribute:AttributeDefinition = attributes[index]; + + // If an offset was already set, the attribute is most likely in use + // elsewhere. Instead of modifying it, make a copy. + if (attribute.offset != -1 && attribute.offset != length) + { + attributes[index] = attribute.clone(); + } + + attribute.offset = length; + length += attribute.length; + } + + this.length = length; + this.attributes = attributes; + } + + public function get(attributeName:String):AttributeDefinition + { + for (attribute in attributes) + { + if (attribute.name == attributeName) + { + return attribute; + } + } + return null; + } + + public inline function toString():String + { + return Std.string(attributes); + } +} + +class AttributeDefinition +{ + public var length(default, null):Int; + + @:allow(away3d.core.base.data.VertexDefinition) + public var offset(default, null):Int = -1; + + public var name(default, null):String; + + public var vertexBufferFormat(default, null):Context3DVertexBufferFormat; + + public inline function new(name:String, length:Int) + { + this.name = name; + this.length = length; + + vertexBufferFormat = switch (length) + { + case 1: + FLOAT_1; + case 2: + FLOAT_2; + case 3: + FLOAT_3; + case 4: + FLOAT_4; + default: + throw length + " should be 1-4"; + }; + } + + public inline function clone():AttributeDefinition + { + return new AttributeDefinition(name, length); + } + + public inline function toString():String + { + return name + ":FLOAT_" + length; + } +} + +#if !haxe4 +@:forward(copy, filter, indexOf, iterator, join, lastIndexOf, map, slice, toString) +abstract ReadOnlyArray(Array) from Array to Iterable +{ + public var length(get, never):Int; + + inline function get_length() + return this.length; + + @:arrayAccess inline function get(i:Int) + return this[i]; + + public inline function concat(a:ReadOnlyArray):Array + return this.concat(cast a); +} +#end diff --git a/away3d/loaders/parsers/DAEParser.hx b/away3d/loaders/parsers/DAEParser.hx index 63f425d4..3fb828be 100644 --- a/away3d/loaders/parsers/DAEParser.hx +++ b/away3d/loaders/parsers/DAEParser.hx @@ -492,7 +492,7 @@ class DAEParser extends ParserBase for (i in 0...base.subGeometries.length) { sub = cast(base.subGeometries[i], CompactSubGeometry); vertexData = sub.vertexData.concat(); - for (v in 0...Std.int(vertexData.length/13)) { + for (v in 0...Std.int(vertexData.length/sub.definition.length)) { j = sub.vertexOffset + v*sub.vertexStride; vertexData[j] = morph.method == "NORMALIZED"? startWeight*sub.vertexData[j] : sub.vertexData[j]; for (k in 0...morph.targets.length) diff --git a/away3d/tools/helpers/ParticleGeometryHelper.hx b/away3d/tools/helpers/ParticleGeometryHelper.hx index 5a87b0b8..574004cc 100644 --- a/away3d/tools/helpers/ParticleGeometryHelper.hx +++ b/away3d/tools/helpers/ParticleGeometryHelper.hx @@ -3,6 +3,7 @@ package away3d.tools.helpers; import away3d.core.base.ParticleGeometry; import away3d.core.base.CompactSubGeometry; import away3d.core.base.data.ParticleData; +import away3d.core.base.data.VertexDefinition; import away3d.core.base.Geometry; import away3d.core.base.ISubGeometry; import away3d.tools.helpers.data.ParticleGeometryTransform; @@ -20,7 +21,7 @@ class ParticleGeometryHelper { public static inline var MAX_VERTEX:Int = 65535; - public static function generateGeometry(geometries:Vector, transforms:Vector = null):ParticleGeometry + public static function generateGeometry(geometries:Vector, transforms:Vector = null, ?vertexDefinition:VertexDefinition):ParticleGeometry { var verticesVector:Vector> = new Vector>(); var indicesVector:Vector> = new Vector>(); @@ -45,6 +46,11 @@ class ParticleGeometryHelper var tempTangents:Vector3D = new Vector3D(); var tempUV:Point = new Point(); + var positionDefinition:AttributeDefinition = vertexDefinition.get("position"); + var normalDefinition:AttributeDefinition = vertexDefinition.get("normal"); + var tangentDefinition:AttributeDefinition = vertexDefinition.get("tangent"); + var uvDefinition:AttributeDefinition = vertexDefinition.get("UV"); + for (i in 0...numParticles) { sourceSubGeometries = geometries[i].subGeometries; numSubGeometries = sourceSubGeometries.length; @@ -54,7 +60,7 @@ class ParticleGeometryHelper sub2SubMap.push(subGeometries.length); verticesVector.push(new Vector()); indicesVector.push(new Vector()); - subGeometries.push(new CompactSubGeometry()); + subGeometries.push(new CompactSubGeometry(vertexDefinition)); vertexCounters.push(0); } @@ -66,7 +72,7 @@ class ParticleGeometryHelper sub2SubMap[srcIndex] = subGeometries.length; verticesVector.push(new Vector()); indicesVector.push(new Vector()); - subGeometries.push(new CompactSubGeometry()); + subGeometries.push(new CompactSubGeometry(vertexDefinition)); vertexCounters.push(0); } @@ -88,13 +94,17 @@ class ParticleGeometryHelper vertexCounters[j] += sourceSubGeometry.numVertices; var k:Int; - var tempLen:Int; var compact:CompactSubGeometry = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(sourceSubGeometry, CompactSubGeometry) ? cast sourceSubGeometry : null; var product:Int; var sourceVertices:Vector; + var attributesDone:Array = []; + + var inStride:Int = compact.definition.length; + var outStride:Int = subGeometry.definition.length; + var startIndex:Int = vertices.length; + vertices.length += outStride * compact.numVertices; if (compact != null) { - tempLen = compact.numVertices; compact.numTriangles; sourceVertices = compact.vertexData; @@ -104,64 +114,102 @@ class ParticleGeometryHelper var invVertexTransform:Matrix3D = particleGeometryTransform.invVertexTransform; var UVTransform:Matrix = particleGeometryTransform.UVTransform; - for (k in 0...tempLen) { - /* - * 0 - 2: vertex position X, Y, Z - * 3 - 5: normal X, Y, Z - * 6 - 8: tangent X, Y, Z - * 9 - 10: U V - * 11 - 12: Secondary U V*/ - product = k*13; - tempVertex.x = sourceVertices[product]; - tempVertex.y = sourceVertices[product + 1]; - tempVertex.z = sourceVertices[product + 2]; - tempNormal.x = sourceVertices[product + 3]; - tempNormal.y = sourceVertices[product + 4]; - tempNormal.z = sourceVertices[product + 5]; - tempTangents.x = sourceVertices[product + 6]; - tempTangents.y = sourceVertices[product + 7]; - tempTangents.z = sourceVertices[product + 8]; - tempUV.x = sourceVertices[product + 9]; - tempUV.y = sourceVertices[product + 10]; - if (vertexTransform != null) { + var inPositionDefinition:AttributeDefinition = compact.definition.get("position"); + var inNormalDefinition:AttributeDefinition = compact.definition.get("normal"); + var inTangentDefinition:AttributeDefinition = compact.definition.get("tangent"); + var inUVDefinition:AttributeDefinition = compact.definition.get("UV"); + + for (k in 0...compact.numVertices) { + product = k*compact.definition.length; + + if (inPositionDefinition != null && positionDefinition != null && vertexTransform != null) { + tempVertex.x = sourceVertices[product + inPositionDefinition.offset]; + tempVertex.y = sourceVertices[product + inPositionDefinition.offset + 1]; + tempVertex.z = sourceVertices[product + inPositionDefinition.offset + 2]; + #if flash tempVertex = vertexTransform.transformVector(tempVertex); + #else + vertexTransform.transformVectorToOutput(tempVertex, tempVertex); + #end + vertices[startIndex + k * vertexDefinition.length + positionDefinition.offset] = tempVertex.x; + vertices[startIndex + k * vertexDefinition.length + positionDefinition.offset + 1] = tempVertex.y; + vertices[startIndex + k * vertexDefinition.length + positionDefinition.offset + 2] = tempVertex.z; + + attributesDone.push("position"); + } + + if (inNormalDefinition != null && normalDefinition != null && vertexTransform != null) { + tempNormal.x = sourceVertices[product + inNormalDefinition.offset]; + tempNormal.y = sourceVertices[product + inNormalDefinition.offset + 1]; + tempNormal.z = sourceVertices[product + inNormalDefinition.offset + 2]; + #if flash tempNormal = invVertexTransform.deltaTransformVector(tempNormal); - tempTangents = invVertexTransform.deltaTransformVector(tempNormal); + #else + invVertexTransform.deltaTransformVectorToOutput(tempNormal, tempNormal); + #end + vertices[startIndex + k * vertexDefinition.length + normalDefinition.offset] = tempNormal.x; + vertices[startIndex + k * vertexDefinition.length + normalDefinition.offset + 1] = tempNormal.y; + vertices[startIndex + k * vertexDefinition.length + normalDefinition.offset + 2] = tempNormal.z; + + attributesDone.push("normal"); + } + + if (inTangentDefinition != null && tangentDefinition != null && vertexTransform != null) { + tempTangents.x = sourceVertices[product + inTangentDefinition.offset]; + tempTangents.y = sourceVertices[product + inTangentDefinition.offset + 1]; + tempTangents.z = sourceVertices[product + inTangentDefinition.offset + 2]; + #if flash + tempTangents = invVertexTransform.deltaTransformVector(tempTangents); + #else + invVertexTransform.deltaTransformVectorToOutput(tempTangents, tempTangents); + #end + vertices[startIndex + k * vertexDefinition.length + tangentDefinition.offset] = tempTangents.x; + vertices[startIndex + k * vertexDefinition.length + tangentDefinition.offset + 1] = tempTangents.y; + vertices[startIndex + k * vertexDefinition.length + tangentDefinition.offset + 2] = tempTangents.z; + + attributesDone.push("tangent"); } - if (UVTransform != null) + + if (inUVDefinition != null && uvDefinition != null && UVTransform != null) { + tempUV.x = sourceVertices[product + inUVDefinition.offset]; + tempUV.y = sourceVertices[product + inUVDefinition.offset + 1]; + #if flash tempUV = UVTransform.transformPoint(tempUV); - //this is faster than that only push one data - vertices.push(tempVertex.x); - vertices.push(tempVertex.y); - vertices.push(tempVertex.z); - vertices.push(tempNormal.x); - vertices.push(tempNormal.y); - vertices.push(tempNormal.z); - vertices.push(tempTangents.x); - vertices.push(tempTangents.y); - vertices.push(tempTangents.z); - vertices.push(tempUV.x); - vertices.push(tempUV.y); - vertices.push(sourceVertices[product + 11]); - vertices.push(sourceVertices[product + 12]); + #else + UVTransform.transformPointToOutput(tempUV, tempUV); + #end + vertices[startIndex + k * vertexDefinition.length + uvDefinition.offset] = tempUV.x; + vertices[startIndex + k * vertexDefinition.length + uvDefinition.offset + 1] = tempUV.y; + + attributesDone.push("UV"); + } + } + } + + for (outAttribute in subGeometry.definition.attributes) { + if (attributesDone.indexOf(outAttribute.name) >= 0) { + continue; } - } else { - for (k in 0...tempLen) { - product = k*13; - //this is faster than that only push one data - vertices.push(sourceVertices[product]); - vertices.push(sourceVertices[product + 1]); - vertices.push(sourceVertices[product + 2]); - vertices.push(sourceVertices[product + 3]); - vertices.push(sourceVertices[product + 4]); - vertices.push(sourceVertices[product + 5]); - vertices.push(sourceVertices[product + 6]); - vertices.push(sourceVertices[product + 7]); - vertices.push(sourceVertices[product + 8]); - vertices.push(sourceVertices[product + 9]); - vertices.push(sourceVertices[product + 10]); - vertices.push(sourceVertices[product + 11]); - vertices.push(sourceVertices[product + 12]); + + var sourceAttribute:AttributeDefinition = compact.definition.get(outAttribute.name); + + if (sourceAttribute == null) { + throw 'Input data does not include attribute "${ outAttribute.name }". It defines "' + + [for(attribute in compact.definition.attributes) attribute.name].join('", "') + '".'; + } + + if (outAttribute.length != sourceAttribute.length) { + throw 'Length mismatch for attribute "${ outAttribute.name }": source has length ${ sourceAttribute.length }, destination needs length ${ outAttribute.name }.'; + } + + var length:Int = outAttribute.length; + var inOffset:Int = sourceAttribute.offset; + var outOffset:Int = outAttribute.offset; + + for (k in 0...compact.numVertices) { + for (l in 0...length) { + vertices[startIndex + k * outStride + outOffset + l] = sourceVertices[k * inStride + inOffset + l]; + } } } } else { @@ -169,8 +217,7 @@ class ParticleGeometryHelper } var sourceIndices:Vector = sourceSubGeometry.indexData; - tempLen = sourceSubGeometry.numTriangles; - for (k in 0...tempLen) { + for (k in 0...sourceSubGeometry.numTriangles) { product = k*3; indices.push(sourceIndices[product] + vertexCounter); indices.push(sourceIndices[product + 1] + vertexCounter); @@ -183,8 +230,7 @@ class ParticleGeometryHelper particleGeometry.particles = particles; particleGeometry.numParticles = numParticles; - numParticles = subGeometries.length; - for (i in 0...numParticles) { + for (i in 0...subGeometries.length) { subGeometry = subGeometries[i]; subGeometry.updateData(verticesVector[i]); subGeometry.updateIndexData(indicesVector[i]); diff --git a/away3d/tools/utils/GeomUtil.hx b/away3d/tools/utils/GeomUtil.hx index 2e43e5ec..6168c6a1 100644 --- a/away3d/tools/utils/GeomUtil.hx +++ b/away3d/tools/utils/GeomUtil.hx @@ -189,8 +189,8 @@ class GeomUtil /* * Combines a set of separate raw buffers into an interleaved one, compatible - * with CompactSubGeometry. SubGeometry uses separate buffers, whereas CompactSubGeometry - * uses a single, combined buffer. + * with a default CompactSubGeometry. SubGeometry uses separate buffers, whereas + * CompactSubGeometry uses a single, combined buffer. */ public static function interleaveBuffers(numVertices:Int, vertices:Vector = null, normals:Vector = null, tangents:Vector = null, uvs:Vector = null, suvs:Vector = null):Vector {