mirror of
https://github.com/MapMakersAndProgrammers/Alternativa3D.git
synced 2025-10-26 09:59:10 -07:00
Get back good state of master
This commit is contained in:
@@ -32,7 +32,7 @@ package alternativa.engine3d.lights {
|
||||
/**
|
||||
* Distance from at which falloff is complete.
|
||||
*/
|
||||
public var _attenuationEnd:Number;
|
||||
public var attenuationEnd:Number;
|
||||
|
||||
/**
|
||||
* Creates a OmniLight object.
|
||||
@@ -209,22 +209,7 @@ package alternativa.engine3d.lights {
|
||||
_shadow = value;
|
||||
_shadow._light = this;
|
||||
var omniShadow:OmniLightShadow = value as OmniLightShadow;
|
||||
if (omniShadow!=null) omniShadow.setBoundSize(this._attenuationEnd*1.0);
|
||||
if (omniShadow!=null) omniShadow.setBoundSize(this.attenuationEnd*1.5);
|
||||
}
|
||||
|
||||
public function get attenuationEnd():Number{
|
||||
return _attenuationEnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set attenuationEnd(value:Number):void{
|
||||
// TODO: recalculate BoundBox
|
||||
_attenuationEnd = value;
|
||||
var omniShadow:OmniLightShadow = shadow as OmniLightShadow;
|
||||
if (omniShadow!=null) omniShadow.setBoundSize(this._attenuationEnd*1.0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -139,6 +139,7 @@ package alternativa.engine3d.loaders.collada {
|
||||
var data:ByteArray = geometry._vertexStreams[0].data;
|
||||
var numMappings:int = geometry._vertexStreams[0].attributes.length;
|
||||
|
||||
// TODO: Normalize normal and tangent after transformation
|
||||
// TODO: Transform normal with transpose inverted matrix
|
||||
var normalOffset:int = (geometry.hasAttribute(VertexAttributes.NORMAL))?geometry.getAttributeOffset(VertexAttributes.NORMAL):-1;
|
||||
var tangentOffset:int = (geometry.hasAttribute(VertexAttributes.TANGENT4))?geometry.getAttributeOffset(VertexAttributes.TANGENT4):-1;
|
||||
@@ -152,13 +153,13 @@ package alternativa.engine3d.loaders.collada {
|
||||
data.writeFloat(x*bindShapeMatrix[0] + y*bindShapeMatrix[1] + z*bindShapeMatrix[2] + bindShapeMatrix[3]);
|
||||
data.writeFloat(x*bindShapeMatrix[4] + y*bindShapeMatrix[5] + z*bindShapeMatrix[6] + bindShapeMatrix[7]);
|
||||
data.writeFloat(x*bindShapeMatrix[8] + y*bindShapeMatrix[9] + z*bindShapeMatrix[10] + bindShapeMatrix[11]);
|
||||
|
||||
|
||||
var tmpX:Number;
|
||||
var tmpY:Number;
|
||||
var tmpZ:Number;
|
||||
var tmpLen:Number;
|
||||
|
||||
if (normalOffset >= 0){
|
||||
if (normalOffset>=0){
|
||||
data.position = 4*(numMappings*i + normalOffset);
|
||||
var normalX:Number = data.readFloat();
|
||||
var normalY:Number = data.readFloat();
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private простое дерево, на листочках ключи KFbxAnimCurve
|
||||
*/
|
||||
public class KFbxAnimCurveNode {
|
||||
public var node:KFbxNode;
|
||||
|
||||
public var channel:String;
|
||||
public var curveNodes:Vector.<KFbxAnimCurveNode> = new Vector.<KFbxAnimCurveNode>();
|
||||
|
||||
public function collectNodes(nodes:Vector.<KFbxNode>):void {
|
||||
for each (var curveNode:KFbxAnimCurveNode in curveNodes) {
|
||||
if (curveNode.node) {
|
||||
if (nodes.indexOf(curveNode.node) < 0) {
|
||||
nodes.push(curveNode.node);
|
||||
}
|
||||
}
|
||||
curveNode.collectNodes(nodes);
|
||||
}
|
||||
}
|
||||
|
||||
public function collectCurves(curves:Vector.<KFbxAnimCurveNode>, targetNode:KFbxNode):void {
|
||||
for each (var curveNode:KFbxAnimCurveNode in curveNodes) {
|
||||
if (curveNode.node == targetNode) {
|
||||
if (curveNode.curveNodes.length > 0) {
|
||||
// if children are not bound to node...
|
||||
if (curveNode.curveNodes [0].node == null) {
|
||||
// ...collect it...
|
||||
curves.push(curveNode);
|
||||
} else {
|
||||
// ...else keep drilling
|
||||
curveNode.collectCurves(curves, targetNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// KFbxAnimCurve:
|
||||
public var KeyTime:Vector.<Number> = new Vector.<Number>();
|
||||
public var KeyValueFloat:Vector.<Number> = new Vector.<Number>();
|
||||
|
||||
public function interpolateValue(t:Number):Number {
|
||||
for (var i:int = 1, n:int = KeyTime.length; i < n; i++) {
|
||||
if (t > KeyTime [int(i)]) continue;
|
||||
// linear for now, TODO
|
||||
var c:Number = ( KeyTime [int(i)] - t )/( KeyTime [int(i)] - KeyTime [int(i - 1)] );
|
||||
return KeyValueFloat [int(i)]*(1 - c) + KeyValueFloat [int(i - 1)]*c;
|
||||
}
|
||||
return KeyValueFloat [int(n - 1)];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private SDK: The animation layer is a collection of animation curve nodes.
|
||||
|
||||
Its purpose is to store a variable number of KFbxAnimCurveNodes. The class provides different states flags (bool properties), an animatable weight, and the blending mode flag to indicate how the data on this layer is interacting with the data of the other layers during the evaluation.
|
||||
|
||||
*/
|
||||
public class KFbxAnimLayer extends KFbxAnimCurveNode {
|
||||
// TODO blending support
|
||||
|
||||
/** в V6 один получается 1 слой на KFbxNode, но curveNode-ы не привязаны к нему. */
|
||||
public function fixV6():void {
|
||||
fixV6CurveNodes(this);
|
||||
}
|
||||
|
||||
private function fixV6CurveNodes(parent:KFbxAnimCurveNode):void {
|
||||
if (parent.node) {
|
||||
for each (var child:KFbxAnimCurveNode in parent.curveNodes) {
|
||||
if (child.curveNodes.length > 0) {
|
||||
child.node = parent.node;
|
||||
fixV6CurveNodes(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private SDK: The Animation stack is a collection of animation layers.
|
||||
|
||||
The Fbx document can have one or more animation stacks. Each stack can be viewed as one "take" in the previous versions of the FBX SDK. The "stack" terminology comes from the fact that the object contains 1 to n animation layers that are evaluated according to their blending modes to produce a resulting animation for a given attribute.
|
||||
|
||||
*/
|
||||
public class KFbxAnimStack {
|
||||
public var layers:Vector.<KFbxAnimLayer> = new Vector.<KFbxAnimLayer>();
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private SDK: Class for clusters (links).
|
||||
* A cluster, or link, is an entity acting on a geometry (KFbxGeometry). More precisely, the cluster acts on a subset of the geometry's control points. For each control point that the cluster acts on, the intensity of the cluster's action is modulated by a weight. The link mode (ELinkMode) specifies how the weights are taken into account.
|
||||
*/
|
||||
public class KFbxCluster { // extends KFbxSubDeformer {
|
||||
public var Indexes:Vector.<Number> = new Vector.<Number>;
|
||||
public var Weights:Vector.<Number> = new Vector.<Number>;
|
||||
public var Transform:Vector.<Number> = Vector.<Number>([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
|
||||
public var TransformLink:Vector.<Number> = Vector.<Number>([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
|
||||
|
||||
// связь с джоинтом
|
||||
public var jointNode:KFbxNode;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private SDK: Base class for skin deformer (KFbxSkin) and vertex cache deformer (KFbxVertexCacheDeformer).
|
||||
*/
|
||||
public class KFbxDeformer {
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private SDK: The base class of geometric objects that support control point deformations.
|
||||
*/
|
||||
public class KFbxGeometry extends KFbxGeometryBase {
|
||||
public var deformers:Vector.<KFbxDeformer> = new Vector.<KFbxDeformer>();
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private SDK: This class is the base class for geometric object such as meshes, NURBS and patches.
|
||||
*/
|
||||
public class KFbxGeometryBase extends KFbxLayerContainer {
|
||||
/**
|
||||
* KArrayTemplate< KFbxVector4 > mControlPoints
|
||||
*/
|
||||
public var Vertices:Vector.<Number> = new Vector.<Number>();
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private SDK: A layer can contain one or more of the following layer elements:
|
||||
* Normals
|
||||
* Binormals
|
||||
* Tangents
|
||||
* Materials
|
||||
* Polygon Groups
|
||||
* UVs
|
||||
* Vertex Colors
|
||||
* Smoothing informations
|
||||
* Vertex Creases
|
||||
* Edge Creases
|
||||
* Custom User Data
|
||||
* Visibilities
|
||||
* Textures (diffuse, ambient, specular, etc.) (deprecated)
|
||||
* A typical layer for a Mesh contains Normals, UVs and Materials. A typical layer for NURBS contains only Materials. In the case of the NURBS, the NURBS' parameterization is used for the UVs; no UVs should be specified.
|
||||
* In most cases, you only need a single layer to describe a geometry. Many applications only support what is defined on the first layer. Take this into account when you fill the layer. For example, it is legal to define the Layer 0 with the UVs and then define the model's Normals on layer 1. However if you construct a file this way, it may not be imported correctly in other applications. Store the Normals in Layer 0 to avoid problems.
|
||||
*/
|
||||
public class KFbxLayer {
|
||||
public var elements:Vector.<KFbxLayerElement> = new Vector.<KFbxLayerElement>();
|
||||
|
||||
public function getLayerElement(type:Class, stringProperty:String = null,
|
||||
value:String = null):KFbxLayerElement {
|
||||
for (var i:int = 0; i < elements.length; i++) {
|
||||
var e:KFbxLayerElement = elements [i];
|
||||
if (e is type) {
|
||||
if (stringProperty == null) {
|
||||
return e;
|
||||
} else {
|
||||
if (e [stringProperty] == value) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private SDK: Contains a collection of KFbxLayer objects.
|
||||
*/
|
||||
public class KFbxLayerContainer extends KFbxNodeAttribute {
|
||||
public var layers:Vector.<KFbxLayer> = new Vector.<KFbxLayer>();
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private SDK: A KFbxLayerElement contains Normals, UVs or other kind of information..
|
||||
*/
|
||||
public class KFbxLayerElement {
|
||||
/**
|
||||
* Mapping.
|
||||
* "NoMappingInformation"
|
||||
* "ByVertice"
|
||||
* "ByPolygon"
|
||||
* "ByPolygonVertex"
|
||||
* "ByFace"
|
||||
* "ByEdge"
|
||||
* "AllSame"
|
||||
* "ByModel"
|
||||
*
|
||||
* {
|
||||
* eNONE,
|
||||
* eBY_CONTROL_POINT,
|
||||
* eBY_POLYGON_VERTEX,
|
||||
* eBY_POLYGON,
|
||||
* eBY_EDGE,
|
||||
* eALL_SAME
|
||||
* } EMappingMode;
|
||||
*/
|
||||
public var MappingInformationType:String;
|
||||
/**
|
||||
* Reference.
|
||||
* "Direct" This indicates that the mapping information for the n'th element
|
||||
* is found in the n'th place of KFbxLayerElementTemplate::mDirectArray.
|
||||
* "Index" This symbol is kept for backward compatibility with FBX v5.0 files.
|
||||
* In FBX v6.0 and higher, this symbol is replaced with "IndexToDirect".
|
||||
* "IndexToDirect" This indicates that the KFbxLayerElementTemplate::mIndexArray
|
||||
* contains, for the n'th element, an index in the KFbxLayerElementTemplate::mDirectArray
|
||||
* array of mapping elements.
|
||||
*/
|
||||
public var ReferenceInformationType:String;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private SDK: Layer element for mapping materials (KFbxSurfaceMaterial) to a geometry.
|
||||
*/
|
||||
public class KFbxLayerElementMaterial extends KFbxLayerElement {
|
||||
public var Materials:Vector.<Number> = new Vector.<Number>();
|
||||
|
||||
public function KFbxLayerElementMaterial(values:Vector.<Number> = null, mapping:String = "ByPolygon",
|
||||
reference:String = "IndexToDirect") {
|
||||
if (values != null) Materials = values;
|
||||
if (mapping != null) MappingInformationType = mapping;
|
||||
if (reference != null) ReferenceInformationType = reference;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
import flash.geom.Vector3D;
|
||||
|
||||
/**
|
||||
* @private SDK: Layer to map Normals on a geometry.
|
||||
*/
|
||||
public class KFbxLayerElementNormal extends KFbxLayerElement {
|
||||
public var Normals:Vector.<Number> = new Vector.<Number>();
|
||||
|
||||
public function KFbxLayerElementNormal(values:Vector.<Number> = null, mapping:String = "ByVertice"
|
||||
/* TODO "ByPolygonVertex" ?? */, reference:String = "Direct") {
|
||||
if (values != null) Normals = values;
|
||||
if (mapping != null) MappingInformationType = mapping;
|
||||
if (reference != null) ReferenceInformationType = reference;
|
||||
}
|
||||
|
||||
static public function generateDefaultNormals(mesh:KFbxMesh):KFbxLayerElementNormal {
|
||||
var vertices:Vector.<Number> = mesh.Vertices, polyIndex:Vector.<Number> = mesh.PolygonVertexIndex;
|
||||
|
||||
var vertexNormals:Vector.<Number> = new Vector.<Number>(vertices.length);
|
||||
|
||||
var i:int = 0;
|
||||
var va:Vector3D = new Vector3D;
|
||||
var vb:Vector3D = new Vector3D;
|
||||
var vc:Vector3D = new Vector3D;
|
||||
var vn:Vector3D;
|
||||
while (i < polyIndex.length) {
|
||||
var a:int = polyIndex [i], a3:int = a*3;
|
||||
var b:int = polyIndex [i + 1], b3:int = b*3;
|
||||
var c:int = polyIndex [i + 2], c3:int;
|
||||
if (c < 0) c = -c - 1;
|
||||
c3 = c*3;
|
||||
va.x = vertices [a3];
|
||||
va.y = vertices [a3 + 1];
|
||||
va.z = vertices [a3 + 2];
|
||||
vb.x = vertices [b3];
|
||||
vb.y = vertices [b3 + 1];
|
||||
vb.z = vertices [b3 + 2];
|
||||
vc.x = vertices [c3];
|
||||
vc.y = vertices [c3 + 1];
|
||||
vc.z = vertices [c3 + 2];
|
||||
va.decrementBy(vc);
|
||||
vb.decrementBy(vc);
|
||||
vn = va.crossProduct(vb); //vn.normalize ();
|
||||
|
||||
// TODO smoothing groups, "ByPolygonVertex"?
|
||||
do {
|
||||
c = polyIndex [i++];
|
||||
if (c < 0) c = -c - 1;
|
||||
c *= 3;
|
||||
vertexNormals [c] += vn.x;
|
||||
vertexNormals [c + 1] += vn.y;
|
||||
vertexNormals [c + 2] += vn.z;
|
||||
} while (polyIndex [i - 1] >= 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < vertexNormals.length; i += 3) {
|
||||
vn.x = 1e-9 + vertexNormals [i];
|
||||
vn.y = vertexNormals [i + 1];
|
||||
vn.z = vertexNormals [i + 2];
|
||||
vn.normalize();
|
||||
vertexNormals [i] = vn.x;
|
||||
vertexNormals [i + 1] = vn.y;
|
||||
vertexNormals [i + 2] = vn.z;
|
||||
}
|
||||
|
||||
return new KFbxLayerElementNormal(vertexNormals, "ByVertice", "Direct");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private SDK: Layer element for mapping Textures to a geometry.
|
||||
* Deprecated since FBX SDK 2011. Textures (KFbxTexture derived classes)
|
||||
* should be connected to material properties.
|
||||
*/
|
||||
public class KFbxLayerElementTexture extends KFbxLayerElement {
|
||||
public var TextureId:Vector.<Number> = new Vector.<Number>();
|
||||
|
||||
/**
|
||||
* Канал для ParserMaterial. Сам MotionBuilder v6, похоже, умеет только
|
||||
* diffuse текстуры, однако SDK предусматривает кучу типов. К сожалению,
|
||||
* SDK v7 считает KFbxLayerElementTexture устаревшим и не описывает
|
||||
* соответствующие токены (в примере файла найдены токены для specular и bump).
|
||||
*
|
||||
*
|
||||
* В SDK каждый KFbxLayerElement имеет тип, и в зависимости от типа
|
||||
* данные пишутся в конкретный класс-наследник; в KFbxLayerElementTexture
|
||||
* пишутся данные для следующих типов:
|
||||
* eDIFFUSE_TEXTURES Layer Element of type KFbxLayerElementTexture,
|
||||
* eEMISSIVE_TEXTURES Layer Element of type KFbxLayerElementTexture,
|
||||
* eEMISSIVE_FACTOR_TEXTURES Layer Element of type KFbxLayerElementTexture,
|
||||
* eAMBIENT_TEXTURES Layer Element of type KFbxLayerElementTexture,
|
||||
* eAMBIENT_FACTOR_TEXTURES Layer Element of type KFbxLayerElementTexture,
|
||||
* eDIFFUSE_FACTOR_TEXTURES Layer Element of type KFbxLayerElementTexture,
|
||||
* eSPECULAR_TEXTURES Layer Element of type KFbxLayerElementTexture,
|
||||
* eNORMALMAP_TEXTURES Layer Element of type KFbxLayerElementTexture,
|
||||
* eSPECULAR_FACTOR_TEXTURES Layer Element of type KFbxLayerElementTexture,
|
||||
* eSHININESS_TEXTURES Layer Element of type KFbxLayerElementTexture,
|
||||
* eBUMP_TEXTURES Layer Element of type KFbxLayerElementTexture,
|
||||
* eTRANSPARENT_TEXTURES Layer Element of type KFbxLayerElementTexture,
|
||||
* eTRANSPARENCY_FACTOR_TEXTURES Layer Element of type KFbxLayerElementTexture,
|
||||
* eREFLECTION_TEXTURES Layer Element of type KFbxLayerElementTexture,
|
||||
* eREFLECTION_FACTOR_TEXTURES Layer Element of type KFbxLayerElementTexture,
|
||||
* eDISPLACEMENT_TEXTURES Layer Element of type KFbxLayerElementTexture,
|
||||
* eVECTOR_DISPLACEMENT_TEXTURES Layer Element of type KFbxLayerElementTexture.
|
||||
* @see http://download.autodesk.com/global/docs/fbxsdk2012/en_us/cpp_ref/class_k_fbx_layer_element.html#a6478dfad43def5e882aaf6607af3fdae
|
||||
*/
|
||||
public var renderChannel:String;
|
||||
|
||||
public function KFbxLayerElementTexture(channel:String = "diffuse", values:Vector.<Number> = null,
|
||||
mapping:String = "ByPolygon", reference:String = "IndexToDirect") {
|
||||
if (channel != null) renderChannel = channel;
|
||||
if (values != null) TextureId = values;
|
||||
if (mapping != null) MappingInformationType = mapping;
|
||||
if (reference != null) ReferenceInformationType = reference;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private SDK: Layer element for mapping UVs to a geometry.
|
||||
*/
|
||||
public class KFbxLayerElementUV extends KFbxLayerElement {
|
||||
public var UV:Vector.<Number> = new Vector.<Number>();
|
||||
public var UVIndex:Vector.<Number> = new Vector.<Number>();
|
||||
|
||||
public function KFbxLayerElementUV() {
|
||||
// v5 has MappingInformationType set to "ByPolygon" - how the fuck could UVs be by polygon?
|
||||
MappingInformationType = "ByPolygonVertex";
|
||||
ReferenceInformationType = "IndexToDirect";
|
||||
}
|
||||
|
||||
static public function generateDefaultTextureMap(mesh:KFbxMesh):KFbxLayerElementUV {
|
||||
var uv:KFbxLayerElementUV = new KFbxLayerElementUV;
|
||||
var i:int, j:int;
|
||||
for (i = 0; i < mesh.PolygonVertexIndex.length; i++) {
|
||||
j = mesh.PolygonVertexIndex [i];
|
||||
if (j < 0) j = -j - 1;
|
||||
uv.UVIndex [i] = j;
|
||||
}
|
||||
for (i = 0; i < mesh.Vertices.length/3; i++) {
|
||||
j = i*3;
|
||||
var x:Number = mesh.Vertices [j++];
|
||||
var y:Number = mesh.Vertices [j++];
|
||||
var z:Number = mesh.Vertices [j++];
|
||||
var rxy:Number = 1e-5 + Math.sqrt(x*x + y*y);
|
||||
j = i*2;
|
||||
uv.UV [j++] = Math.atan2(rxy, z)*0.159154943 + 0.5;
|
||||
uv.UV [j++] = Math.atan2(y, x)*0.159154943 + 0.5;
|
||||
}
|
||||
return uv;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private SDK: This node attribute contains methods for accessing the properties of a light..
|
||||
*/
|
||||
public class KFbxLight extends KFbxNodeAttribute {
|
||||
public var Color:Vector.<Number> = Vector.<Number>([1, 1, 1]);
|
||||
/** Percents? Blender uses 0..200 range. */
|
||||
public var Intensity:Number = 100;
|
||||
|
||||
public function getIntensity():Number {
|
||||
return Intensity*1e-2;
|
||||
}
|
||||
|
||||
|
||||
/** Outer cone, degrees. */
|
||||
public var Coneangle:Number = 45;
|
||||
/** Inner cone, degrees. Blender does not write this value (hence -1 default). */
|
||||
public var HotSpot:Number = -1;
|
||||
|
||||
/** 0 point, 1 directional, 2 spot, 3 blender hemi (?.. investigating), -1 ambient */
|
||||
public var LightType:Number = -1;
|
||||
|
||||
/** 0 none, 1 linear, 2 quadratic, 3 cubic */
|
||||
public var DecayType:Number = 0;
|
||||
public var DecayStart:Number = 50;
|
||||
|
||||
/* not supported by alternativa
|
||||
// public var EnableNearAttenuation:Number = 0;
|
||||
public var NearAttenuationStart:Number = 0;
|
||||
public var NearAttenuationEnd:Number = 0; */
|
||||
|
||||
// public var EnableFarAttenuation:Number = 0;
|
||||
public var FarAttenuationStart:Number = 0;
|
||||
public var FarAttenuationEnd:Number = 0;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private SDK: A mesh is a geometry made of polygons.
|
||||
* The class can define a geometry with as many n-sided polygons as needed. Users can freely mix triangles, quadrilaterals, and other polygons. Since the mesh-related terminology of the FBX SDK differs a little from the known standards, here are our definitions:
|
||||
* A control point is an XYZ coordinate, it is synonym of vertex.
|
||||
* A polygon vertex is an index to a control point (the same control point can be referenced by multiple polygon vertices).
|
||||
* A polygon is a group of polygon vertices. The minimum valid number of polygon vertices to define a polygon is 3.
|
||||
*/
|
||||
public class KFbxMesh extends KFbxGeometry {
|
||||
/*
|
||||
00955 public:
|
||||
00956 //Please use GetPolygonVertexIndex and GetPolygonVertices to access these arrays.
|
||||
00957 //DO NOT MODIFY them directly, otherwise unexpected behavior will occur.
|
||||
00958 //These members are public only for application data copy performance reasons.
|
||||
00959 struct KFbxPolygon{ int mIndex; int mSize; int mGroup; };
|
||||
00960 KArrayTemplate<KFbxPolygon> mPolygons;
|
||||
00961 KArrayTemplate<int> mPolygonVertices;
|
||||
*/
|
||||
|
||||
/**
|
||||
* mPolygonVertices.
|
||||
* В файле: "PolygonVertexIndex"
|
||||
* Пример: 0,3,2,-2,3,7,6,-3,0,4,7...
|
||||
* отрицательные числа = последняя вершина полика XOR -1 (X XOR -1 = -X -1)
|
||||
*/
|
||||
public var PolygonVertexIndex:Vector.<Number> = new Vector.<Number>();
|
||||
}
|
||||
}
|
||||
@@ -1,226 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
import flash.geom.Matrix3D;
|
||||
import flash.geom.Vector3D;
|
||||
|
||||
/**
|
||||
* @private SDK: Represents an element in the scene graph.
|
||||
*/
|
||||
public class KFbxNode {
|
||||
public var LclTranslation:Vector.<Number> = Vector.<Number>([0, 0, 0]);
|
||||
public var LclRotation:Vector.<Number> = Vector.<Number>([0, 0, 0]);
|
||||
public var LclScaling:Vector.<Number> = Vector.<Number>([1, 1, 1]);
|
||||
public var RotationOffset:Vector.<Number> = Vector.<Number>([0, 0, 0]);
|
||||
public var RotationPivot:Vector.<Number> = Vector.<Number>([0, 0, 0]);
|
||||
public var PreRotation:Vector.<Number> = Vector.<Number>([0, 0, 0]);
|
||||
public var PostRotation:Vector.<Number> = Vector.<Number>([0, 0, 0]);
|
||||
public var ScalingOffset:Vector.<Number> = Vector.<Number>([0, 0, 0]);
|
||||
public var ScalingPivot:Vector.<Number> = Vector.<Number>([0, 0, 0]);
|
||||
public var GeometricTranslation:Vector.<Number> = Vector.<Number>([0, 0, 0]);
|
||||
public var GeometricRotation:Vector.<Number> = Vector.<Number>([0, 0, 0]);
|
||||
public var GeometricScaling:Vector.<Number> = Vector.<Number>([1, 1, 1]);
|
||||
|
||||
public function transformationClone():KFbxNode {
|
||||
var tmp:KFbxNode = new KFbxNode;
|
||||
tmp.LclTranslation = LclTranslation.slice();
|
||||
tmp.LclRotation = LclRotation.slice();
|
||||
tmp.LclScaling = LclScaling.slice();
|
||||
tmp.RotationOffset = RotationOffset.slice();
|
||||
tmp.RotationPivot = RotationPivot.slice();
|
||||
tmp.PreRotation = PreRotation.slice();
|
||||
tmp.PostRotation = PostRotation.slice();
|
||||
tmp.ScalingOffset = ScalingOffset.slice();
|
||||
tmp.ScalingPivot = ScalingPivot.slice();
|
||||
tmp.GeometricTranslation = GeometricTranslation.slice();
|
||||
tmp.GeometricRotation = GeometricRotation.slice();
|
||||
tmp.GeometricScaling = GeometricScaling.slice();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Собирает матрицу трансформации. Из доки СДК:
|
||||
*
|
||||
* Each pivot context stores values (as KFbxVector4) for:
|
||||
* - Rotation offset (Roff)
|
||||
* - Rotation pivot (Rp)
|
||||
* - Pre-rotation (Rpre)
|
||||
* - Post-rotation (Rpost)
|
||||
* - Scaling offset (Soff)
|
||||
* - Scaling pivot (Sp)
|
||||
* - Geometric translation (Gt)
|
||||
* - Geometric rotation (Gr)
|
||||
* - Geometric scaling (Gs)
|
||||
*
|
||||
* These values combine in the matrix form to compute the World transform of the node
|
||||
* using the formula:
|
||||
*
|
||||
* World = ParentWorld * T * Roff * Rp * Rpre * R * Rpost * Rp-1 * Soff * Sp * S * Sp-1
|
||||
*/
|
||||
public function calculateNodeTransformation():Matrix3D {
|
||||
var extraPostRotation:Number = 0;
|
||||
if (getAttribute(KFbxLight)) {
|
||||
// By default, a KFbxNode uses its positive X axis as the aiming constraint. Recall that
|
||||
// a newly created light points along the node's negative Y axis by default. To make the
|
||||
// light point along the node's positive X axis, a rotation offset of 90 degrees must be
|
||||
// applied to the light's node using KFbxNode::SetPostTargetRotation().
|
||||
extraPostRotation = 90;
|
||||
}
|
||||
|
||||
var T:Matrix3D = new Matrix3D;
|
||||
T.prependTranslation(LclTranslation [0], LclTranslation [1], LclTranslation [2]);
|
||||
// rotation offset
|
||||
T.prependTranslation(RotationOffset [0], RotationOffset [1], RotationOffset [2]);
|
||||
// rotaton pivot
|
||||
var Rp:Matrix3D = new Matrix3D;
|
||||
Rp.prependTranslation(RotationPivot [0], RotationPivot [1], RotationPivot [2]);
|
||||
T.prepend(Rp);
|
||||
// prerotation
|
||||
T.prepend(makeRotationMatrix(PreRotation [0], PreRotation [1], PreRotation [2]));
|
||||
// rotation
|
||||
T.prepend(makeRotationMatrix(LclRotation [0], LclRotation [1], LclRotation [2]));
|
||||
// postrotation
|
||||
T.prepend(makeRotationMatrix(PostRotation [0] - extraPostRotation, PostRotation [1], PostRotation [2]));
|
||||
// inv. rotation pivot
|
||||
Rp.invert();
|
||||
T.prepend(Rp);
|
||||
// scaling offset
|
||||
T.prependTranslation(ScalingOffset [0], ScalingOffset [1], ScalingOffset [2]);
|
||||
// scaling pivot
|
||||
var Sp:Matrix3D = new Matrix3D;
|
||||
Sp.prependTranslation(ScalingPivot [0], ScalingPivot [1], ScalingPivot [2]);
|
||||
T.prepend(Sp);
|
||||
// scaling
|
||||
T.prependScale(LclScaling [0], LclScaling [1], LclScaling [2]);
|
||||
// inv. scaling pivot
|
||||
Sp.invert();
|
||||
T.prepend(Sp);
|
||||
|
||||
return T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Если возвращает ненулевое преобразование, аттрибуты должны быть по-любому добавлены
|
||||
* как дочерние объекты к данной ноде.
|
||||
*
|
||||
* The geometric transformation (Gt * Gr * Gs) is applied only to the node attribute
|
||||
* and after the node transformations. This transformation is not inherited across the
|
||||
* node hierarchy.
|
||||
*
|
||||
* Gt * Gr * Gs вроде как используется только 3DMax-ом в редких случаях:
|
||||
* @see http://download.autodesk.com/global/docs/fbxsdk2012/en_us/files/GUID-10CDD63C-79C1-4F2D-BB28-AD2BE65A02E-50.htm
|
||||
*/
|
||||
public function calculateAttributesTransformation():Matrix3D {
|
||||
var hasAttrTransform:Boolean;
|
||||
for (var i:int = 0; i < 3; i++) {
|
||||
hasAttrTransform ||= (GeometricTranslation [i] != 0);
|
||||
hasAttrTransform ||= (GeometricRotation [i] != 0);
|
||||
hasAttrTransform ||= (GeometricScaling [i] != 1);
|
||||
}
|
||||
|
||||
if (hasAttrTransform) {
|
||||
// shit :(
|
||||
var G:Matrix3D = new Matrix3D;
|
||||
G.prependTranslation(GeometricTranslation [0], GeometricTranslation [1], GeometricTranslation [2]);
|
||||
G.prepend(makeRotationMatrix(GeometricRotation [0], GeometricRotation [1], GeometricRotation [2]));
|
||||
G.prependScale(GeometricScaling [0], GeometricScaling [1], GeometricScaling [2]);
|
||||
return G;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* typedef enum
|
||||
* {
|
||||
* eEULER_XYZ = 0,
|
||||
* eEULER_XZY,
|
||||
* eEULER_YZX,
|
||||
* eEULER_YXZ,
|
||||
* eEULER_ZXY,
|
||||
* eEULER_ZYX,
|
||||
* eSPHERIC_XYZ // WTF??
|
||||
* } ERotationOrder;
|
||||
*/
|
||||
public var RotationOrder:int = 0;
|
||||
private const eEULER_XYZ:int = 0;
|
||||
private const eEULER_XZY:int = 1;
|
||||
private const eEULER_YZX:int = 2;
|
||||
private const eEULER_YXZ:int = 3;
|
||||
private const eEULER_ZXY:int = 4;
|
||||
private const eEULER_ZYX:int = 5;
|
||||
|
||||
/**
|
||||
* The R matrix takes into account the rotation order. Because of the mathematical
|
||||
* properties of the matrices, R is the result of one of the possible combinations
|
||||
* of Ry, Ry and Rz (each being matrices also). For example, for the default rotation
|
||||
* order of XYZ, R = Rx * Ry * Rz
|
||||
*/
|
||||
private function makeRotationMatrix(rx:Number, ry:Number, rz:Number):Matrix3D {
|
||||
var R:Matrix3D = new Matrix3D;
|
||||
switch (RotationOrder) {
|
||||
case eEULER_XZY:
|
||||
R.appendRotation(rx, Vector3D.X_AXIS);
|
||||
R.appendRotation(rz, Vector3D.Z_AXIS);
|
||||
R.appendRotation(ry, Vector3D.Y_AXIS);
|
||||
break;
|
||||
|
||||
case eEULER_YZX:
|
||||
R.appendRotation(ry, Vector3D.Y_AXIS);
|
||||
R.appendRotation(rz, Vector3D.Z_AXIS);
|
||||
R.appendRotation(rx, Vector3D.X_AXIS);
|
||||
break;
|
||||
|
||||
case eEULER_YXZ:
|
||||
R.appendRotation(ry, Vector3D.Y_AXIS);
|
||||
R.appendRotation(rx, Vector3D.X_AXIS);
|
||||
R.appendRotation(rz, Vector3D.Z_AXIS);
|
||||
break;
|
||||
|
||||
case eEULER_ZXY:
|
||||
R.appendRotation(rz, Vector3D.Z_AXIS);
|
||||
R.appendRotation(rx, Vector3D.X_AXIS);
|
||||
R.appendRotation(ry, Vector3D.Y_AXIS);
|
||||
break;
|
||||
|
||||
case eEULER_ZYX:
|
||||
R.appendRotation(rz, Vector3D.Z_AXIS);
|
||||
R.appendRotation(ry, Vector3D.Y_AXIS);
|
||||
R.appendRotation(rx, Vector3D.X_AXIS);
|
||||
break;
|
||||
|
||||
case eEULER_XYZ:
|
||||
default:
|
||||
R.appendRotation(rx, Vector3D.X_AXIS);
|
||||
R.appendRotation(ry, Vector3D.Y_AXIS);
|
||||
R.appendRotation(rz, Vector3D.Z_AXIS);
|
||||
break;
|
||||
}
|
||||
return R;
|
||||
}
|
||||
|
||||
public var parent:KFbxNode;
|
||||
public var Children:Vector.<String> = new Vector.<String>();//* for V5 only */
|
||||
|
||||
public var attributes:Vector.<KFbxNodeAttribute> = new Vector.<KFbxNodeAttribute>();
|
||||
|
||||
public var materials:Vector.<KFbxSurfaceMaterial> = new Vector.<KFbxSurfaceMaterial>();
|
||||
public var textures:Vector.<KFbxTexture> = new Vector.<KFbxTexture>();
|
||||
|
||||
public var Visibility:Number = 1;
|
||||
|
||||
public function isVisible():Boolean {
|
||||
return (Visibility == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Судя по методам в СДК, аттрибутов может быть много, но по одному одного типа.
|
||||
*/
|
||||
public function getAttribute(type:Class):KFbxNodeAttribute {
|
||||
for (var i:int = 0; i < attributes.length; i++) {
|
||||
var a:KFbxNodeAttribute = attributes [i];
|
||||
if (a is type) return a;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private SDK: This class is the base class to all types of node attributes.
|
||||
*/
|
||||
public class KFbxNodeAttribute {
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private SDK: a node attribute to represent the elements forming "bone" chains.
|
||||
*/
|
||||
public class KFbxSkeleton extends KFbxNodeAttribute {
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private SDK: FBX SDK skin class.
|
||||
*/
|
||||
public class KFbxSkin extends KFbxDeformer {
|
||||
public var clusters:Vector.<KFbxCluster> = new Vector.<KFbxCluster>();
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
/**
|
||||
* @private SDK: This class contains material settings.
|
||||
*/
|
||||
public dynamic class KFbxSurfaceMaterial {
|
||||
/*
|
||||
// v6 properties
|
||||
public var ShadingModel:String = "Phong";
|
||||
public var EmissiveColor:Vector.<Number> = new <Number> [0, 0, 0];
|
||||
public var EmissiveFactor:Number = 1;
|
||||
public var AmbientColor:Vector.<Number> = new <Number> [0, 0, 0];
|
||||
public var AmbientFactor:Number = 1;
|
||||
public var DiffuseColor:Vector.<Number> = new <Number> [0, 0, 0];
|
||||
public var DiffuseFactor:Number = 1;
|
||||
public var Bump:Vector.<Number> = new <Number> [0, 0, 0];
|
||||
public var TransparentColor:Vector.<Number> = new <Number> [0, 0, 0];
|
||||
public var TransparencyFactor:Number = 1;
|
||||
public var SpecularColor:Vector.<Number> = new <Number> [0, 0, 0];
|
||||
public var SpecularFactor:Number = 1;
|
||||
public var ShininessExponent:Number = 1;
|
||||
public var ReflectionColor:Vector.<Number> = new <Number> [0, 0, 0];
|
||||
public var ReflectionFactor:Number = 1;
|
||||
public var Emissive:Vector.<Number> = new <Number> [0, 0, 0];
|
||||
public var Ambient:Vector.<Number> = new <Number> [0, 0, 0];
|
||||
public var Diffuse:Vector.<Number> = new <Number> [0, 0, 0];
|
||||
public var Specular:Vector.<Number> = new <Number> [0, 0, 0];
|
||||
public var Shininess:Number = 1;
|
||||
public var Opacity:Number = 1;
|
||||
public var Reflectivity:Number = 1;
|
||||
// v7 properties
|
||||
public var NormalMap:Vector.<Number> = new <Number> [0, 0, 0];
|
||||
public var BumpFactor:Number = 1;
|
||||
public var DisplacementColor:Vector.<Number> = new <Number> [0, 0, 0];
|
||||
public var DisplacementFactor:Number = 1;
|
||||
public var VectorDisplacementColor:Vector.<Number> = new <Number> [0, 0, 0];
|
||||
public var VectorDisplacementFactor:Number = 1;
|
||||
*/
|
||||
public function KFbxSurfaceMaterial() {
|
||||
// vars dynamic vars so that for (var property:String in this) could work
|
||||
// copy through byte array: ba.readObject() wastes memory
|
||||
// manual prop-after-prop copying: spagetti code, could miss new props if any
|
||||
// describeType: could be an option..
|
||||
|
||||
// v6 properties
|
||||
this.ShadingModel = "Phong";
|
||||
this.EmissiveColor = Vector.<Number>([0, 0, 0]);
|
||||
this.EmissiveFactor = 1;
|
||||
this.AmbientColor = Vector.<Number>([0, 0, 0]);
|
||||
this.AmbientFactor = 1;
|
||||
this.DiffuseColor = Vector.<Number>([0, 0, 0]);
|
||||
this.DiffuseFactor = 1;
|
||||
this.Bump = Vector.<Number>([0, 0, 0]);
|
||||
this.TransparentColor = Vector.<Number>([0, 0, 0]);
|
||||
this.TransparencyFactor = 1;
|
||||
this.SpecularColor = Vector.<Number>([0, 0, 0]);
|
||||
this.SpecularFactor = 1;
|
||||
this.ShininessExponent = 1;
|
||||
this.ReflectionColor = Vector.<Number>([0, 0, 0]);
|
||||
this.ReflectionFactor = 1;
|
||||
this.Emissive = Vector.<Number>([0, 0, 0]);
|
||||
this.Ambient = Vector.<Number>([0, 0, 0]);
|
||||
this.Diffuse = Vector.<Number>([0, 0, 0]);
|
||||
this.Specular = Vector.<Number>([0, 0, 0]);
|
||||
this.Shininess = 1;
|
||||
this.Opacity = 1;
|
||||
this.Reflectivity = 1;
|
||||
// v7 properties
|
||||
this.NormalMap = Vector.<Number>([0, 0, 0]);
|
||||
this.BumpFactor = 1;
|
||||
this.DisplacementColor = Vector.<Number>([0, 0, 0]);
|
||||
this.DisplacementFactor = 1;
|
||||
this.VectorDisplacementColor = Vector.<Number>([0, 0, 0]);
|
||||
this.VectorDisplacementFactor = 1;
|
||||
}
|
||||
|
||||
// node pointer for v7 to propagate textures up to node
|
||||
public var node:KFbxNode;
|
||||
|
||||
// textures
|
||||
public var textures:Object = {};
|
||||
|
||||
public function copyTo(dest:KFbxSurfaceMaterial):void {
|
||||
// shallow copy dynamic properties
|
||||
for (var property:String in dest) dest [property] = this [property];
|
||||
// and textures
|
||||
for (var channel:String in textures) dest.textures [channel] = this.textures [channel];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox {
|
||||
|
||||
import flash.geom.Matrix;
|
||||
import flash.geom.Matrix3D;
|
||||
import flash.geom.Vector3D;
|
||||
|
||||
/**
|
||||
* @private SDK: This class is the base class for textures,
|
||||
* ie classes KFbxFileTexture, KFbxLayeredTexture and KFbxProceduralTexture.
|
||||
*/
|
||||
public class KFbxTexture {
|
||||
|
||||
public var RelativeFilename:String = "";
|
||||
/* these aren't actually set by 3dmax?
|
||||
public var ModelUVTranslation:Vector.<Number> = new <Number> [0, 0];
|
||||
public var ModelUVScaling:Vector.<Number> = new <Number> [1, 1];
|
||||
*/
|
||||
public var Translation:Vector.<Number> = Vector.<Number>([0, 0, 0]);
|
||||
public var Rotation:Vector.<Number> = Vector.<Number>([0, 0, 0]);
|
||||
public var Scaling:Vector.<Number> = Vector.<Number>([1, 1, 1]);
|
||||
public var TextureRotationPivot:Vector.<Number> = Vector.<Number>([0, 0, 0]);
|
||||
public var TextureScalingPivot:Vector.<Number> = Vector.<Number>([0, 0, 0]);
|
||||
|
||||
public var transformation:Matrix;
|
||||
|
||||
public function calculateTextureTransformation():Matrix {
|
||||
// guesswork by analogy to KFbxNode formula
|
||||
var T:Matrix3D = new Matrix3D;
|
||||
T.prependTranslation(Translation [0], Translation [1], Translation [2]);
|
||||
// rotaton pivot
|
||||
var Rp:Matrix3D = new Matrix3D;
|
||||
Rp.prependTranslation(TextureRotationPivot [0], TextureRotationPivot [1], TextureRotationPivot [2]);
|
||||
T.prepend(Rp);
|
||||
// rotation
|
||||
T.prepend(makeRotationMatrix(Rotation [0], Rotation [1], Rotation [2]));
|
||||
// inv. rotation pivot
|
||||
Rp.invert();
|
||||
T.prepend(Rp);
|
||||
// scaling pivot
|
||||
var Sp:Matrix3D = new Matrix3D;
|
||||
Sp.prependTranslation(TextureScalingPivot [0], TextureScalingPivot [1], TextureScalingPivot [2]);
|
||||
T.prepend(Sp);
|
||||
// scaling
|
||||
T.prependScale(Scaling [0], Scaling [1], Scaling [2]);
|
||||
// inv. scaling pivot
|
||||
Sp.invert();
|
||||
T.prepend(Sp);
|
||||
|
||||
// sample transform at W = 0
|
||||
var raw:Vector.<Number> = T.rawData;
|
||||
transformation = new Matrix(raw [0], raw [1], raw [4], raw [5], raw [3], raw [7]);
|
||||
|
||||
return transformation;
|
||||
}
|
||||
|
||||
private function makeRotationMatrix(rx:Number, ry:Number, rz:Number):Matrix3D {
|
||||
var R:Matrix3D = new Matrix3D;
|
||||
R.prependRotation(rx, Vector3D.X_AXIS);
|
||||
R.prependRotation(ry, Vector3D.Y_AXIS);
|
||||
R.prependRotation(rz, Vector3D.Z_AXIS);
|
||||
return R;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox.readers {
|
||||
|
||||
/** @private Прокладка для чтения файла. */
|
||||
public interface IReader {
|
||||
function hasDataLeft():Boolean;
|
||||
|
||||
function getDepth():uint;
|
||||
|
||||
function getRecordName():String;
|
||||
|
||||
function getRecordData(parseNumbers:Boolean = true):RecordData;
|
||||
|
||||
function stepIn():void;
|
||||
|
||||
function stepOver():void;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox.readers {
|
||||
|
||||
|
||||
/** @private */
|
||||
public class ReaderBinary implements IReader {
|
||||
|
||||
public function hasDataLeft():Boolean {
|
||||
trace("binary reader not implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getDepth():uint {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getRecordName():String {
|
||||
return "";
|
||||
}
|
||||
|
||||
public function getRecordData(parseNumbers:Boolean = true):RecordData {
|
||||
return new RecordData;
|
||||
}
|
||||
|
||||
public function stepIn():void {
|
||||
;
|
||||
}
|
||||
|
||||
public function stepOver():void {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox.readers {
|
||||
|
||||
import flash.utils.ByteArray;
|
||||
|
||||
// import flash.utils.getTimer;
|
||||
|
||||
/** @private */
|
||||
public class ReaderText implements IReader {
|
||||
|
||||
private var lines:Vector.<String>, currentLine:int = 0, nextLineHint:int = -1;
|
||||
|
||||
public function ReaderText(ba:ByteArray):void {
|
||||
var text:String = ba.toString(); // ba.readUTFBytes (ba.bytesAvailable);
|
||||
|
||||
var crat:int = text.indexOf("\n");
|
||||
var eol:String = ((crat > 0) && (text.charAt(crat - 1) == "\r")) ? "\r\n" : "\n";
|
||||
|
||||
lines = Vector.<String>(text.split(eol));
|
||||
}
|
||||
|
||||
public function hasDataLeft():Boolean {
|
||||
if (currentLine < nextLineHint) {
|
||||
currentLine = nextLineHint;
|
||||
}
|
||||
|
||||
while (currentLine < lines.length) {
|
||||
var line:String = lines [currentLine];
|
||||
if (line.indexOf(": ") > -1) return true;
|
||||
// can't have "{" here
|
||||
if (line.indexOf("}") > -1) depth--;
|
||||
currentLine++;
|
||||
}
|
||||
return (currentLine < lines.length);
|
||||
}
|
||||
|
||||
private var depth:uint = 0;
|
||||
|
||||
public function getDepth():uint {
|
||||
return depth;
|
||||
}
|
||||
|
||||
public function getRecordName():String {
|
||||
var line:String = lines [currentLine];
|
||||
var name:String = line.substr(0, line.indexOf(":"));
|
||||
var last:int = name.lastIndexOf(" ") + 1;
|
||||
if (last > 0) {
|
||||
name = name.substr(last);
|
||||
} else {
|
||||
last = name.lastIndexOf("\t") + 1;
|
||||
if (last > 0) {
|
||||
name = name.substr(last);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public function getRecordData(parseNumbers:Boolean = true):RecordData {
|
||||
//var t:int = getTimer ();
|
||||
var data:RecordData = new RecordData;
|
||||
|
||||
var text:String = "";
|
||||
|
||||
// 1st bit of data starts at currentLine after ": "
|
||||
var line:String = lines [currentLine];
|
||||
line = line.substr(line.indexOf(": ") + 1);
|
||||
|
||||
var c:int = currentLine + 1;
|
||||
while ((line.indexOf(": ") < 0) && (line.indexOf("}") < 0) && (line.indexOf("{") < 0)) {
|
||||
// additional check for comments
|
||||
var s:int = line.indexOf(";");
|
||||
if (s >= 0) {
|
||||
for (var i:int = 0; i < s; i++) {
|
||||
if (line.charCodeAt(i) > 32) {
|
||||
s = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s < 0) {
|
||||
text += line;
|
||||
}
|
||||
line = lines [c];
|
||||
c++;
|
||||
}
|
||||
|
||||
// now line is either last one, or irrelevant one
|
||||
nextLineHint = c - 2;
|
||||
if ((line.indexOf(": ") < 0) && (line.indexOf("}") < 0)) {
|
||||
line = line.substr(0, line.indexOf("{"));
|
||||
text += line;
|
||||
}
|
||||
|
||||
// split text
|
||||
var items:Array = text.split(",");
|
||||
|
||||
//var profile:Boolean = (items.length > 10);
|
||||
//if (profile) {
|
||||
// trace ("----->", items.length, "data items over", (c - currentLine), "lines");
|
||||
// trace ("@", lines [currentLine].substr (0, 50));
|
||||
//}
|
||||
|
||||
var isNumber:Boolean, n:int = items.length;
|
||||
for (i = 0; i < n; i++) {
|
||||
var item:String = items [i] as String;
|
||||
|
||||
// trim heading whitespace
|
||||
s = 0;
|
||||
while (item.charCodeAt(s) < 33) s++;
|
||||
if (s > 0) item = item.substr(s);
|
||||
|
||||
// number ?
|
||||
if (!isNumber) {
|
||||
s = item.charCodeAt(0);
|
||||
if (parseNumbers) isNumber = (s == 0x2D) || ((0x2F < s) && (s < 0x3A));
|
||||
}
|
||||
|
||||
if (isNumber) {
|
||||
data.numbers.push(parseFloat(item));
|
||||
} else {
|
||||
var quotes:Boolean = (s == 0x22);
|
||||
|
||||
// trim trailing whitespace
|
||||
s = item.length;
|
||||
while (item.charCodeAt(s - 1) < 33) s--;
|
||||
if (s < item.length) item = item.substr(0, s);
|
||||
|
||||
if (quotes) {
|
||||
// strip quotes
|
||||
data.strings.push(item.substr(1, item.length - 2));
|
||||
} else if (item.length > 0) {
|
||||
data.strings.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if (profile) trace (1e-3 * (getTimer () - t), "wasted in getRecordData()");
|
||||
|
||||
if ((data.numbers.length == 0) && (data.strings.length == 1) && (data.strings [0].charCodeAt(0) == 0x2A)) {
|
||||
// v7 arrays shortcut
|
||||
c = currentLine;
|
||||
i = nextLineHint;
|
||||
s = depth;
|
||||
stepIn();
|
||||
hasDataLeft();
|
||||
data = getRecordData();
|
||||
currentLine = c;
|
||||
nextLineHint = i;
|
||||
depth = s;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public function stepIn():void {
|
||||
currentLine++;
|
||||
depth++;
|
||||
}
|
||||
|
||||
public function stepOver():void {
|
||||
var par:int = 0;
|
||||
do {
|
||||
var line:String = lines [currentLine];
|
||||
if (line.indexOf("{") >= 0) par++; else if (line.indexOf("}") >= 0) par--;
|
||||
currentLine++;
|
||||
} while (par > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox.readers {
|
||||
|
||||
/** @private Большинство данных в filmbox представимо в этом виде. */
|
||||
public class RecordData {
|
||||
public var strings:Vector.<String> = new Vector.<String>();
|
||||
public var numbers:Vector.<Number> = new Vector.<Number>();
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox.versions {
|
||||
|
||||
import alternativa.engine3d.loaders.filmbox.readers.IReader;
|
||||
|
||||
/** @private Прокладка для интерпретации содержимого файла. TODO better separation! */
|
||||
public interface IVersion {
|
||||
function parseCurrentRecord(reader:IReader, stack:Array, heap:Object):void;
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox.versions {
|
||||
|
||||
import alternativa.engine3d.loaders.filmbox.*;
|
||||
import alternativa.engine3d.loaders.filmbox.readers.*;
|
||||
|
||||
/** @private */
|
||||
public class V5 extends VCommon implements IVersion {
|
||||
public function parseCurrentRecord(reader:IReader, stack:Array, heap:Object):void {
|
||||
|
||||
var data:RecordData, node:KFbxNode, object:Object;
|
||||
|
||||
var recordName:String = reader.getRecordName();
|
||||
switch (recordName) {
|
||||
case "AmbientRenderSettings":
|
||||
stack.push(null);
|
||||
reader.stepIn();
|
||||
break;
|
||||
|
||||
case "AmbientLightColor":
|
||||
parseAmbientLight(reader.getRecordData(), heap);
|
||||
reader.stepOver();
|
||||
break;
|
||||
// 3D объекты
|
||||
case "Model":
|
||||
data = reader.getRecordData();
|
||||
parseModelRecord(data, stack, heap);
|
||||
reader.stepIn();
|
||||
break;
|
||||
// разная хрень из Mesh
|
||||
case "Vertices":
|
||||
case "PolygonVertexIndex":
|
||||
setMeshNumericProperty(reader, stack, recordName);
|
||||
reader.stepOver();
|
||||
break;
|
||||
case "Normals":
|
||||
addMeshLayerElement(null, stack, new KFbxLayerElementNormal(reader.getRecordData().numbers), 0,
|
||||
false);
|
||||
reader.stepOver();
|
||||
break;
|
||||
case "Meterials":
|
||||
addMeshLayerElement(null, stack, new KFbxLayerElementMaterial(reader.getRecordData().numbers), 0,
|
||||
false);
|
||||
reader.stepOver();
|
||||
break;
|
||||
case "TextureId":
|
||||
addMeshLayerElement(null, stack,
|
||||
new KFbxLayerElementTexture("diffuse", reader.getRecordData().numbers), 0, false);
|
||||
reader.stepOver();
|
||||
break;
|
||||
case "GeometryUVInfo":
|
||||
addMeshLayerElement(null, stack, new KFbxLayerElementUV, 0);
|
||||
reader.stepIn();
|
||||
break;
|
||||
// поля слоёв
|
||||
case "TextureUV":
|
||||
setPredefinedProperty(reader, stack, "UV");
|
||||
reader.stepOver();
|
||||
break;
|
||||
case "TextureUVVerticeIndex":
|
||||
setPredefinedProperty(reader, stack, "UVIndex");
|
||||
reader.stepOver();
|
||||
break;
|
||||
// поля текстур
|
||||
case "Media":
|
||||
setPredefinedProperty(reader, stack, "RelativeFilename");
|
||||
reader.stepOver();
|
||||
break;
|
||||
case "ModelUVTranslation":
|
||||
case "ModelUVScaling":
|
||||
// иерархия по версии 5
|
||||
case "Children":
|
||||
setPredefinedProperty(reader, stack, recordName);
|
||||
reader.stepOver();
|
||||
break;
|
||||
case "Material":
|
||||
node = stack [stack.length - 1] as KFbxNode;
|
||||
node.materials.push(object = new KFbxSurfaceMaterial);
|
||||
stack.push(object);
|
||||
reader.stepIn();
|
||||
break;
|
||||
case "Texture":
|
||||
node = stack [stack.length - 1] as KFbxNode;
|
||||
node.textures.push(object = new KFbxTexture);
|
||||
stack.push(object);
|
||||
reader.stepIn();
|
||||
break;
|
||||
case "Takes":
|
||||
// all nodes were parsed by now
|
||||
buildHierarchy(heap);
|
||||
reader.stepOver();
|
||||
break;
|
||||
default:
|
||||
reader.stepOver();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private function parseModelRecord(data:RecordData, stack:Array, heap:Object):void {
|
||||
var node:KFbxNode = new KFbxNode;
|
||||
// can't determine attribute yet :(
|
||||
stack.push(heap[data.strings[0]] = node);
|
||||
}
|
||||
|
||||
private function buildHierarchy(heap:Object):void {
|
||||
for (var key:String in heap) {
|
||||
var node:KFbxNode = heap [key] as KFbxNode;
|
||||
if (node) {
|
||||
for (var i:int = 0; i < node.Children.length; i++) {
|
||||
var child:KFbxNode = heap [node.Children [i]] as KFbxNode;
|
||||
if (child) {
|
||||
child.parent = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,359 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox.versions {
|
||||
|
||||
import alternativa.engine3d.loaders.filmbox.*;
|
||||
import alternativa.engine3d.loaders.filmbox.readers.*;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @see http://paulbourke.net/dataformats/fbx/fbx.pdf ?
|
||||
*/
|
||||
public class V6 extends VCommon implements IVersion {
|
||||
public function parseCurrentRecord(reader:IReader, stack:Array, heap:Object):void {
|
||||
|
||||
var data:RecordData;
|
||||
|
||||
var recordName:String = reader.getRecordName();
|
||||
switch (recordName) {
|
||||
// верхний уровень, Prop60
|
||||
case "Objects":
|
||||
case "Connections":
|
||||
case "Takes":
|
||||
case "Properties60":
|
||||
case "Version5":
|
||||
case "AmbientRenderSettings":
|
||||
stack.push(null);
|
||||
reader.stepIn();
|
||||
break;
|
||||
|
||||
case "AmbientLightColor":
|
||||
parseAmbientLight(reader.getRecordData(), heap);
|
||||
reader.stepOver();
|
||||
break;
|
||||
|
||||
// 3D объекты
|
||||
case "Model":
|
||||
data = reader.getRecordData();
|
||||
switch (data.strings.length) {
|
||||
case 2:
|
||||
// свойства объектов
|
||||
parseModelRecord(data, stack, heap);
|
||||
reader.stepIn();
|
||||
break;
|
||||
case 1:
|
||||
// анимация объектов
|
||||
parseAnimationLayer(data, stack, heap);
|
||||
reader.stepIn();
|
||||
break;
|
||||
default:
|
||||
// не должно бы, на всякий случай
|
||||
reader.stepOver();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case "Deformer":
|
||||
data = reader.getRecordData();
|
||||
switch (data.strings [1]) {
|
||||
case "Cluster":
|
||||
stack.push(heap [data.strings [0]] = new KFbxCluster);
|
||||
reader.stepIn();
|
||||
break;
|
||||
case "Skin":
|
||||
heap [data.strings [0]] = new KFbxSkin;
|
||||
reader.stepOver();
|
||||
break;
|
||||
default:
|
||||
reader.stepOver();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// разная хрень из Mesh
|
||||
case "Vertices":
|
||||
case "PolygonVertexIndex":
|
||||
setMeshNumericProperty(reader, stack, recordName);
|
||||
reader.stepOver();
|
||||
break;
|
||||
case "LayerElementMaterial":
|
||||
addMeshLayerElement(reader, stack, new KFbxLayerElementMaterial);
|
||||
reader.stepIn();
|
||||
break;
|
||||
case "LayerElementTexture":
|
||||
addMeshLayerElement(reader, stack, new KFbxLayerElementTexture);
|
||||
reader.stepIn();
|
||||
break;
|
||||
case "LayerElementSpecularTextures":
|
||||
addMeshLayerElement(reader, stack, new KFbxLayerElementTexture("specular"));
|
||||
reader.stepIn();
|
||||
break;
|
||||
case "LayerElementBumpTextures":
|
||||
addMeshLayerElement(reader, stack, new KFbxLayerElementTexture("bump"));
|
||||
reader.stepIn();
|
||||
break;
|
||||
case "LayerElementUV":
|
||||
addMeshLayerElement(reader, stack, new KFbxLayerElementUV);
|
||||
reader.stepIn();
|
||||
break;
|
||||
/*
|
||||
case "LayerElementSpecularUV":
|
||||
case "LayerElementBumpUV":
|
||||
multiple UVs per vertex aren't supported
|
||||
*/
|
||||
case "LayerElementNormal":
|
||||
addMeshLayerElement(reader, stack, new KFbxLayerElementNormal);
|
||||
reader.stepIn();
|
||||
break;
|
||||
|
||||
|
||||
// поля слоёв
|
||||
case "MappingInformationType":
|
||||
case "ReferenceInformationType":
|
||||
case "Normals":
|
||||
case "Materials":
|
||||
case "TextureId":
|
||||
case "UV":
|
||||
case "UVIndex":
|
||||
// поля текстур
|
||||
case "RelativeFilename":
|
||||
case "ModelUVTranslation":
|
||||
case "ModelUVScaling":
|
||||
// поля кластеров
|
||||
case "Indexes":
|
||||
case "Weights":
|
||||
case "Transform":
|
||||
case "TransformLink":
|
||||
setPredefinedProperty(reader, stack, recordName);
|
||||
reader.stepOver();
|
||||
break;
|
||||
|
||||
case "Material":
|
||||
data = reader.getRecordData();
|
||||
stack.push(heap [data.strings [0]] = new KFbxSurfaceMaterial);
|
||||
reader.stepIn();
|
||||
break;
|
||||
|
||||
case "Texture":
|
||||
data = reader.getRecordData();
|
||||
stack.push(heap [data.strings [0]] = new KFbxTexture);
|
||||
reader.stepIn();
|
||||
break;
|
||||
|
||||
|
||||
// свойства
|
||||
case "Property":
|
||||
// someSpecialCase () ||
|
||||
setProperty(reader, stack, 3);
|
||||
reader.stepOver();
|
||||
break;
|
||||
|
||||
|
||||
case "Connect":
|
||||
parseConnection(reader.getRecordData(), heap);
|
||||
reader.stepOver();
|
||||
break;
|
||||
|
||||
|
||||
case "Take":
|
||||
data = reader.getRecordData();
|
||||
stack.push(heap [data.strings [0]] = new KFbxAnimStack);
|
||||
reader.stepIn();
|
||||
break;
|
||||
|
||||
|
||||
case "Channel":
|
||||
parseAnimationChannel(reader.getRecordData(), stack);
|
||||
reader.stepIn();
|
||||
break;
|
||||
|
||||
|
||||
case "Key":
|
||||
parseAnimationKey(reader.getRecordData(false), stack);
|
||||
reader.stepOver();
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
reader.stepOver();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private function parseModelRecord(data:RecordData, stack:Array, heap:Object):void {
|
||||
var attr:KFbxNodeAttribute;
|
||||
switch (data.strings [1]) {
|
||||
case "Light":
|
||||
attr = new KFbxLight;
|
||||
break;
|
||||
case "Limb":
|
||||
case "LimbNode":
|
||||
attr = new KFbxSkeleton;
|
||||
break;
|
||||
case "Mesh":
|
||||
attr = new KFbxMesh;
|
||||
break;
|
||||
}
|
||||
var node:KFbxNode = new KFbxNode;
|
||||
if (attr) {
|
||||
node.attributes.push(attr);
|
||||
}
|
||||
stack.push(heap [data.strings [0]] = node);
|
||||
}
|
||||
|
||||
private function parseConnection(data:RecordData, heap:Object):void {
|
||||
if (data.strings [0] == "OO") {
|
||||
var owned:Object = heap [data.strings [1]];
|
||||
var owner:Object = heap [data.strings [2]];
|
||||
|
||||
if (owned is KFbxNode) {
|
||||
if (owner is KFbxNode) {
|
||||
// иерархия
|
||||
(owned as KFbxNode).parent = owner as KFbxNode;
|
||||
return;
|
||||
}
|
||||
if (owner is KFbxCluster) {
|
||||
// bind joints
|
||||
(owner as KFbxCluster).jointNode = owned as KFbxNode;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// материалы нод
|
||||
if (owned is KFbxSurfaceMaterial) {
|
||||
(owner as KFbxNode).materials.push(owned as KFbxSurfaceMaterial);
|
||||
return;
|
||||
}
|
||||
// текстуры
|
||||
if (owned is KFbxTexture) {
|
||||
(owner as KFbxNode).textures.push(owned as KFbxTexture);
|
||||
return;
|
||||
}
|
||||
// кластера
|
||||
if (owned is KFbxCluster) {
|
||||
(owner as KFbxSkin).clusters.push(owned as KFbxCluster);
|
||||
return;
|
||||
}
|
||||
// скины
|
||||
if (owned is KFbxSkin) {
|
||||
var geom:KFbxGeometry = (owner as KFbxNode).getAttribute(KFbxGeometry) as KFbxGeometry;
|
||||
if (geom) {
|
||||
geom.deformers.push(owned as KFbxSkin);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
// ???
|
||||
}
|
||||
}
|
||||
|
||||
private function parseAnimationChannel(data:RecordData, stack:Array):void {
|
||||
var aniChannel:KFbxAnimCurveNode = new KFbxAnimCurveNode;
|
||||
aniChannel.channel = data.strings [0];
|
||||
var aniChannelParent:KFbxAnimCurveNode = stack [stack.length - 1] as KFbxAnimCurveNode;
|
||||
aniChannelParent.curveNodes.push(aniChannel);
|
||||
stack.push(aniChannel);
|
||||
}
|
||||
|
||||
private function parseAnimationLayer(data:RecordData, stack:Array, heap:Object):void {
|
||||
var aniLayer:KFbxAnimLayer = new KFbxAnimLayer;
|
||||
aniLayer.node = heap [data.strings [0]] as KFbxNode;
|
||||
var aniStack:KFbxAnimStack = stack [stack.length - 1] as KFbxAnimStack;
|
||||
aniStack.layers.push(aniLayer);
|
||||
stack.push(aniLayer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see http://code.google.com/p/blender-to-unity/issues/detail?id=2
|
||||
short:
|
||||
0,-14.7206611633301,U,a,n,...
|
||||
|
||||
0,1.619677305221558,C,n,
|
||||
14779570560,1.619677901268005,C,n,
|
||||
25864248480,1.619676709175110,C,n,
|
||||
27711694800,1.619677901268005,C,n,...
|
||||
|
||||
0,0,U,s,0,0,n,
|
||||
48110581250,0,U,s,0,0,n
|
||||
|
||||
variable length:
|
||||
0, 90, U, s, 0, 0, a, 0.333233326673508, 0.333233326673508,
|
||||
7697693000, 90, U, s, 0, -0, a, 0.333233326673508, 0.333233326673508,
|
||||
15395386000, 90, U, s, 0, 0, r, 0.989998996257782
|
||||
|
||||
neither [s]mooth nor [b]roken tangent:
|
||||
38488465000, 31.6565208435059, U, p, 100, -48.1283378601074, n, n,
|
||||
|
||||
|
||||
The keys are represented like this:
|
||||
1. The first value of a key is a number that represents the time of the key
|
||||
2. The second value is the amplitude of the key, this can be meters for
|
||||
translation or degrees for a rotation...
|
||||
3. The third value is a character that represents the interpolation between the
|
||||
keys, this can be 'C' for constant, 'L' for linear and 'U' for user defined. This
|
||||
last one can be used to represent Bezier curves.
|
||||
4. The fourth value is only needed when using user defined interpolation. This
|
||||
value is a character 's', for unified tangents and 'b' for broken tangents.
|
||||
5. The fifth value is a number that represents the direction of the right tangent
|
||||
of the current key, this is the amplitude the tangent would have, at the current time
|
||||
+ 1 second. The screenshot attached explains a lot.
|
||||
6. The sixth value is a number that represents the direction of the left tangent
|
||||
of the next key. This notation is exactly the same as the notation for the fifth value.
|
||||
7. The seventh value is a character 'a'.
|
||||
8. The eight' value is a number representing the horizontal amplitude of the right
|
||||
tangent of the current key. This is a number between 0 and 1, where 1 is the distance
|
||||
between the current key and the next key. This can also be seen on the screen attached.
|
||||
9. The ninth value is also a number representing the horizontal amplitude, but
|
||||
this time of the left tangent of the next key.
|
||||
|
||||
*/
|
||||
private function parseAnimationKey(data:RecordData, stack:Array):void {
|
||||
var aniCurve:KFbxAnimCurveNode = stack [stack.length - 1] as KFbxAnimCurveNode;
|
||||
for (var i:int = 0, n:int = data.strings.length; i < n;) {
|
||||
|
||||
aniCurve.KeyTime.push(parseFloat(data.strings [i]));
|
||||
aniCurve.KeyValueFloat.push(parseFloat(data.strings [i + 1]));
|
||||
|
||||
// находим начало следующего ключа
|
||||
switch (data.strings [i + 2]) {
|
||||
case "L":
|
||||
i += 3;
|
||||
break;
|
||||
case "C":
|
||||
i += 4;
|
||||
break;
|
||||
case "U":
|
||||
switch (data.strings [i + 3]) {
|
||||
case "a":
|
||||
i += 5;
|
||||
break;
|
||||
case "p":
|
||||
i += 8;
|
||||
break;
|
||||
case "b":
|
||||
case "s":
|
||||
switch (data.strings [i + 6]) {
|
||||
case "n":
|
||||
i += 7;
|
||||
break;
|
||||
case "r":
|
||||
i += 8;
|
||||
break;
|
||||
case "a":
|
||||
i += 9;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
trace("unexpected key format (V6)");
|
||||
i = n;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
trace("unexpected key format (V6)");
|
||||
i = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,332 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox.versions {
|
||||
|
||||
import alternativa.engine3d.loaders.filmbox.*;
|
||||
import alternativa.engine3d.loaders.filmbox.readers.*;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @see http://download.autodesk.com/global/docs/fbxsdk2012/en_us/index.html
|
||||
*/
|
||||
public class V7 extends VCommon implements IVersion {
|
||||
private var namesMap:Object = new Object;
|
||||
|
||||
public function parseCurrentRecord(reader:IReader, stack:Array, heap:Object):void {
|
||||
|
||||
var data:RecordData;
|
||||
|
||||
var recordName:String = reader.getRecordName();
|
||||
switch (recordName) {
|
||||
// верхний уровень, Prop70
|
||||
case "Objects":
|
||||
case "Connections":
|
||||
case "Takes":
|
||||
case "Properties70":
|
||||
stack.push(null);
|
||||
reader.stepIn();
|
||||
break;
|
||||
|
||||
case "GlobalSettings":
|
||||
stack.push(recordName);
|
||||
reader.stepIn();
|
||||
break;
|
||||
|
||||
|
||||
// 3D объекты
|
||||
case "Geometry":
|
||||
data = reader.getRecordData(false);
|
||||
// Geometry: 809442864, "Geometry::", "Mesh"
|
||||
if (data.strings [2] == "Mesh") {
|
||||
stack.push(heap [data.strings [0]] = new KFbxMesh);
|
||||
reader.stepIn();
|
||||
} else {
|
||||
reader.stepOver();
|
||||
}
|
||||
break;
|
||||
|
||||
case "Model":
|
||||
data = reader.getRecordData(false);
|
||||
// Model: 1360186080, "Model::Plane001", "Mesh"
|
||||
namesMap [data.strings [0]] = data.strings [1];
|
||||
stack.push(heap [data.strings [1]] = new KFbxNode);
|
||||
reader.stepIn();
|
||||
break;
|
||||
|
||||
case "NodeAttribute":
|
||||
data = reader.getRecordData(false);
|
||||
// NodeAttribute: 699168640, "NodeAttribute::", "Light"
|
||||
// NodeAttribute: 1396263680, "NodeAttribute::", "LimbNode"
|
||||
parseNodeAttribute(data, stack, heap) ? reader.stepIn() : reader.stepOver();
|
||||
break;
|
||||
|
||||
case "Deformer":
|
||||
data = reader.getRecordData(false);
|
||||
// Deformer: 802630608, "Deformer::", "Skin"
|
||||
// Deformer: 1365552016, "SubDeformer::", "Cluster"
|
||||
switch (data.strings [2]) {
|
||||
case "Cluster":
|
||||
stack.push(heap [data.strings [0]] = new KFbxCluster);
|
||||
reader.stepIn();
|
||||
break;
|
||||
case "Skin":
|
||||
heap [data.strings [0]] = new KFbxSkin;
|
||||
reader.stepOver();
|
||||
break;
|
||||
default:
|
||||
reader.stepOver();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// разная хрень из Mesh
|
||||
case "Vertices":
|
||||
case "PolygonVertexIndex":
|
||||
setMeshNumericProperty(reader, stack, recordName);
|
||||
reader.stepOver();
|
||||
break;
|
||||
case "LayerElementMaterial":
|
||||
addMeshLayerElement(reader, stack, new KFbxLayerElementMaterial);
|
||||
reader.stepIn();
|
||||
break;
|
||||
case "LayerElementUV":
|
||||
addMeshLayerElement(reader, stack, new KFbxLayerElementUV);
|
||||
reader.stepIn();
|
||||
break;
|
||||
case "LayerElementNormal":
|
||||
addMeshLayerElement(reader, stack, new KFbxLayerElementNormal);
|
||||
reader.stepIn();
|
||||
break;
|
||||
|
||||
|
||||
// поля слоёв
|
||||
case "MappingInformationType":
|
||||
case "ReferenceInformationType":
|
||||
case "Normals":
|
||||
case "Materials":
|
||||
case "UV":
|
||||
case "UVIndex":
|
||||
// поля текстур
|
||||
case "RelativeFilename":
|
||||
case "ModelUVTranslation":
|
||||
case "ModelUVScaling":
|
||||
// поля кластеров
|
||||
case "Indexes":
|
||||
case "Weights":
|
||||
case "Transform":
|
||||
case "TransformLink":
|
||||
// поля анимационных кривых
|
||||
case "KeyTime":
|
||||
case "KeyValueFloat":
|
||||
setPredefinedProperty(reader, stack, recordName);
|
||||
reader.stepOver();
|
||||
break;
|
||||
|
||||
|
||||
case "Material":
|
||||
data = reader.getRecordData(false);
|
||||
// Material: 699162640, "Material::Default", ""
|
||||
stack.push(heap [data.strings [0]] = new KFbxSurfaceMaterial);
|
||||
reader.stepIn();
|
||||
break;
|
||||
|
||||
case "Texture":
|
||||
data = reader.getRecordData(false);
|
||||
// Texture: 816837168, "Texture::character_anim:file2", ""
|
||||
stack.push(heap [data.strings [0]] = new KFbxTexture);
|
||||
reader.stepIn();
|
||||
break;
|
||||
|
||||
// свойства
|
||||
case "P":
|
||||
setAmbientLight(reader, stack, heap) || setProperty(reader, stack, 4);
|
||||
reader.stepOver();
|
||||
break;
|
||||
|
||||
|
||||
case "C":
|
||||
parseConnection(reader.getRecordData(false), heap);
|
||||
reader.stepOver();
|
||||
break;
|
||||
|
||||
|
||||
case "AnimationStack":
|
||||
data = reader.getRecordData(false);
|
||||
// AnimationStack: 1391183360, "AnimStack::Take 001", "" {
|
||||
namesMap [data.strings [0]] = data.strings [1];
|
||||
heap [data.strings [1]] = new KFbxAnimStack;
|
||||
reader.stepOver();
|
||||
break;
|
||||
|
||||
|
||||
case "AnimationLayer":
|
||||
data = reader.getRecordData(false);
|
||||
// AnimationLayer: 817238576, "AnimLayer::BaseLayer", "" {
|
||||
heap [data.strings [0]] = new KFbxAnimLayer;
|
||||
reader.stepOver();
|
||||
break;
|
||||
|
||||
|
||||
case "AnimationCurveNode":
|
||||
parseAnimationCurve(reader.getRecordData(false), heap);
|
||||
reader.stepOver();
|
||||
break;
|
||||
|
||||
|
||||
case "AnimationCurve":
|
||||
parseAnimationCurve(reader.getRecordData(false), heap, stack);
|
||||
reader.stepIn();
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
reader.stepOver();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private function parseAnimationCurve(data:RecordData, heap:Object, stack:Array = null):void {
|
||||
// AnimationCurveNode: 704770192, "AnimCurveNode::S", "" {
|
||||
// AnimationCurve: 1382726720, "AnimCurve::", "" {
|
||||
var curve:KFbxAnimCurveNode = new KFbxAnimCurveNode;
|
||||
var channel:String = data.strings [1];
|
||||
var dcat:int = channel.indexOf("::");
|
||||
curve.channel = (dcat > -1) ? channel.substr(dcat + 2) : channel;
|
||||
heap [data.strings [0]] = curve;
|
||||
if (stack) stack.push(curve);
|
||||
}
|
||||
|
||||
private function setAmbientLight(reader:IReader, stack:Array, heap:Object):Boolean {
|
||||
if (stack [stack.length - 2] == "GlobalSettings") {
|
||||
var data:RecordData = reader.getRecordData();
|
||||
if (data.strings [0] == "AmbientColor") {
|
||||
parseAmbientLight(data, heap);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function parseNodeAttribute(data:RecordData, stack:Array, heap:Object):Boolean {
|
||||
// NodeAttribute: 699168640, "NodeAttribute::", "Light"
|
||||
// NodeAttribute: 1396263680, "NodeAttribute::", "LimbNode"
|
||||
var attr:KFbxNodeAttribute;
|
||||
switch (data.strings [2]) {
|
||||
case "Light":
|
||||
attr = new KFbxLight;
|
||||
break;
|
||||
case "Limb":
|
||||
case "LimbNode":
|
||||
attr = new KFbxSkeleton;
|
||||
break;
|
||||
}
|
||||
if (attr) {
|
||||
stack.push(heap [data.strings [0]] = attr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function parseConnection(data:RecordData, heap:Object):void {
|
||||
var owned:Object = heap [data.strings [1]];
|
||||
if (owned == null) owned = heap [namesMap [data.strings [1]]];
|
||||
var node:KFbxNode = heap [namesMap [data.strings [2]]] as KFbxNode;
|
||||
if (data.strings [0] == "OO") {
|
||||
// аттрибуты
|
||||
if (owned is KFbxNodeAttribute) {
|
||||
node.attributes.push(owned as KFbxNodeAttribute);
|
||||
return;
|
||||
}
|
||||
|
||||
if (owned is KFbxNode) {
|
||||
if (node) {
|
||||
// иерархия
|
||||
(owned as KFbxNode).parent = node;
|
||||
return;
|
||||
}
|
||||
|
||||
var cluster:KFbxCluster = heap [data.strings [2]] as KFbxCluster;
|
||||
if (cluster) {
|
||||
// bind joints
|
||||
cluster.jointNode = owned as KFbxNode;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// материалы нод
|
||||
if (owned is KFbxSurfaceMaterial) {
|
||||
var material:KFbxSurfaceMaterial = owned as KFbxSurfaceMaterial;
|
||||
material.node = node;
|
||||
node.materials.push(material);
|
||||
return;
|
||||
}
|
||||
// кластера
|
||||
if (owned is KFbxCluster) {
|
||||
var skin:KFbxSkin = heap [data.strings [2]] as KFbxSkin;
|
||||
skin.clusters.push(owned as KFbxCluster);
|
||||
return;
|
||||
}
|
||||
// скины
|
||||
if (owned is KFbxSkin) {
|
||||
var geom:KFbxGeometry = heap [data.strings [2]] as KFbxGeometry;
|
||||
geom.deformers.push(owned as KFbxSkin);
|
||||
return;
|
||||
}
|
||||
// слои анимации
|
||||
if (owned is KFbxAnimLayer) {
|
||||
var astack:KFbxAnimStack = heap [namesMap [data.strings [2]]] as KFbxAnimStack;
|
||||
astack.layers.push(owned as KFbxAnimLayer);
|
||||
return;
|
||||
}
|
||||
// анимационные кривые
|
||||
if (owned is KFbxAnimCurveNode) {
|
||||
var aparent:KFbxAnimCurveNode = heap [data.strings [2]] as KFbxAnimCurveNode;
|
||||
aparent.curveNodes.push(owned as KFbxAnimCurveNode);
|
||||
return;
|
||||
}
|
||||
|
||||
} else
|
||||
|
||||
if (data.strings [0] == "OP") {
|
||||
// текстуры
|
||||
if (owned is KFbxTexture) {
|
||||
var texture:KFbxTexture = owned as KFbxTexture;
|
||||
var channel:String;
|
||||
switch (data.strings [3]) {
|
||||
case "Bump":
|
||||
channel = "bump";
|
||||
break;
|
||||
case "SpecularColor":
|
||||
channel = "specular";
|
||||
break;
|
||||
case "DiffuseColor":
|
||||
default:
|
||||
channel = "diffuse";
|
||||
break;
|
||||
// TODO find values for glossiness, emission, transparent
|
||||
}
|
||||
material = heap [data.strings [2]] as KFbxSurfaceMaterial;
|
||||
material.textures [channel] = texture;
|
||||
material.node.textures.push(texture);
|
||||
return;
|
||||
}
|
||||
// анимационные кривые
|
||||
if (owned is KFbxAnimCurveNode) {
|
||||
var curve:KFbxAnimCurveNode = owned as KFbxAnimCurveNode;
|
||||
if (node) {
|
||||
// связь с 3д объектами
|
||||
curve.node = node;
|
||||
return;
|
||||
}
|
||||
|
||||
aparent = heap [data.strings [2]] as KFbxAnimCurveNode;
|
||||
if (aparent) {
|
||||
aparent.curveNodes.push(owned as KFbxAnimCurveNode);
|
||||
// curve channel
|
||||
channel = data.strings [3];
|
||||
var barat:int = channel.indexOf("|");
|
||||
curve.channel = (barat >= 0) ? channel.substr(barat + 1) : channel;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox.versions {
|
||||
|
||||
import alternativa.engine3d.loaders.filmbox.*;
|
||||
import alternativa.engine3d.loaders.filmbox.readers.*;
|
||||
|
||||
/** @private */
|
||||
public class VCommon {
|
||||
private function setObjectPropertyFromData(object:Object, property:String, sLength:int,
|
||||
data:RecordData):Boolean {
|
||||
if (object.hasOwnProperty(property)) {
|
||||
var defaultValue:Object = object [property];
|
||||
if (data.numbers.length > 0) {
|
||||
// this is numeric property
|
||||
// if ((defaultValue == null) ? (data.numbers.length > 1) : defaultValue.hasOwnProperty ("length")) {
|
||||
if ((defaultValue == null) ? (data.numbers.length > 1) : defaultValue is Vector.<Number>) {
|
||||
// array
|
||||
object [property] = data.numbers;
|
||||
} else {
|
||||
// scalar
|
||||
object [property] = data.numbers [0];
|
||||
}
|
||||
} else if (data.strings.length > sLength) {
|
||||
// this is string property
|
||||
if ((defaultValue == null) ? (data.strings.length > 1 + sLength) : defaultValue is Vector.<String>) {
|
||||
// array TODO are there actually any string arrays, ever?
|
||||
data.strings.splice(0, sLength);
|
||||
object [property] = data.strings;
|
||||
} else {
|
||||
// scalar
|
||||
object [property] = data.strings [sLength];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function setPredefinedProperty(reader:IReader, stack:Array, recordName:String):Boolean {
|
||||
if (stack.length > 0) {
|
||||
var object:Object = stack [stack.length - 1];
|
||||
if (object != null) {
|
||||
return setObjectPropertyFromData(object, recordName, 0, reader.getRecordData());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function setProperty(reader:IReader, stack:Array, sLength:int):Boolean {
|
||||
if (stack.length > 1) {
|
||||
var object:Object = stack [stack.length - 2];
|
||||
if (object != null) {
|
||||
var data:RecordData = reader.getRecordData();
|
||||
var property:String = data.strings [0];
|
||||
if (property.indexOf("|") > 0) return false; // ignore "Compound" properties for now
|
||||
if (property.indexOf(" ") > 0) property = property.replace(" ", "");
|
||||
var success:Boolean = setObjectPropertyFromData(object, property, sLength, data);
|
||||
if (!success && (object is KFbxNode)) {
|
||||
// also attempt this on every attribute
|
||||
var node:KFbxNode = object as KFbxNode;
|
||||
for each (var attr:KFbxNodeAttribute in node.attributes) {
|
||||
if (setObjectPropertyFromData(attr, property, sLength, data)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getCurrentMesh(stack:Array):KFbxMesh {
|
||||
var mesh:KFbxMesh = stack [stack.length - 1] as KFbxMesh;
|
||||
if (mesh) {
|
||||
return mesh;
|
||||
}
|
||||
// for v6-, there is node on the stack
|
||||
var node:KFbxNode = stack [stack.length - 1] as KFbxNode;
|
||||
if (node) {
|
||||
mesh = node.getAttribute(KFbxMesh) as KFbxMesh;
|
||||
// for v5, there might be no mesh attribute yet
|
||||
if (mesh == null) {
|
||||
mesh = new KFbxMesh;
|
||||
node.attributes.push(mesh);
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function setMeshNumericProperty(reader:IReader, stack:Array, property:String):void {
|
||||
var mesh:KFbxMesh = getCurrentMesh(stack);
|
||||
if (mesh) mesh [property] = reader.getRecordData().numbers;
|
||||
}
|
||||
|
||||
protected function addMeshLayerElement(reader:IReader, stack:Array, element:KFbxLayerElement,
|
||||
layerIndex:int = -1, saveOnStack:Boolean = true):void {
|
||||
var mesh:KFbxMesh = getCurrentMesh(stack);
|
||||
if (mesh) {
|
||||
|
||||
// v5 does not specify layer in data, so we actually pass it as argument
|
||||
if (layerIndex < 0) {
|
||||
var numbers:Vector.<Number> = reader.getRecordData().numbers;
|
||||
if (numbers.length > 0) layerIndex = numbers [0];
|
||||
}
|
||||
|
||||
var layer:KFbxLayer;
|
||||
if (layerIndex < mesh.layers.length) {
|
||||
layer = mesh.layers [layerIndex];
|
||||
} else {
|
||||
mesh.layers.push(layer = new KFbxLayer);
|
||||
}
|
||||
|
||||
layer.elements.push(element);
|
||||
}
|
||||
|
||||
if (saveOnStack) {
|
||||
stack.push(element);
|
||||
}
|
||||
}
|
||||
|
||||
protected function parseAmbientLight(data:RecordData, heap:Object):void {
|
||||
var node:KFbxNode = new KFbxNode;
|
||||
var attr:KFbxLight = new KFbxLight;
|
||||
attr.Color = data.numbers;
|
||||
attr.Intensity = 100*((attr.Color.length > 3) ? attr.Color.pop() : 1);
|
||||
node.attributes.push(attr);
|
||||
heap["AmbientLight"] = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package alternativa.engine3d.loaders.filmbox.versions {
|
||||
|
||||
import alternativa.engine3d.loaders.filmbox.readers.IReader;
|
||||
|
||||
public class VUnknown implements IVersion {
|
||||
public var majorVersion:uint = 0;
|
||||
|
||||
public function parseCurrentRecord(reader:IReader, stack:Array, heap:Object):void {
|
||||
switch (reader.getRecordName()) {
|
||||
case "FBXHeaderExtension":
|
||||
stack.push(null);
|
||||
reader.stepIn();
|
||||
break;
|
||||
case "FBXVersion":
|
||||
majorVersion = reader.getRecordData().numbers [0]/1000;
|
||||
default:
|
||||
reader.stepOver();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -467,23 +467,13 @@ package alternativa.engine3d.materials {
|
||||
// i3 - ambient
|
||||
// i2 - shadow-test
|
||||
|
||||
source.push("mul t0.xw, t0.xw, i2.x");
|
||||
source.push("mul t0.xw, t0.xw, i2.xw");
|
||||
source.push("mul t0.xyz, c1.xyz, t0.xxx"); // t = color*t
|
||||
source.push("mul t1.xyz, t0.xyz, t1.w");
|
||||
source.push("add o1.xyz, o1.xyz, t1.xyz");
|
||||
source.push("mul t0.xyz, t0.xyz, t0.www");
|
||||
source.push("add o0.xyz, t0.xyz, i3.xyz");
|
||||
|
||||
// source.push("mov o1, t1");
|
||||
// source.push("mov o1, c1");
|
||||
// source.push("mov o1, i2");
|
||||
// source.push("mov o1, i3");
|
||||
// source.push("sub o1, t0, t0");
|
||||
//
|
||||
//
|
||||
// source.push("mov o0.xyz, i2.x");
|
||||
// source.push("div o0.w, i2.x, i2.x");
|
||||
|
||||
} else {
|
||||
|
||||
// Считаем вектор из точки к свету
|
||||
|
||||
@@ -131,10 +131,10 @@ package alternativa.engine3d.shadows {
|
||||
* @private
|
||||
*/
|
||||
alternativa3d function setBoundSize(value:Number):void{
|
||||
this.boundSize = value*2;
|
||||
this.boundSize = value;
|
||||
for (var i:int = 0; i < 6; i++) {
|
||||
var cam:Camera3D = cameras[i];
|
||||
cam.view.width = cam.view.height = 1;
|
||||
cam.view.width = cam.view.height = int (value);
|
||||
cam.farClipping = value;
|
||||
cam.calculateProjection(value,value);
|
||||
}
|
||||
@@ -143,36 +143,36 @@ package alternativa.engine3d.shadows {
|
||||
private function createDebugCube(material:Material, context:Context3D):Mesh{
|
||||
var mesh:Mesh = new Mesh();
|
||||
// TODO: определиться куб или сфера
|
||||
var geometry:Geometry = new Geometry(8);
|
||||
mesh.geometry = geometry;
|
||||
|
||||
var attributes:Array = new Array();
|
||||
attributes[0] = VertexAttributes.POSITION;
|
||||
attributes[1] = VertexAttributes.POSITION;
|
||||
attributes[2] = VertexAttributes.POSITION;
|
||||
geometry.addVertexStream(attributes);
|
||||
|
||||
geometry.setAttributeValues(VertexAttributes.POSITION, Vector.<Number>([-0.5, -0.5, -0.5,
|
||||
0.5, -0.5, -0.5,
|
||||
0.5, 0.5, -0.5,
|
||||
-0.5, 0.5, -0.5,
|
||||
-0.5, -0.5, 0.5,
|
||||
0.5, -0.5, 0.5,
|
||||
0.5, 0.5, 0.5,
|
||||
-0.5, 0.5, 0.5]));
|
||||
|
||||
geometry.indices = Vector.<uint>([ 0, 1, 2, 3, 0, 2, 2, 1, 0, 3, 2, 0,
|
||||
2, 6, 1, 1, 6, 2, 1, 6, 5, 5, 6, 1,
|
||||
6, 4, 5, 5, 4, 6, 6, 4, 7, 7, 4, 6,
|
||||
0, 7, 4, 4, 7, 0, 0, 7, 3, 3, 7, 0,
|
||||
3, 6, 2, 2, 6, 3, 3, 7, 6, 6, 7, 3,
|
||||
0, 5, 1, 1, 5, 0, 0, 4, 5, 5, 4, 0]);
|
||||
|
||||
mesh.addSurface(material, 0, 24);
|
||||
// var sphere:GeoSphere = new GeoSphere(1, 4, false);
|
||||
// var geometry:Geometry = sphere.geometry;
|
||||
// var geometry:Geometry = new Geometry(8);
|
||||
// mesh.geometry = geometry;
|
||||
// mesh.addSurface(material, 0, geometry.numTriangles);
|
||||
//
|
||||
// var attributes:Array = new Array();
|
||||
// attributes[0] = VertexAttributes.POSITION;
|
||||
// attributes[1] = VertexAttributes.POSITION;
|
||||
// attributes[2] = VertexAttributes.POSITION;
|
||||
// geometry.addVertexStream(attributes);
|
||||
//
|
||||
// geometry.setAttributeValues(VertexAttributes.POSITION, Vector.<Number>([-0.5, -0.5, -0.5,
|
||||
// 0.5, -0.5, -0.5,
|
||||
// 0.5, 0.5, -0.5,
|
||||
// -0.5, 0.5, -0.5,
|
||||
// -0.5, -0.5, 0.5,
|
||||
// 0.5, -0.5, 0.5,
|
||||
// 0.5, 0.5, 0.5,
|
||||
// -0.5, 0.5, 0.5]));
|
||||
//
|
||||
// geometry.indices = Vector.<uint>([ 0, 1, 2, 3, 0, 2, 2, 1, 0, 3, 2, 0,
|
||||
// 2, 6, 1, 1, 6, 2, 1, 6, 5, 5, 6, 1,
|
||||
// 6, 4, 5, 5, 4, 6, 6, 4, 7, 7, 4, 6,
|
||||
// 0, 7, 4, 4, 7, 0, 0, 7, 3, 3, 7, 0,
|
||||
// 3, 6, 2, 2, 6, 3, 3, 7, 6, 6, 7, 3,
|
||||
// 0, 5, 1, 1, 5, 0, 0, 4, 5, 5, 4, 0]);
|
||||
//
|
||||
// mesh.addSurface(material, 0, 24);
|
||||
var sphere:GeoSphere = new GeoSphere(1, 4, false);
|
||||
var geometry:Geometry = sphere.geometry;
|
||||
mesh.geometry = geometry;
|
||||
mesh.addSurface(material, 0, geometry.numTriangles);
|
||||
|
||||
geometry.upload(context);
|
||||
|
||||
@@ -236,7 +236,6 @@ package alternativa.engine3d.shadows {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Пробегаемся по 6-и камерам
|
||||
for (i = 0; i < 6; i++) {
|
||||
// камера соответствующая грани куба
|
||||
@@ -272,8 +271,7 @@ package alternativa.engine3d.shadows {
|
||||
// собираем матрицу перевода из кастера в пространство edgeCamera
|
||||
casterToEdgedCameraTransform.combine(edgeCamera.inverseTransform, caster.localToLightTransform);
|
||||
// Собираем драуколлы для кастера и его дочерних объектов
|
||||
// if (i == 1)
|
||||
collectDraws(context, caster, edgeCamera);
|
||||
collectDraws(context, caster, edgeCamera);
|
||||
}
|
||||
|
||||
// Отрисовка дроуколов
|
||||
@@ -527,14 +525,14 @@ package alternativa.engine3d.shadows {
|
||||
}
|
||||
|
||||
var proc:Procedure = Procedure.compileFromArray([
|
||||
"#c1=cScale", // 255/boundSize, 0, 0, 1
|
||||
"#c1=cScale",
|
||||
"#v0=vDistance",
|
||||
|
||||
"m34 t0.xyz, i0, c2",
|
||||
"dp3 t0.x, t0.xyz, t0.xyz",
|
||||
"sqt t0.x, t0.x", // x: [0, boundSize]
|
||||
"mul t0.w, t0.x, c1.x", // w: [0, 255]
|
||||
// "mov t0.w, c1.w",
|
||||
"mul t0.x, t0.x, c1.x", // x: [0, 255]
|
||||
"mov t0.w, c1.w",
|
||||
"mov v0, t0",
|
||||
|
||||
"m44 o0, i0, c0"
|
||||
@@ -552,10 +550,10 @@ package alternativa.engine3d.shadows {
|
||||
}
|
||||
}
|
||||
fLinker.addProcedure(Procedure.compileFromArray([
|
||||
"#v0=vDistance", // w: [0, 255]
|
||||
"#v0=vDistance", // x: [0, 255]
|
||||
"#c0=cConstants", // 1/255, 0, 0, 1
|
||||
"frc t0.y, v0.w",
|
||||
"sub t0.x, v0.w, t0.y",
|
||||
"frc t0.y, v0.x",
|
||||
"sub t0.x, v0.x, t0.y",
|
||||
"mul t0.x, t0.x, c0.x",
|
||||
"mov t0.zw, c0.zw",
|
||||
|
||||
@@ -572,7 +570,7 @@ package alternativa.engine3d.shadows {
|
||||
|
||||
|
||||
|
||||
//------------- ShadowMap Shader in material ----------
|
||||
//------------- ShadowMap Shader ----------
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -589,14 +587,13 @@ package alternativa.engine3d.shadows {
|
||||
// TODO: сделать множитель более корректный. Возможно 65536 (разрешающая способность глубины буфера).
|
||||
if (_pcfOffset > 0) {
|
||||
|
||||
var offset:Number = _pcfOffset*0.0175; //TODO: заточить оффсет под 1 градус
|
||||
var offset:Number = _pcfOffset*0.0175; //1 градус
|
||||
drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cPCFOffsets"), -3/2, 1/16, 0, 0);
|
||||
drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cConstants"), -1, 1, 0, offset/boundSize);
|
||||
drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cDecode"), -10000, -10000/255, biasMultiplier*10000/boundSize, 10);
|
||||
}
|
||||
else{
|
||||
drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cConstants"), -100000, -100000/255, biasMultiplier*100000/boundSize, 1);
|
||||
// drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cConstants"), -100000, -100000/255, 2/boundSize, 1);
|
||||
drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cConstants"), -10000, -10000/255, biasMultiplier*10000/boundSize, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -628,15 +625,9 @@ package alternativa.engine3d.shadows {
|
||||
shaderArr[line++] = "dp3 t0.x, t0.xyz, c0.xyz"; // декодируем, находим разницу между расстояниями и умножаем ее на большое число
|
||||
|
||||
// рассчитываем значение тени
|
||||
shaderArr[line++] = "sat t0.x, t0.x";
|
||||
shaderArr[line++] = "sat t0, t0.x";
|
||||
shaderArr[line++] = "sub o0, c0.w, t0.x";
|
||||
|
||||
// shaderArr[line++] = "tex t0.xy, v0, s0 <cube, linear>";
|
||||
// shaderArr[line++] = "mov t0.z, v0.w"; // z: [0, boundSize]
|
||||
// shaderArr[line++] = "mul t0.z, t0.z, c0.z"; // z: [0, 1]
|
||||
// shaderArr[line++] = "mov o0, t0.z"; // r/boundSize
|
||||
|
||||
|
||||
return Procedure.compileFromArray(shaderArr, "OmniShadowMapFragment");
|
||||
}
|
||||
|
||||
@@ -813,8 +804,6 @@ import alternativa.engine3d.resources.Geometry;
|
||||
import flash.display3D.Context3D;
|
||||
import flash.display3D.Context3DBlendFactor;
|
||||
import flash.display3D.Context3DProgramType;
|
||||
import flash.display3D.Program3D;
|
||||
|
||||
import flash.display3D.VertexBuffer3D;
|
||||
import flash.display3D.textures.CubeTexture;
|
||||
import flash.utils.Dictionary;
|
||||
|
||||
Reference in New Issue
Block a user