<commit_before>package com.babylonhx.mesh;

import com.babylonhx.actions.ActionManager;
import com.babylonhx.bones.Bone;
import com.babylonhx.bones.Skeleton;
import com.babylonhx.cameras.Camera;
import com.babylonhx.collisions.Collider;
import com.babylonhx.collisions.IntersectionInfo;
import com.babylonhx.collisions.PickingInfo;
import com.babylonhx.culling.BoundingInfo;
import com.babylonhx.culling.BoundingSphere;
import com.babylonhx.culling.octrees.Octree;
import com.babylonhx.materials.Material;
import com.babylonhx.materials.MaterialDefines;
import com.babylonhx.math.Matrix;
import com.babylonhx.math.Plane;
import com.babylonhx.math.Axis;
import com.babylonhx.math.Quaternion;
import com.babylonhx.culling.Ray;
import com.babylonhx.math.Space;
import com.babylonhx.math.Tools;
import com.babylonhx.math.Vector3;
import com.babylonhx.math.Color3;
import com.babylonhx.math.Color4;
import com.babylonhx.math.Frustum;
import com.babylonhx.Node.NodeCache;
import com.babylonhx.physics.PhysicsEngine;
import com.babylonhx.physics.PhysicsBodyCreationOptions;
import com.babylonhx.rendering.EdgesRenderer;
import com.babylonhx.math.Tmp;
import com.babylonhx.utils.typedarray.Float32Array;

/**
 * ...
 * @author <NAME>
 */
 
@:expose('BABYLON.AbstractMesh') class AbstractMesh extends Node implements IDisposable {
	
	// Statics
	public static var BILLBOARDMODE_NONE:Int = 0;
	public static var BILLBOARDMODE_X:Int = 1;
	public static var BILLBOARDMODE_Y:Int = 2;
	public static var BILLBOARDMODE_Z:Int = 4;
	public static var BILLBOARDMODE_ALL:Int = 7;


	// Properties
	public var definedFacingForward:Bool = true; // orientation for POV movement & rotation
	public var position:Vector3 = new Vector3(0, 0, 0);
	public var rotation(get, set):Vector3;
	public var rotationQuaternion(get, set):Quaternion;
	public var scaling(get, set):Vector3;
	public var billboardMode:Int = AbstractMesh.BILLBOARDMODE_NONE;
	
	private var _rotation:Vector3 = new Vector3(0, 0, 0);
	private var _scaling:Vector3 = new Vector3(1, 1, 1);
	private var _rotationQuaternion:Quaternion;
	
	private var _visibility:Float = 1.0;
	public var visibility(get, set):Float;
	private function get_visibility():Float {
		return _visibility;
	}
	private function set_visibility(val:Float):Float {
		_visibility = val;
		return val;
	}	
	
	public var alphaIndex:Float = Math.POSITIVE_INFINITY;
	public var infiniteDistance:Bool = false;
	public var isVisible:Bool = true;	
	
	private var _isPickable:Bool = false;
	public var isPickable(get, set):Bool;
	private function get_isPickable():Bool {
		return _isPickable;
	}
	private function set_isPickable(val:Bool):Bool {
		_isPickable = val;
		return val;
	}
	
	public var showBoundingBox:Bool = false;
	public var showSubMeshesBoundingBox:Bool = false;
	public var onDispose:Void->Void = null;	
	public var isBlocker:Bool = false;	
	
	public var renderingGroupId:Int = 0;	
	
	private var _material:Material;
	public var material(get, set):Material;
	private function get_material():Material {
		return _material;
	}
	private function set_material(val:Material):Material {
		_material = val;
		return val;
	}
	
	private var _receiveShadows:Bool = false;
	public var receiveShadows(get, set):Bool;
	private function get_receiveShadows():Bool {
		return _receiveShadows;
	}
	private function set_receiveShadows(val:Bool):Bool {
		_receiveShadows = val;
		return val;
	}
	
	public var actionManager:ActionManager;
	public var renderOutline:Bool = false;
	public var outlineColor:Color3 = Color3.Red();
	public var outlineWidth:Float = 0.02;
	public var renderOverlay:Bool = false;
	public var overlayColor:Color3 = Color3.Red();
	public var overlayAlpha:Float = 0.5;
	public var hasVertexAlpha:Bool = false;
	public var useVertexColors:Bool = true;
	public var applyFog:Bool = true;
	public var computeBonesUsingShaders:Bool = true;
	public var scalingDeterminant:Float = 1;
	public var numBoneInfluencers:Int = 4;

	public var useOctreeForRenderingSelection:Bool = true;
	public var useOctreeForPicking:Bool = true;
	public var useOctreeForCollisions:Bool = true;

	public var layerMask:Int = 0x0FFFFFFF;
	
	// for bGUI
	public var __gui:Bool = false;
	
	public var alwaysSelectAsActiveMesh:Bool = false;

	// Physics
	public var _physicImpostor:Int = PhysicsEngine.NoImpostor;
	public var _physicsMass:Float = 0;
	public var _physicsFriction:Float = 0;
	public var _physicRestitution:Float = 0;
	public var onPhysicsCollide:AbstractMesh->Dynamic->Void; 

	// Collisions
	private var _checkCollisions:Bool = false;
	public var ellipsoid:Vector3 = new Vector3(0.5, 1, 0.5);
	public var ellipsoidOffset:Vector3 = new Vector3(0, 0, 0);
	private var _collider:Collider = new Collider();
	private var _oldPositionForCollisions:Vector3 = new Vector3(0, 0, 0);
	private var _diffPositionForCollisions:Vector3 = new Vector3(0, 0, 0);
	private var _newPositionForCollisions:Vector3 = new Vector3(0, 0, 0);
	public var onCollide:AbstractMesh->Void;
	public var onCollisionPositionChange:Vector3->Void;
	
	// Attach to bone
    private var _meshToBoneReferal:AbstractMesh;
	
	// Edges
	public var edgesWidth:Float = 1;
    public var edgesColor:Color4 = new Color4(1, 0, 0, 1);
	public var _edgesRenderer:EdgesRenderer;

	// Cache
	private var _localScaling:Matrix = Matrix.Zero();
	private var _localRotation:Matrix = Matrix.Zero();
	private var _localTranslation:Matrix = Matrix.Zero();
	private var _localBillboard:Matrix = Matrix.Zero();
	private var _localPivotScaling:Matrix = Matrix.Zero();
	private var _localPivotScalingRotation:Matrix = Matrix.Zero();
	private var _localMeshReferalTransform:Matrix;
	private var _localWorld:Matrix = Matrix.Zero();
	public var _worldMatrix:Matrix = Matrix.Zero();
	private var _rotateYByPI:Matrix = Matrix.RotationY(Math.PI);
	private var _absolutePosition:Vector3 = Vector3.Zero();
	private var _collisionsTransformMatrix:Matrix = Matrix.Zero();
	private var _collisionsScalingMatrix:Matrix = Matrix.Zero();	
	
	public var _savedMaterial:Material;
		
	private var _positions:Array<Vector3>;
	public var positions(get, set):Array<Vector3>;
	private function get_positions():Array<Vector3> {
		return _positions;
	}
	private function set_positions(val:Array<Vector3>):Array<Vector3> {
		_positions = val;
		return val;
	}
	
	public var useBones(get, never):Bool;
	private function get_useBones():Bool {
		return this.skeleton != null && this.getScene().skeletonsEnabled && this.isVerticesDataPresent(VertexBuffer.MatricesIndicesKind) && this.isVerticesDataPresent(VertexBuffer.MatricesWeightsKind);
	}
	
	private var _isDirty:Bool = false;
	public var _masterMesh:AbstractMesh;
	public var _materialDefines:MaterialDefines;

	public var _boundingInfo:BoundingInfo;
	private var _pivotMatrix:Matrix = Matrix.Identity();
	public var _isDisposed:Bool = false;
	public var _renderId:Int = 0;

	public var subMeshes:Array<SubMesh>;
	public var _submeshesOctree:Octree<SubMesh>;
	public var _intersectionsInProgress:Array<AbstractMesh> = [];
	
	private var _onAfterWorldMatrixUpdate:Array<AbstractMesh->Void> = [];
	
	private var _isWorldMatrixFrozen:Bool = false;
	
	public var _unIndexed:Bool = false;
	
	public var _poseMatrix:Matrix;
	
	// Loading properties
	public var _waitingActions:Dynamic;
	public var _waitingFreezeWorldMatrix:Bool;
	
	// Skeleton
	private var _skeleton:Skeleton;
	public var skeleton(get, set):Skeleton;
	public var _bonesTransformMatrices: #if (js || purejs || web || html5) Float32Array #else Array<Float> #end ;
	
	private function get_skeleton():Skeleton {
		return this._skeleton;
	}
	private function set_skeleton(value:Skeleton):Skeleton {
		if (this._skeleton != null && this._skeleton.needInitialSkinMatrix) {
			this._skeleton._unregisterMeshWithPoseMatrix(this);
		}
		
		if (value != null && value.needInitialSkinMatrix) {
			value._registerMeshWithPoseMatrix(this);
		}
		
		this._skeleton = value;
		
		if (this._skeleton == null) {
			this._bonesTransformMatrices = null;
		}
		
		return value;
	}
	

	public function new(name:String, scene:Scene) {
		super(name, scene);
		scene.addMesh(this);
		
		// TODO: macro ...
		#if purejs
		untyped __js__("Object.defineProperty(this, 'visibility', { get: this.get_visibility, set: this.set_visibility })");
		untyped __js__("Object.defineProperty(this, 'isPickable', { get: this.get_isPickable, set: this.set_isPickable })");
		untyped __js__("Object.defineProperty(this, 'skeleton', { get: this.get_skeleton, set: this.set_skeleton })");
		untyped __js__("Object.defineProperty(this, 'material', { get: this.get_material, set: this.set_material })");
		untyped __js__("Object.defineProperty(this, 'receiveShadows', { get: this.get_receiveShadows, set: this.set_receiveShadows })");
		untyped __js__("Object.defineProperty(this, 'positions', { get: this.get_positions, set: this.set_positions })");
		untyped __js__("Object.defineProperty(this, 'useBones', { get: this.get_useBones, set: this.set_useBones })");
		untyped __js__("Object.defineProperty(this, 'isBlocked', { get: this.get_isBlocked, set: this.set_isBlocked })");
		untyped __js__("Object.defineProperty(this, 'worldMatrixFromCache', { get: this.get_worldMatrixFromCache })");
		untyped __js__("Object.defineProperty(this, 'absolutePosition', { get: this.get_absolutePosition })");
		untyped __js__("Object.defineProperty(this, 'isWorldMatrixFrozen', { get: this.get_isWorldMatrixFrozen })");
		#end
	}
	
	/**
	 * Getting the rotation object. 
	 * If rotation quaternion is set, this vector will (almost always) be the Zero vector!
	 */
	private function get_rotation():Vector3 {
		return this._rotation;
	}
	private function set_rotation(newRotation:Vector3):Vector3 {
		return this._rotation = newRotation;
	}

	private function get_scaling():Vector3 {
		return this._scaling;
	}
	private function set_scaling(newScaling:Vector3):Vector3 {
		this._scaling = newScaling;
		/*if (this.physicsImpostor != null) {
			this.physicsImpostor.forceUpdate();
		}*/
		
		return newScaling;
	}

	private function get_rotationQuaternion():Quaternion {
		return this._rotationQuaternion;
	} 
	private function set_rotationQuaternion(?quaternion:Quaternion):Quaternion {
        this._rotationQuaternion = quaternion;
        //reset the rotation vector. 
		if (quaternion != null && this.rotation.length() > 0) {
			this.rotation.copyFromFloats(0, 0, 0);
		}
		
		return quaternion;
	}

	// Methods
	public function updatePoseMatrix(matrix:Matrix) {
		this._poseMatrix.copyFrom(matrix);
	}

	public function getPoseMatrix():Matrix {
		return this._poseMatrix;
	}
	
	public function disableEdgesRendering() {
        if (this._edgesRenderer != null) {
            this._edgesRenderer.dispose();
            this._edgesRenderer = null;
        }
    }
    public function enableEdgesRendering(epsilon:Float = 0.95, checkVerticesInsteadOfIndices:Bool = false) {
        this.disableEdgesRendering();
		
        this._edgesRenderer = new EdgesRenderer(this, epsilon, checkVerticesInsteadOfIndices);
    }
	
	private var _isBlocked:Bool;
	public var isBlocked(get, never):Bool;
	private function get_isBlocked():Bool {
		return false;
	}

	public function getLOD(camera:Camera, ?boundingSphere:BoundingSphere):AbstractMesh {
		return this;
	}

	public function getTotalVertices():Int {
		return 0;
	}

	public function getIndices(copyWhenShared:Bool = false):Array<Int> {
		return null;
	}

	public function getVerticesData(kind:String, copyWhenShared:Bool = false):Array<Float> {
		return null;
	}

	public function isVerticesDataPresent(kind:String):Bool {
		return false;
	}

	public function getBoundingInfo():BoundingInfo {
		if (this._masterMesh != null) {
			return this._masterMesh.getBoundingInfo();
		}
		
		if (this._boundingInfo == null) {
			this._updateBoundingInfo();
		}
		
		return this._boundingInfo;
	}
	
	public function _preActivate() { }
	
	public function _preActivateForIntermediateRendering(renderId:Int) { }
	
	public function _activate(renderId:Int) {
		this._renderId = renderId;
	}

	override public function getWorldMatrix():Matrix {
		if (this._masterMesh != null) {
			return this._masterMesh.getWorldMatrix();
		}
		
		if (this._currentRenderId != this.getScene().getRenderId()) {
			this.computeWorldMatrix();
		}
		
		return this._worldMatrix;
	}

	public var worldMatrixFromCache(get, never):Matrix;
	private function get_worldMatrixFromCache():Matrix {
		return this._worldMatrix;
	}

	public var absolutePosition(get, never):Vector3;
	private function get_absolutePosition():Vector3 {
		return this._absolutePosition;
	}
	
	inline public function freezeWorldMatrix() {
		this._isWorldMatrixFrozen = false;  // no guarantee world is not already frozen, switch off temporarily
        this.computeWorldMatrix(true);
        this._isWorldMatrixFrozen = true;
    }

    inline public function unfreezeWorldMatrix() {
        this._isWorldMatrixFrozen = false;
		this.computeWorldMatrix(true);
    }
	
	public var isWorldMatrixFrozen(get, never):Bool;
	private function get_isWorldMatrixFrozen():Bool {
        return this._isWorldMatrixFrozen;
    }

	public function rotate(axis:Vector3, amount:Float, space:Space) {
		axis.normalize();
		
		if (this.rotationQuaternion == null) {
			this.rotationQuaternion = Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z);
			this.rotation = Vector3.Zero();
		}
		
		if (space == null || space == Space.LOCAL) {
			var rotationQuaternion = Quaternion.RotationAxis(axis, amount);
			this.rotationQuaternion = this.rotationQuaternion.multiply(rotationQuaternion);
		}
		else {
			if (this.parent != null) {
				var invertParentWorldMatrix = this.parent.getWorldMatrix().clone();
				invertParentWorldMatrix.invert();
				
				axis = Vector3.TransformNormal(axis, invertParentWorldMatrix);
			}
			rotationQuaternion = Quaternion.RotationAxis(axis, amount);
			this.rotationQuaternion = rotationQuaternion.multiply(this.rotationQuaternion);
		}
	}

	public function translate(axis:Vector3, distance:Float, ?space:Space) {
		var displacementVector = axis.scale(distance);
		
		if (space == null || space == Space.LOCAL) {
			var tempV3 = this.getPositionExpressedInLocalSpace().add(displacementVector);
			this.setPositionWithLocalVector(tempV3);
		}
		else {
			this.setAbsolutePosition(this.getAbsolutePosition().add(displacementVector));
		}
	}

	inline public function getAbsolutePosition():Vector3 {
		this.computeWorldMatrix();
		return this._absolutePosition;
	}

	public function setAbsolutePosition(?absolutePosition:Dynamic) {
		if (absolutePosition == null) {
			return;
		}
		<commit_msg>fix AbstractMesh.rotate() in Space.WORLD error<commit_after>package com.babylonhx.mesh;

import com.babylonhx.actions.ActionManager;
import com.babylonhx.bones.Bone;
import com.babylonhx.bones.Skeleton;
import com.babylonhx.cameras.Camera;
import com.babylonhx.collisions.Collider;
import com.babylonhx.collisions.IntersectionInfo;
import com.babylonhx.collisions.PickingInfo;
import com.babylonhx.culling.BoundingInfo;
import com.babylonhx.culling.BoundingSphere;
import com.babylonhx.culling.octrees.Octree;
import com.babylonhx.materials.Material;
import com.babylonhx.materials.MaterialDefines;
import com.babylonhx.math.Matrix;
import com.babylonhx.math.Plane;
import com.babylonhx.math.Axis;
import com.babylonhx.math.Quaternion;
import com.babylonhx.culling.Ray;
import com.babylonhx.math.Space;
import com.babylonhx.math.Tools;
import com.babylonhx.math.Vector3;
import com.babylonhx.math.Color3;
import com.babylonhx.math.Color4;
import com.babylonhx.math.Frustum;
import com.babylonhx.Node.NodeCache;
import com.babylonhx.physics.PhysicsEngine;
import com.babylonhx.physics.PhysicsBodyCreationOptions;
import com.babylonhx.rendering.EdgesRenderer;
import com.babylonhx.math.Tmp;
import com.babylonhx.utils.typedarray.Float32Array;

/**
 * ...
 * @author <NAME>
 */
 
@:expose('BABYLON.AbstractMesh') class AbstractMesh extends Node implements IDisposable {
	
	// Statics
	public static var BILLBOARDMODE_NONE:Int = 0;
	public static var BILLBOARDMODE_X:Int = 1;
	public static var BILLBOARDMODE_Y:Int = 2;
	public static var BILLBOARDMODE_Z:Int = 4;
	public static var BILLBOARDMODE_ALL:Int = 7;


	// Properties
	public var definedFacingForward:Bool = true; // orientation for POV movement & rotation
	public var position:Vector3 = new Vector3(0, 0, 0);
	public var rotation(get, set):Vector3;
	public var rotationQuaternion(get, set):Quaternion;
	public var scaling(get, set):Vector3;
	public var billboardMode:Int = AbstractMesh.BILLBOARDMODE_NONE;
	
	private var _rotation:Vector3 = new Vector3(0, 0, 0);
	private var _scaling:Vector3 = new Vector3(1, 1, 1);
	private var _rotationQuaternion:Quaternion;
	
	private var _visibility:Float = 1.0;
	public var visibility(get, set):Float;
	private function get_visibility():Float {
		return _visibility;
	}
	private function set_visibility(val:Float):Float {
		_visibility = val;
		return val;
	}	
	
	public var alphaIndex:Float = Math.POSITIVE_INFINITY;
	public var infiniteDistance:Bool = false;
	public var isVisible:Bool = true;	
	
	private var _isPickable:Bool = false;
	public var isPickable(get, set):Bool;
	private function get_isPickable():Bool {
		return _isPickable;
	}
	private function set_isPickable(val:Bool):Bool {
		_isPickable = val;
		return val;
	}
	
	public var showBoundingBox:Bool = false;
	public var showSubMeshesBoundingBox:Bool = false;
	public var onDispose:Void->Void = null;	
	public var isBlocker:Bool = false;	
	
	public var renderingGroupId:Int = 0;	
	
	private var _material:Material;
	public var material(get, set):Material;
	private function get_material():Material {
		return _material;
	}
	private function set_material(val:Material):Material {
		_material = val;
		return val;
	}
	
	private var _receiveShadows:Bool = false;
	public var receiveShadows(get, set):Bool;
	private function get_receiveShadows():Bool {
		return _receiveShadows;
	}
	private function set_receiveShadows(val:Bool):Bool {
		_receiveShadows = val;
		return val;
	}
	
	public var actionManager:ActionManager;
	public var renderOutline:Bool = false;
	public var outlineColor:Color3 = Color3.Red();
	public var outlineWidth:Float = 0.02;
	public var renderOverlay:Bool = false;
	public var overlayColor:Color3 = Color3.Red();
	public var overlayAlpha:Float = 0.5;
	public var hasVertexAlpha:Bool = false;
	public var useVertexColors:Bool = true;
	public var applyFog:Bool = true;
	public var computeBonesUsingShaders:Bool = true;
	public var scalingDeterminant:Float = 1;
	public var numBoneInfluencers:Int = 4;

	public var useOctreeForRenderingSelection:Bool = true;
	public var useOctreeForPicking:Bool = true;
	public var useOctreeForCollisions:Bool = true;

	public var layerMask:Int = 0x0FFFFFFF;
	
	// for bGUI
	public var __gui:Bool = false;
	
	public var alwaysSelectAsActiveMesh:Bool = false;

	// Physics
	public var _physicImpostor:Int = PhysicsEngine.NoImpostor;
	public var _physicsMass:Float = 0;
	public var _physicsFriction:Float = 0;
	public var _physicRestitution:Float = 0;
	public var onPhysicsCollide:AbstractMesh->Dynamic->Void; 

	// Collisions
	private var _checkCollisions:Bool = false;
	public var ellipsoid:Vector3 = new Vector3(0.5, 1, 0.5);
	public var ellipsoidOffset:Vector3 = new Vector3(0, 0, 0);
	private var _collider:Collider = new Collider();
	private var _oldPositionForCollisions:Vector3 = new Vector3(0, 0, 0);
	private var _diffPositionForCollisions:Vector3 = new Vector3(0, 0, 0);
	private var _newPositionForCollisions:Vector3 = new Vector3(0, 0, 0);
	public var onCollide:AbstractMesh->Void;
	public var onCollisionPositionChange:Vector3->Void;
	
	// Attach to bone
    private var _meshToBoneReferal:AbstractMesh;
	
	// Edges
	public var edgesWidth:Float = 1;
    public var edgesColor:Color4 = new Color4(1, 0, 0, 1);
	public var _edgesRenderer:EdgesRenderer;

	// Cache
	private var _localScaling:Matrix = Matrix.Zero();
	private var _localRotation:Matrix = Matrix.Zero();
	private var _localTranslation:Matrix = Matrix.Zero();
	private var _localBillboard:Matrix = Matrix.Zero();
	private var _localPivotScaling:Matrix = Matrix.Zero();
	private var _localPivotScalingRotation:Matrix = Matrix.Zero();
	private var _localMeshReferalTransform:Matrix;
	private var _localWorld:Matrix = Matrix.Zero();
	public var _worldMatrix:Matrix = Matrix.Zero();
	private var _rotateYByPI:Matrix = Matrix.RotationY(Math.PI);
	private var _absolutePosition:Vector3 = Vector3.Zero();
	private var _collisionsTransformMatrix:Matrix = Matrix.Zero();
	private var _collisionsScalingMatrix:Matrix = Matrix.Zero();	
	
	public var _savedMaterial:Material;
		
	private var _positions:Array<Vector3>;
	public var positions(get, set):Array<Vector3>;
	private function get_positions():Array<Vector3> {
		return _positions;
	}
	private function set_positions(val:Array<Vector3>):Array<Vector3> {
		_positions = val;
		return val;
	}
	
	public var useBones(get, never):Bool;
	private function get_useBones():Bool {
		return this.skeleton != null && this.getScene().skeletonsEnabled && this.isVerticesDataPresent(VertexBuffer.MatricesIndicesKind) && this.isVerticesDataPresent(VertexBuffer.MatricesWeightsKind);
	}
	
	private var _isDirty:Bool = false;
	public var _masterMesh:AbstractMesh;
	public var _materialDefines:MaterialDefines;

	public var _boundingInfo:BoundingInfo;
	private var _pivotMatrix:Matrix = Matrix.Identity();
	public var _isDisposed:Bool = false;
	public var _renderId:Int = 0;

	public var subMeshes:Array<SubMesh>;
	public var _submeshesOctree:Octree<SubMesh>;
	public var _intersectionsInProgress:Array<AbstractMesh> = [];
	
	private var _onAfterWorldMatrixUpdate:Array<AbstractMesh->Void> = [];
	
	private var _isWorldMatrixFrozen:Bool = false;
	
	public var _unIndexed:Bool = false;
	
	public var _poseMatrix:Matrix;
	
	// Loading properties
	public var _waitingActions:Dynamic;
	public var _waitingFreezeWorldMatrix:Bool;
	
	// Skeleton
	private var _skeleton:Skeleton;
	public var skeleton(get, set):Skeleton;
	public var _bonesTransformMatrices: #if (js || purejs || web || html5) Float32Array #else Array<Float> #end ;
	
	private function get_skeleton():Skeleton {
		return this._skeleton;
	}
	private function set_skeleton(value:Skeleton):Skeleton {
		if (this._skeleton != null && this._skeleton.needInitialSkinMatrix) {
			this._skeleton._unregisterMeshWithPoseMatrix(this);
		}
		
		if (value != null && value.needInitialSkinMatrix) {
			value._registerMeshWithPoseMatrix(this);
		}
		
		this._skeleton = value;
		
		if (this._skeleton == null) {
			this._bonesTransformMatrices = null;
		}
		
		return value;
	}
	

	public function new(name:String, scene:Scene) {
		super(name, scene);
		scene.addMesh(this);
		
		// TODO: macro ...
		#if purejs
		untyped __js__("Object.defineProperty(this, 'visibility', { get: this.get_visibility, set: this.set_visibility })");
		untyped __js__("Object.defineProperty(this, 'isPickable', { get: this.get_isPickable, set: this.set_isPickable })");
		untyped __js__("Object.defineProperty(this, 'skeleton', { get: this.get_skeleton, set: this.set_skeleton })");
		untyped __js__("Object.defineProperty(this, 'material', { get: this.get_material, set: this.set_material })");
		untyped __js__("Object.defineProperty(this, 'receiveShadows', { get: this.get_receiveShadows, set: this.set_receiveShadows })");
		untyped __js__("Object.defineProperty(this, 'positions', { get: this.get_positions, set: this.set_positions })");
		untyped __js__("Object.defineProperty(this, 'useBones', { get: this.get_useBones, set: this.set_useBones })");
		untyped __js__("Object.defineProperty(this, 'isBlocked', { get: this.get_isBlocked, set: this.set_isBlocked })");
		untyped __js__("Object.defineProperty(this, 'worldMatrixFromCache', { get: this.get_worldMatrixFromCache })");
		untyped __js__("Object.defineProperty(this, 'absolutePosition', { get: this.get_absolutePosition })");
		untyped __js__("Object.defineProperty(this, 'isWorldMatrixFrozen', { get: this.get_isWorldMatrixFrozen })");
		#end
	}
	
	/**
	 * Getting the rotation object. 
	 * If rotation quaternion is set, this vector will (almost always) be the Zero vector!
	 */
	private function get_rotation():Vector3 {
		return this._rotation;
	}
	private function set_rotation(newRotation:Vector3):Vector3 {
		return this._rotation = newRotation;
	}

	private function get_scaling():Vector3 {
		return this._scaling;
	}
	private function set_scaling(newScaling:Vector3):Vector3 {
		this._scaling = newScaling;
		/*if (this.physicsImpostor != null) {
			this.physicsImpostor.forceUpdate();
		}*/
		
		return newScaling;
	}

	private function get_rotationQuaternion():Quaternion {
		return this._rotationQuaternion;
	} 
	private function set_rotationQuaternion(?quaternion:Quaternion):Quaternion {
        this._rotationQuaternion = quaternion;
        //reset the rotation vector. 
		if (quaternion != null && this.rotation.length() > 0) {
			this.rotation.copyFromFloats(0, 0, 0);
		}
		
		return quaternion;
	}

	// Methods
	public function updatePoseMatrix(matrix:Matrix) {
		this._poseMatrix.copyFrom(matrix);
	}

	public function getPoseMatrix():Matrix {
		return this._poseMatrix;
	}
	
	public function disableEdgesRendering() {
        if (this._edgesRenderer != null) {
            this._edgesRenderer.dispose();
            this._edgesRenderer = null;
        }
    }
    public function enableEdgesRendering(epsilon:Float = 0.95, checkVerticesInsteadOfIndices:Bool = false) {
        this.disableEdgesRendering();
		
        this._edgesRenderer = new EdgesRenderer(this, epsilon, checkVerticesInsteadOfIndices);
    }
	
	private var _isBlocked:Bool;
	public var isBlocked(get, never):Bool;
	private function get_isBlocked():Bool {
		return false;
	}

	public function getLOD(camera:Camera, ?boundingSphere:BoundingSphere):AbstractMesh {
		return this;
	}

	public function getTotalVertices():Int {
		return 0;
	}

	public function getIndices(copyWhenShared:Bool = false):Array<Int> {
		return null;
	}

	public function getVerticesData(kind:String, copyWhenShared:Bool = false):Array<Float> {
		return null;
	}

	public function isVerticesDataPresent(kind:String):Bool {
		return false;
	}

	public function getBoundingInfo():BoundingInfo {
		if (this._masterMesh != null) {
			return this._masterMesh.getBoundingInfo();
		}
		
		if (this._boundingInfo == null) {
			this._updateBoundingInfo();
		}
		
		return this._boundingInfo;
	}
	
	public function _preActivate() { }
	
	public function _preActivateForIntermediateRendering(renderId:Int) { }
	
	public function _activate(renderId:Int) {
		this._renderId = renderId;
	}

	override public function getWorldMatrix():Matrix {
		if (this._masterMesh != null) {
			return this._masterMesh.getWorldMatrix();
		}
		
		if (this._currentRenderId != this.getScene().getRenderId()) {
			this.computeWorldMatrix();
		}
		
		return this._worldMatrix;
	}

	public var worldMatrixFromCache(get, never):Matrix;
	private function get_worldMatrixFromCache():Matrix {
		return this._worldMatrix;
	}

	public var absolutePosition(get, never):Vector3;
	private function get_absolutePosition():Vector3 {
		return this._absolutePosition;
	}
	
	inline public function freezeWorldMatrix() {
		this._isWorldMatrixFrozen = false;  // no guarantee world is not already frozen, switch off temporarily
        this.computeWorldMatrix(true);
        this._isWorldMatrixFrozen = true;
    }

    inline public function unfreezeWorldMatrix() {
        this._isWorldMatrixFrozen = false;
		this.computeWorldMatrix(true);
    }
	
	public var isWorldMatrixFrozen(get, never):Bool;
	private function get_isWorldMatrixFrozen():Bool {
        return this._isWorldMatrixFrozen;
    }

	public function rotate(axis:Vector3, amount:Float, space:Space) {
		axis.normalize();
		
		if (this.rotationQuaternion == null) {
			this.rotationQuaternion = Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z);
			this.rotation = Vector3.Zero();
		}
		
		if (space == null || space == Space.LOCAL) {
			var rotationQuaternion = Quaternion.RotationAxis(axis, amount);
			this.rotationQuaternion = this.rotationQuaternion.multiply(rotationQuaternion);
		}
		else {
			if (this.parent != null) {
				var invertParentWorldMatrix = this.parent.getWorldMatrix().clone();
				invertParentWorldMatrix.invert();
				
				axis = Vector3.TransformNormal(axis, invertParentWorldMatrix);
			}
			var rotationQuaternion = Quaternion.RotationAxis(axis, amount);
			this.rotationQuaternion = rotationQuaternion.multiply(this.rotationQuaternion);
		}
	}

	public function translate(axis:Vector3, distance:Float, ?space:Space) {
		var displacementVector = axis.scale(distance);
		
		if (space == null || space == Space.LOCAL) {
			var tempV3 = this.getPositionExpressedInLocalSpace().add(displacementVector);
			this.setPositionWithLocalVector(tempV3);
		}
		else {
			this.setAbsolutePosition(this.getAbsolutePosition().add(displacementVector));
		}
	}

	inline public function getAbsolutePosition():Vector3 {
		this.computeWorldMatrix();
		return this._absolutePosition;
	}

	public function setAbsolutePosition(?absolutePosition:Dynamic) {
		if (absolutePosition == null) {
			return;
		}
		
{'fraction_non_alphanumeric': 0.10565236742100037, 'fraction_numerical': 0.007874285323016879, 'mean_word_length': 5.13655462184874, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3811208', 'n_tokens_mistral': 10146, 'n_tokens_neox': 9283, 'n_words': 2021}