Merge remote-tracking branch 'origin/master'

This commit is contained in:
Leonid Gaev
2012-08-16 15:34:29 +06:00
17 changed files with 1736 additions and 1305 deletions

196
changelog_en.txt Normal file
View File

@@ -0,0 +1,196 @@
Changelog Alternativa3D
NEXT
----
Added:
+ Added:
+ Object3DUtils: setPosition, lookAt to Camera3D and converting between Radians and Degrees
+ Stage3D constrained profile support
+ BitmapTextureResource: auto resize for GPU option
+ MouseEvent3D: right and middle mouse buttons support (FP 11.2 and -swf-version=15 required)
+ Object3D: excludeLight()
+ OmniLightShadow: add omni radius in debug scale
+ Camera3D: light sorting
Fixed:
= Object3D.toString()
= AnimationClip: animated and loop properties in AnimationClip.slice(), AnimationClip.clone()
= Bubbling in MouseEvent3D
= ExporterA3D: export meshes without geometry as Object3D
= Box: correct tangents and binormals
= WireFrame:fix createBinormals()
= Decal: Fixed incorrect drawing with extremaly low nearClipping.
= View: Fixed bug with mouse events and postprosessing
= Several minor fixes
Removed:
-Diagram: removed CPU time
8.31.0
---
= Rendering optimizations
= Increased materials performance
= AnimationController:fixed error when using notifiers cause animation goes in infinite loop
= Camera3D: fixed a bug with duplicating diagram
8.30.0
---
Fixed:
= OmniLightShadow: fixed some errors and increased performance
= ParserCollada: loading Skin without normals and tangents
= ParserA3D: parsing scene with spot lights
= DirectionalLigthShadow, OmniLightShadow:default value of biasMultiplyer property was changed to 0.97
= StandardMaterial:removed traces
8.29.0
---
Added:
+ Possibility to use unlimited light sources and shadows count with StandardMaterial
+ A flag Object3D.useShadow which controls shadow visibility on object.
+ OmniLightShadow class
Fixed:
= Fixed issue with Skin lighting
= StandardMaterial does not throw exception about limitation number of light sources and shadows anymore.
8.27.0
----
Added:
+ Added DirectionalLightShadow class for calculation of shadow from directional light source.
+ ParserA3D: implemented import of animation, LOD objects and layers from binary format A3D.
+ ExporterA3D: implemented export of Skin class objects, animation and materials to binary format A3D.
+ Added rendering of materials with alpha-test and two-pass alpha-test.
API of materials has been changed: now, if you want to show objects with translucent textures, you must to set value of alphaThreshold.
+ Implemented EnvironmentMaterial with simulation of reflection on cube texture.
+ StandardMaterial: added ability to use pre-computed texture of light together with dynamic light.
+ Added check for maximum number of light sources influencing on object.
+ Added LOD class for switching of detail levels depending on the distance between camera and object.
+ Implemented Occluder class that removes objects, covered by obstacles from rendering.
+ Object3D: added field userData with type Object.
+ Skin, Joint: added methods of setting and calculation of bind position matrix.
+ Skin: implemented method of bound-box calculation, taking into account bone transformation.
+ Geometry: added calculateNormals() and calculateTangents() methods for calculation of normals and vertex tangents, respectively.
+ Added cloning methods at all materials and Camera3D class.
+ Added base Parser class, that is parent class for ParserA3D, ParserCollada and Parser3DS.
+ Camera3D: added display of average frame time and CPU calculation time in statistics.
+ ParserCollada: now you can import intensivity for light sources.
Fixed:
= Fixed incorrect engine work after changing of current Context3D.
= ExporterA3D: fixed the export of materials to binary format A3D.
= Fixed some problems with mouse events:
- mouse events at flash player version 11.1;
- mouse events at software rendering;
- mouse events with non-convex objects.
= VertexLightTextureMaterial: fixed incorrect light from SpotLight.
= Object3D: removed incorrect dispatch of events Event3D.ADDED, Event3D.REMOVED when you re-add object to its parent.
= AmbientLight, DirectionalLight: fixed calculation of bound-box.
= Wireframe: fixed bug with incorrect thickness of lines on some sizes of view.
= Optimized playing of animation.
= Accelerated the import and creation of animation using format parser.
= View: fixed joint work with Flash-profiler.
Removed:
- Removed support of Flash Player Incubator.
- TextureMaterial: removed parameter useDiffuseAlphaChannel.
- Skin: parameter numJoints removed from constructor.
8.17.0
----
+ ParserA3D: added the import of objects of Skin type and the import of light sources.
+ Added Parser3DS class for import models from 3DS format.
+ Added intersectRay() - The method of finding a ray intersects with an object of Mesh type.
+ Added AxisAlignedSprite class to display plane oriented along one axis to the camera.
+ Export to the binary format A3D is supported.
+ Added debug mode displaying of objects bounds.
+ Added primitive Plane.
+ GeoSphere primitive has normals and tangents of vertices after creation.
+ Normalmaps supported with left-sided system of coordinates in StandardMaterial.
= Decal: removed the offset property and changed the logic of work.
= StandardMaterial: fixed a bug with lighting of some light sources.
= FillMaterial: color in construstor is grey by default now.
= Box: constructor is optimized.
= Box: fixed a bug in the cloning of the primitive. Surfaces is not duplicated now.
= WireFrame.getResources() allows parameter resourceType now.
8.12.0
----
+ The Public version Flash Player 11 Beta 2 is now supported.
+ The orthographic mode has been added to the Camera3D.
+ The MouseEvent system has been optimized and accelerated.
+ Logo "AlternativaPltaform" has been updated.
+ Now when objects are added and removed from the parent, the event will be sent (Event3D.ADDED, Event3D.REMOVED).
+ The ability to change the property renderToBitmap into View after creating has been added.
= The height and width of the View has been limited to the minimum size of 50x50.
= Bug in mouse events system when used skins divided on surfaces by divide() was fixed.
= A bug has been fixed in Decal.
= Skin lighting algorithm changed to more precise one.
= ParserCollada: Fixed a bug when binormal vector of the vertices of the object was incorrectly parsed.
= The value of backgroundAlpha in the View constructor changed to 1.0 by default.
= VertexLightTextureMaterial now draws correctly without lights in scene.
= MouseEvent3D was moved from alternativa.engine3d.core to alternativa.engine3d.core.events.
= A bug has been fixed in Object3D.dispatchEvent().
= The offset property has been added to the constructor Decal and it is compulsory.
= Now the offset property can be copied using the clone () method of class Decal.
- The ratio property has been removed from View class.
- VertexLightTextureMaterial now can be used with skin with the maximum number of bones in surface no more than 33.
8.8.0
----
- TextureMaterial, VertexLightMaterial, LightmapMaterial now supports the map-transparency and alpha property.
- Added EllipsoidCollider class for continuous collision detection.
- Added Decal class for detalization of texture on models.
- WireFrame class was added.
- New class SkyBox was added.
- StandardMaterial supports Object-space normal maps now.
- StandardMaterial supports glossiness maps now
- Property alwaysOnTop was added in the Sprite.
- clone() method was added to Skin.
- concatenatedMatrix property was added in Object3D.
- Primitive Box contains vertex tangents now.
- ParserA3D: glossiness and opacity maps are supported now.
- Parsing of Skin with animation from collada was fixed.
- ParserCollada: a bug, when model without vertex normals parsed, was fixed.
- Lighting in StandartMaterial, VertexLightMaterial, when models have non-identity scale, was fixed.
- View can be any size now without throwing exceptions.
- Mouse events work properly now after creating the View with zero width or height.
- Bug with culling of scaled objects in camera frustum was fixed.
- A bug in dispose() method of Geometry class was fixed.
- DirectionalLight: bug with wrong light direction after parsing from Collada was fixed.
- ParserA3D: bug with wrong textures assignment was fixed.
- ParserA3D: vertex tangents are supported now.
- ParserA3D: bug, when Geometry methods worked incorrectly on a parsed model, was fixed.
- FileTextureResource: after a repeated call to upload() the resource is not destroyed now.
- FileTextureResource: you can get and set the texture data now.
- FileTextureResource renamed to ExternalTextureResource.
- ColladaMaterial renamed to ParserMaterial.
- Surface: owner property renamed to object.
- Geometry: findVertexBufferByAttribute renamed to findVertexStreamByAttribute.
- Sprite3D: StandartMaterial and VertexLightMaterial are not supported with it now.
- Fillmaterial: the color property has uint type now.
8.5.0
-----
- GPU support
- Directional, omni, spot lights
- Hierarchical exclusion of light sources
- Material with normal, specular, opacity mapping
- Lightmap Material
- Vertex light Material
- Fill Material
- Skin
- Skin subdividing
- Semi-transparent Material
- Mesh with several materials
- Sprite
- Animated Sprite
- GPU-based MouseEvents
- ATF textures loading
- Collada loading
- Binary A3D loading
- Drawing to DisplayObject mode
- Animation engine
- Hierarchical Animated blending tree

View File

@@ -465,6 +465,8 @@ package alternativa.engine3d.animation {
*/
public function slice(start:Number, end:Number = Number.MAX_VALUE):AnimationClip {
var sliced:AnimationClip = new AnimationClip(name);
sliced.animated = animated;
sliced.loop = loop;
sliced._objects = (_objects == null) ? null : [].concat(_objects);
for (var i:int = 0; i < _numTracks; i++) {
sliced.addTrack(_tracks[i].slice(start, end));
@@ -477,6 +479,8 @@ package alternativa.engine3d.animation {
*/
public function clone():AnimationClip {
var cloned:AnimationClip = new AnimationClip(name);
cloned.animated = animated;
cloned.loop = loop;
cloned._objects = (_objects == null) ? null : [].concat(_objects);
for (var i:int = 0; i < _numTracks; i++) {
cloned.addTrack(_tracks[i]);

View File

@@ -46,6 +46,12 @@ package alternativa.engine3d.core {
*/
public class Camera3D extends Object3D {
/**
* @private
* Key - context, value - properties.
*/
alternativa3d static var context3DPropertiesPool:Dictionary = new Dictionary(true);
/**
* The viewport defines part of screen to which renders image seen by the camera.
* If viewport is not defined, the camera would not draws anything.
@@ -156,6 +162,11 @@ public class Camera3D extends Object3D {
*/
alternativa3d var context3D:Context3D;
/**
* @private
*/
alternativa3d var context3DProperties:RendererContext3DProperties;
/**
* @private
* Camera's renderer. If is not defined, the camera will no draw anything.
@@ -195,7 +206,6 @@ public class Camera3D extends Object3D {
* @param stage3D <code>Stage3D</code> to which image will be rendered.
*/
public function render(stage3D:Stage3D):void {
// TODO: don't check mouse events if no listeners
var i:int;
var j:int;
var light:Light3D;
@@ -214,13 +224,27 @@ public class Camera3D extends Object3D {
ambient[2] = 0;
ambient[3] = 1;
// Receiving the context
context3D = stage3D.context3D;
var currentContext3D:Context3D = stage3D.context3D;
if (currentContext3D != context3D) {
if (currentContext3D != null) {
context3DProperties = context3DPropertiesPool[currentContext3D];
if (context3DProperties == null) {
context3DProperties = new RendererContext3DProperties();
context3DProperties.isConstrained = currentContext3D.driverInfo.lastIndexOf("(Baseline Constrained)") >= 0;
context3DPropertiesPool[currentContext3D] = context3DProperties;
}
context3D = currentContext3D;
} else {
context3D = null;
context3DProperties = null;
}
}
if (context3D != null && view != null && renderer != null && (view.stage != null || view._canvas != null)) {
renderer.camera = this;
// Projection argument calculating
calculateProjection(view._width, view._height);
// Preparing to rendering
view.prepareToRender(stage3D, context3D);
view.configureContext3D(stage3D, context3D, this);
// Transformations calculating
if (transformChanged) composeTransforms();
localToGlobalTransform.copy(transform);
@@ -236,14 +260,12 @@ public class Camera3D extends Object3D {
// Check if object of hierarchy is visible
if (root.visible) {
globalMouseHandlingType = 0;
// Calculating the matrix to transform from the camera space to local space
root.cameraToLocalTransform.combine(root.inverseTransform, localToGlobalTransform);
// Calculating the matrix to transform from local space to the camera space
root.localToCameraTransform.combine(globalToLocalTransform, root.transform);
if (root.mouseEnabled) globalMouseHandlingType |= root.mouseHandlingType;
globalMouseHandlingType = root.mouseHandlingType;
// Checking the culling
if (root.boundBox != null) {
calculateFrustum(root.cameraToLocalTransform);
@@ -251,7 +273,7 @@ public class Camera3D extends Object3D {
} else {
root.culling = 63;
}
// Calculations of conent visibility
// Calculations of content visibility
if (root.culling >= 0) root.calculateVisibility(this);
// Calculations visibility of children
root.calculateChildrenVisibility(this);
@@ -334,6 +356,16 @@ public class Camera3D extends Object3D {
}
raysLength = view.raysLength;
var r:Number = ((view.backgroundColor >> 16) & 0xff)/0xff;
var g:Number = ((view.backgroundColor >> 8) & 0xff)/0xff;
var b:Number = (view.backgroundColor & 0xff)/0xff;
if (view._canvas != null) {
r *= view.backgroundAlpha;
g *= view.backgroundAlpha;
b *= view.backgroundAlpha;
}
context3D.clear(r, g, b, view.backgroundAlpha);
// Check getting in frustum and occluding
if (root.culling >= 0 && (root.boundBox == null || occludersLength == 0 || !root.boundBox.checkOcclusion(occluders, occludersLength, root.localToCameraTransform))) {
// Check if the ray crossing the bounding box
@@ -387,7 +419,6 @@ public class Camera3D extends Object3D {
}
// Gather the draws for children
root.collectChildrenDraws(this, lights, lightsLength, root.useShadow);
// Mouse events prosessing
view.processMouseEvents(context3D, this);
// Render
@@ -405,7 +436,6 @@ public class Camera3D extends Object3D {
lights.length = 0;
childLights.length = 0;
occluders.length = 0;
context3D = null;
}
/**
@@ -424,7 +454,7 @@ public class Camera3D extends Object3D {
var deltaX:Number = x - this.x;
var deltaY:Number = y - this.y;
var deltaZ:Number = z - this.z;
var rotX = Math.atan2(deltaZ, Math.sqrt(deltaX * deltaX + deltaY * deltaY));
var rotX:Number = Math.atan2(deltaZ, Math.sqrt(deltaX * deltaX + deltaY * deltaY));
rotationX = rotX - 0.5 * Math.PI;
rotationY = 0;
rotationZ = - Math.atan2(deltaX,deltaY);

View File

@@ -172,26 +172,53 @@ package alternativa.engine3d.core {
*/
public class Object3D implements IEventDispatcher {
// Mouse moving
private static const MOUSE_MOVE_BIT:uint = 1;
private static const MOUSE_OVER_BIT:uint = 2;
private static const MOUSE_OUT_BIT:uint = 4;
private static const ROLL_OVER_BIT:uint = 0x8;
private static const ROLL_OUT_BIT:uint = 0x10;
private static const USE_HAND_CURSOR_BIT:uint = 0x20;
// Mouse pressing
private static const MOUSE_DOWN_BIT:uint = 0x40;
private static const MOUSE_UP_BIT:uint = 0x80;
private static const CLICK_BIT:uint = 0x100;
private static const DOUBLE_CLICK_BIT:uint = 0x200;
// Mouse wheel
private static const MOUSE_WHEEL_BIT:uint = 0x400;
// Mouse middle button
private static const MIDDLE_CLICK_BIT:uint = 0x800;
private static const MIDDLE_MOUSE_DOWN_BIT:uint = 0x1000;
private static const MIDDLE_MOUSE_UP_BIT:uint = 0x2000;
// Mouse right button
private static const RIGHT_CLICK_BIT:uint = 0x4000;
private static const RIGHT_MOUSE_DOWN_BIT:uint = 0x8000;
private static const RIGHT_MOUSE_UP_BIT:uint = 0x10000;
/**
* @private
*/
alternativa3d static const MOUSE_HANDLING_MOVING:uint = 1;
alternativa3d static const MOUSE_HANDLING_MOVING:uint = MOUSE_MOVE_BIT | MOUSE_OVER_BIT | MOUSE_OUT_BIT | ROLL_OVER_BIT | ROLL_OUT_BIT | USE_HAND_CURSOR_BIT;
/**
* @private
*/
alternativa3d static const MOUSE_HANDLING_PRESSING:uint = 2;
alternativa3d static const MOUSE_HANDLING_PRESSING:uint = MOUSE_DOWN_BIT | MOUSE_UP_BIT | CLICK_BIT | DOUBLE_CLICK_BIT;
/**
* @private
*/
alternativa3d static const MOUSE_HANDLING_WHEEL:uint = 4;
alternativa3d static const MOUSE_HANDLING_WHEEL:uint = MOUSE_WHEEL_BIT;
/**
* @private
*/
alternativa3d static const MOUSE_HANDLING_MIDDLE_BUTTON:uint = 8;
alternativa3d static const MOUSE_HANDLING_MIDDLE_BUTTON:uint = MIDDLE_CLICK_BIT | MIDDLE_MOUSE_DOWN_BIT | MIDDLE_MOUSE_UP_BIT;
/**
* @private
*/
alternativa3d static const MOUSE_HANDLING_RIGHT_BUTTON:uint = 16;
alternativa3d static const MOUSE_HANDLING_RIGHT_BUTTON:uint = RIGHT_CLICK_BIT | RIGHT_MOUSE_DOWN_BIT | RIGHT_MOUSE_UP_BIT;
/**
* Custom data available to store within <code>Object3D</code> by user.
@@ -249,12 +276,6 @@ package alternativa.engine3d.core {
*/
public var doubleClickEnabled:Boolean = false;
/**
* A Boolean value that indicates whether the pointing hand (hand cursor)
* appears when the pointer rolls over a <code>Object3D</code>.
*/
public var useHandCursor:Boolean = false;
/**
* Bounds of the object described as rectangular parallelepiped.
*/
@@ -587,6 +608,25 @@ package alternativa.engine3d.core {
transformChanged = true;
}
/**
* A Boolean value that indicates whether the pointing hand (hand cursor)
* appears when the pointer rolls over a <code>Object3D</code>.
*/
public function get useHandCursor():Boolean {
return (mouseHandlingType & USE_HAND_CURSOR_BIT) != 0;
}
/**
* @private
*/
public function set useHandCursor(value:Boolean):void {
if (value) {
mouseHandlingType |= USE_HAND_CURSOR_BIT;
} else {
mouseHandlingType &= ~USE_HAND_CURSOR_BIT;
}
}
/**
* Searches for the intersection of an <code>Object3D</code> and given ray, defined by <code>origin</code> and <code>direction</code>.
*
@@ -739,20 +779,56 @@ package alternativa.engine3d.core {
vector = new Vector.<Function>();
listeners[type] = vector;
if (type == MouseEvent3D.MOUSE_MOVE || type == MouseEvent3D.MOUSE_OVER || type == MouseEvent3D.MOUSE_OUT || type == MouseEvent3D.ROLL_OVER || type == MouseEvent3D.ROLL_OUT) {
mouseHandlingType |= MOUSE_HANDLING_MOVING;
}
if (type == MouseEvent3D.MOUSE_DOWN || type == MouseEvent3D.MOUSE_UP || type == MouseEvent3D.CLICK || type == MouseEvent3D.DOUBLE_CLICK) {
mouseHandlingType |= MOUSE_HANDLING_PRESSING;
}
if (type == MouseEvent3D.MOUSE_WHEEL) {
mouseHandlingType |= MOUSE_HANDLING_WHEEL;
}
if (type == MouseEvent3D.MIDDLE_CLICK || type == MouseEvent3D.MIDDLE_MOUSE_DOWN || type == MouseEvent3D.MIDDLE_MOUSE_UP) {
mouseHandlingType |= MOUSE_HANDLING_MIDDLE_BUTTON;
}
if (type == MouseEvent3D.RIGHT_CLICK || type == MouseEvent3D.RIGHT_MOUSE_DOWN || type == MouseEvent3D.RIGHT_MOUSE_UP) {
mouseHandlingType |= MOUSE_HANDLING_RIGHT_BUTTON;
// update mouseHandlingType bits
switch (type) {
case MouseEvent3D.MOUSE_MOVE:
mouseHandlingType |= MOUSE_MOVE_BIT;
break;
case MouseEvent3D.MOUSE_OVER:
mouseHandlingType |= MOUSE_OVER_BIT;
break;
case MouseEvent3D.MOUSE_OUT:
mouseHandlingType |= MOUSE_OUT_BIT;
break;
case MouseEvent3D.ROLL_OVER:
mouseHandlingType |= ROLL_OVER_BIT;
break;
case MouseEvent3D.ROLL_OUT:
mouseHandlingType |= ROLL_OUT_BIT;
break;
case MouseEvent3D.MOUSE_DOWN:
mouseHandlingType |= MOUSE_DOWN_BIT;
break;
case MouseEvent3D.MOUSE_UP:
mouseHandlingType |= MOUSE_UP_BIT;
break;
case MouseEvent3D.CLICK:
mouseHandlingType |= CLICK_BIT;
break;
case MouseEvent3D.DOUBLE_CLICK:
mouseHandlingType |= DOUBLE_CLICK_BIT;
break;
case MouseEvent3D.MOUSE_WHEEL:
mouseHandlingType |= MOUSE_WHEEL_BIT;
break;
case MouseEvent3D.MIDDLE_CLICK:
mouseHandlingType |= MIDDLE_CLICK_BIT;
break;
case MouseEvent3D.MIDDLE_MOUSE_DOWN:
mouseHandlingType |= MIDDLE_MOUSE_DOWN_BIT;
break;
case MouseEvent3D.MIDDLE_MOUSE_UP:
mouseHandlingType |= MIDDLE_MOUSE_UP_BIT;
break;
case MouseEvent3D.RIGHT_CLICK:
mouseHandlingType |= RIGHT_CLICK_BIT;
break;
case MouseEvent3D.RIGHT_MOUSE_DOWN:
mouseHandlingType |= RIGHT_MOUSE_DOWN_BIT;
break;
case MouseEvent3D.RIGHT_MOUSE_UP:
mouseHandlingType |= RIGHT_MOUSE_UP_BIT;
break;
}
}
if (vector.indexOf(listener) < 0) {
@@ -781,7 +857,68 @@ package alternativa.engine3d.core {
if (length > 1) {
vector.length = length - 1;
} else {
// update mouseHandlingType bits
var noListeners:Boolean;
if (listeners == captureListeners) {
noListeners = (bubbleListeners == null || bubbleListeners[type] == null);
} else {
noListeners = (captureListeners == null || captureListeners[type] == null);
}
if (noListeners) {
switch (type) {
case MouseEvent3D.MOUSE_MOVE:
mouseHandlingType &= ~MOUSE_MOVE_BIT;
break;
case MouseEvent3D.MOUSE_OVER:
mouseHandlingType &= ~MOUSE_OVER_BIT;
break;
case MouseEvent3D.MOUSE_OUT:
mouseHandlingType &= ~MOUSE_OUT_BIT;
break;
case MouseEvent3D.ROLL_OVER:
mouseHandlingType &= ~ROLL_OVER_BIT;
break;
case MouseEvent3D.ROLL_OUT:
mouseHandlingType &= ~ROLL_OUT_BIT;
break;
case MouseEvent3D.MOUSE_DOWN:
mouseHandlingType &= ~MOUSE_DOWN_BIT;
break;
case MouseEvent3D.MOUSE_UP:
mouseHandlingType &= ~MOUSE_UP_BIT;
break;
case MouseEvent3D.CLICK:
mouseHandlingType &= ~CLICK_BIT;
break;
case MouseEvent3D.DOUBLE_CLICK:
mouseHandlingType &= ~DOUBLE_CLICK_BIT;
break;
case MouseEvent3D.MOUSE_WHEEL:
mouseHandlingType &= ~MOUSE_WHEEL_BIT;
break;
case MouseEvent3D.MIDDLE_CLICK:
mouseHandlingType &= ~MIDDLE_CLICK_BIT;
break;
case MouseEvent3D.MIDDLE_MOUSE_DOWN:
mouseHandlingType &= ~MIDDLE_MOUSE_DOWN_BIT;
break;
case MouseEvent3D.MIDDLE_MOUSE_UP:
mouseHandlingType &= ~MIDDLE_MOUSE_UP_BIT;
break;
case MouseEvent3D.RIGHT_CLICK:
mouseHandlingType &= ~RIGHT_CLICK_BIT;
break;
case MouseEvent3D.RIGHT_MOUSE_DOWN:
mouseHandlingType &= ~RIGHT_MOUSE_DOWN_BIT;
break;
case MouseEvent3D.RIGHT_MOUSE_UP:
mouseHandlingType &= ~RIGHT_MOUSE_UP_BIT;
break;
}
}
delete listeners[type];
var key:*;
for (key in listeners) break;
if (!key) {
@@ -791,21 +928,6 @@ package alternativa.engine3d.core {
bubbleListeners = null;
}
}
if (type == MouseEvent3D.MOUSE_MOVE || type == MouseEvent3D.MOUSE_OVER || type == MouseEvent3D.MOUSE_OUT || type == MouseEvent3D.ROLL_OVER || type == MouseEvent3D.ROLL_OUT) {
mouseHandlingType &= ~MOUSE_HANDLING_MOVING;
}
if (type == MouseEvent3D.MOUSE_DOWN || type == MouseEvent3D.MOUSE_UP || type == MouseEvent3D.CLICK || type == MouseEvent3D.DOUBLE_CLICK) {
mouseHandlingType &= ~MOUSE_HANDLING_PRESSING;
}
if (type == MouseEvent3D.MOUSE_WHEEL) {
mouseHandlingType &= ~MOUSE_HANDLING_WHEEL;
}
if (type == MouseEvent3D.MIDDLE_CLICK || type == MouseEvent3D.MIDDLE_MOUSE_DOWN || type == MouseEvent3D.MIDDLE_MOUSE_UP) {
mouseHandlingType &= ~MOUSE_HANDLING_MIDDLE_BUTTON;
}
if (type == MouseEvent3D.RIGHT_CLICK || type == MouseEvent3D.RIGHT_MOUSE_DOWN || type == MouseEvent3D.RIGHT_MOUSE_UP) {
mouseHandlingType &= ~MOUSE_HANDLING_RIGHT_BUTTON;
}
}
}
}
@@ -1401,7 +1523,7 @@ package alternativa.engine3d.core {
// Calculating matrix for converting from local coordinates to camera coordinates
child.localToCameraTransform.combine(localToCameraTransform, child.transform);
if (child.mouseEnabled) camera.globalMouseHandlingType |= child.mouseHandlingType;
camera.globalMouseHandlingType |= child.mouseHandlingType;
// Culling checking
if (child.boundBox != null) {
camera.calculateFrustum(child.cameraToLocalTransform);
@@ -1531,7 +1653,12 @@ package alternativa.engine3d.core {
/**
* Toggle off light source from litting this object
* Disables lighting of the object by given <code>light</code>.
*
* @param light Light which should not affect to the object
* @param updateChildren If <code>true</code> all children of this object will be also shielded from the given light.
* @see #excludedLights()
* @see #clearExcludedLights()
*/
public function excludeLight(light:Light3D, updateChildren:Boolean = false):void{
if (_excludedLights.indexOf(light) < 0) {
@@ -1552,7 +1679,7 @@ package alternativa.engine3d.core {
}
/**
* Resets list of lights excluded from litting this object
* Resets list of lights excluded from lighting this object.
*/
public function clearExcludedLights(updateChildren:Boolean = false):void {
_excludedLights.length = 0;
@@ -1564,7 +1691,7 @@ package alternativa.engine3d.core {
}
/**
* Returns a copy of object
* Returns a copy of object.
* @return A copy of this <code>Object3D</code>.
*/
public function clone():Object3D {
@@ -1614,7 +1741,8 @@ package alternativa.engine3d.core {
*/
public function toString():String {
var className:String = getQualifiedClassName(this);
return "[" + className.substr(className.indexOf("::") + 2) + " " + name + "]";
var start:int = className.indexOf("::");
return "[" + (start < 0 ? className : className.substr(start + 2)) + " " + name + "]";
}
}

View File

@@ -4,8 +4,8 @@
* You may add additional accurate notices of copyright ownership.
*
* It is desirable to notify that Covered Software was "Powered by AlternativaPlatform" with link to http://www.alternativaplatform.com/
* */
*
*/
package alternativa.engine3d.core {
import alternativa.engine3d.alternativa3d;
@@ -16,7 +16,6 @@ package alternativa.engine3d.core {
import flash.display3D.Context3DProgramType;
import flash.display3D.IndexBuffer3D;
import flash.display3D.Program3D;
import flash.utils.Dictionary;
use namespace alternativa3d;
@@ -37,9 +36,6 @@ package alternativa.engine3d.core {
public static const NEXT_LAYER:int = 50;
// Key - context, value - properties.
protected static var properties:Dictionary = new Dictionary(true);
// Collector
protected var collector:DrawUnit;
@@ -47,7 +43,6 @@ package alternativa.engine3d.core {
alternativa3d var drawUnits:Vector.<DrawUnit> = new Vector.<DrawUnit>();
protected var _context3D:Context3D;
protected var _contextProperties:RendererContext3DProperties;
alternativa3d function render(context3D:Context3D):void {
@@ -59,29 +54,29 @@ package alternativa.engine3d.core {
if (list != null) {
switch (i) {
case SKY:
_context3D.setDepthTest(false, Context3DCompareMode.ALWAYS);
context3D.setDepthTest(false, Context3DCompareMode.ALWAYS);
break;
case OPAQUE:
_context3D.setDepthTest(true, Context3DCompareMode.LESS);
context3D.setDepthTest(true, Context3DCompareMode.LESS);
break;
case OPAQUE_OVERHEAD:
_context3D.setDepthTest(false, Context3DCompareMode.EQUAL);
context3D.setDepthTest(false, Context3DCompareMode.EQUAL);
break;
case DECALS:
_context3D.setDepthTest(false, Context3DCompareMode.LESS_EQUAL);
context3D.setDepthTest(false, Context3DCompareMode.LESS_EQUAL);
break;
case TRANSPARENT_SORT:
if (list.next != null) list = sortByAverageZ(list);
_context3D.setDepthTest(false, Context3DCompareMode.LESS);
context3D.setDepthTest(false, Context3DCompareMode.LESS);
break;
case NEXT_LAYER:
_context3D.setDepthTest(false, Context3DCompareMode.ALWAYS);
context3D.setDepthTest(false, Context3DCompareMode.ALWAYS);
break;
}
// Rendering
while (list != null) {
var next:DrawUnit = list.next;
renderDrawUnit(list, _context3D, camera);
renderDrawUnit(list, context3D, camera);
// Send to collector
list.clear();
list.next = collector;
@@ -90,6 +85,7 @@ package alternativa.engine3d.core {
}
}
}
// TODO: not free buffers and textures in each renderer, only when full camera cycle finishes.
freeContext3DProperties(context3D);
// Clear
drawUnits.length = 0;
@@ -180,14 +176,7 @@ package alternativa.engine3d.core {
}
protected function updateContext3D(value:Context3D):void {
if (_context3D != value) {
_contextProperties = properties[value];
if (_contextProperties == null) {
_contextProperties = new RendererContext3DProperties();
properties[value] = _contextProperties;
}
_context3D = value;
}
_contextProperties = camera.context3DProperties;
}
/**

View File

@@ -8,7 +8,11 @@
package alternativa.engine3d.core {
import alternativa.engine3d.materials.ShaderProgram;
import alternativa.engine3d.resources.Geometry;
import flash.display3D.Program3D;
import flash.utils.Dictionary;
/**
* @private
@@ -16,6 +20,12 @@ package alternativa.engine3d.core {
*/
public class RendererContext3DProperties {
public var isConstrained:Boolean = false;
public var backBufferWidth:int = -1;
public var backBufferHeight:int = -1;
public var backBufferAntiAlias:int = -1;
public var usedBuffers:uint = 0;
public var usedTextures:uint = 0;
@@ -24,5 +34,11 @@ package alternativa.engine3d.core {
public var blendSource:String;
public var blendDestination:String;
// View: mouse events
// Key - vertex program of object, value - program.
public var drawDistancePrograms:Dictionary = new Dictionary();
public var drawColoredRectProgram:ShaderProgram;
public var drawRectGeometry:Geometry;
}
}

View File

@@ -61,10 +61,6 @@ package alternativa.engine3d.core {
private static const renderEvent:MouseEvent = new MouseEvent("render");
private static var properties:Dictionary = new Dictionary(true);
private var cachedContext3D:Context3D;
private var context3DProperties:Context3DViewProperties;
static private var drawDistanceFragment:Linker;
static private var drawDistanceVertexProcedure:Procedure;
@@ -309,6 +305,11 @@ package alternativa.engine3d.core {
addEventListener(Event.REMOVED_FROM_STAGE, onRemoveFromStage);
}
/**
* If <code>true</code>, you will able to handle following events <code>MouseEvent3D.RIGHT_CLICK</code>,
* <code>MouseEvent3D.RIGHT_MOUSE_DOWN</code>, <code>MouseEvent3D.RIGHT_MOUSE_UP</code>.
* The context menu will no longer open on clicking right mouse button.
*/
public function get rightClick3DEnabled():Boolean {
return _rightClick3DEnabled;
}
@@ -533,7 +534,7 @@ package alternativa.engine3d.core {
/**
* @private
*/
alternativa3d function prepareToRender(stage3D:Stage3D, context:Context3D):void {
alternativa3d function configureContext3D(stage3D:Stage3D, context3D:Context3D, camera:Camera3D):void {
if (_canvas == null) {
var vis:Boolean = this.visible;
for (var parent:DisplayObject = this.parent; parent != null; parent = parent.parent) {
@@ -553,70 +554,55 @@ package alternativa.engine3d.core {
createRenderBitmap();
}
}
if (context != cachedContext3D) {
// Get properties.
cachedContext3D = context;
context3DProperties = properties[cachedContext3D];
if (context3DProperties == null) {
context3DProperties = new Context3DViewProperties();
// Inititalize data for mouse events
var rectGeometry:Geometry = new Geometry(4);
rectGeometry.addVertexStream([VertexAttributes.POSITION, VertexAttributes.POSITION, VertexAttributes.POSITION, VertexAttributes.TEXCOORDS[0], VertexAttributes.TEXCOORDS[0]]);
rectGeometry.setAttributeValues(VertexAttributes.POSITION, Vector.<Number>([0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1]));
rectGeometry.setAttributeValues(VertexAttributes.TEXCOORDS[0], Vector.<Number>([0, 0, 0, 1, 1, 1, 1, 0]));
rectGeometry.indices = Vector.<uint>([0, 1, 3, 2, 3, 1]);
rectGeometry.upload(context);
var vLinker:Linker = new Linker(Context3DProgramType.VERTEX);
vLinker.addProcedure(Procedure.compileFromArray([
"#a0=a0",
"#c0=c0",
"mul t0.x, a0.x, c0.x",
"mul t0.y, a0.y, c0.y",
"add o0.x, t0.x, c0.z",
"add o0.y, t0.y, c0.w",
"mov o0.z, a0.z",
"mov o0.w, a0.z",
]));
var fLinker:Linker = new Linker(Context3DProgramType.FRAGMENT);
fLinker.addProcedure(Procedure.compileFromArray([
"#c0=c0",
"mov o0, c0",
]));
var coloredRectProgram:ShaderProgram = new ShaderProgram(vLinker, fLinker);
coloredRectProgram.upload(context);
var context3DProperties:RendererContext3DProperties = camera.context3DProperties;
if (context3DProperties.drawRectGeometry == null) {
// Inititalize data for mouse events
var rectGeometry:Geometry = new Geometry(4);
rectGeometry.addVertexStream([VertexAttributes.POSITION, VertexAttributes.POSITION, VertexAttributes.POSITION, VertexAttributes.TEXCOORDS[0], VertexAttributes.TEXCOORDS[0]]);
rectGeometry.setAttributeValues(VertexAttributes.POSITION, Vector.<Number>([0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1]));
rectGeometry.setAttributeValues(VertexAttributes.TEXCOORDS[0], Vector.<Number>([0, 0, 0, 1, 1, 1, 1, 0]));
rectGeometry.indices = Vector.<uint>([0, 1, 3, 2, 3, 1]);
rectGeometry.upload(context3D);
var vLinker:Linker = new Linker(Context3DProgramType.VERTEX);
vLinker.addProcedure(Procedure.compileFromArray([
"#a0=a0",
"#c0=c0",
"mul t0.x, a0.x, c0.x",
"mul t0.y, a0.y, c0.y",
"add o0.x, t0.x, c0.z",
"add o0.y, t0.y, c0.w",
"mov o0.z, a0.z",
"mov o0.w, a0.z",
]));
var fLinker:Linker = new Linker(Context3DProgramType.FRAGMENT);
fLinker.addProcedure(Procedure.compileFromArray([
"#c0=c0",
"mov o0, c0",
]));
var coloredRectProgram:ShaderProgram = new ShaderProgram(vLinker, fLinker);
coloredRectProgram.upload(context3D);
context3DProperties.drawRectGeometry = rectGeometry;
context3DProperties.drawColoredRectProgram = coloredRectProgram;
properties[cachedContext3D] = context3DProperties;
}
context3DProperties.drawRectGeometry = rectGeometry;
context3DProperties.drawColoredRectProgram = coloredRectProgram;
}
if (_width != context3DProperties.backBufferWidth || _height != context3DProperties.backBufferHeight || antiAlias != context3DProperties.backBufferAntiAlias) {
context3DProperties.backBufferWidth = _width;
context3DProperties.backBufferHeight = _height;
context3DProperties.backBufferAntiAlias = antiAlias;
context.configureBackBuffer(_width, _height, antiAlias);
context3D.configureBackBuffer(_width, _height, antiAlias);
}
var r:Number = ((backgroundColor >> 16) & 0xff)/0xff;
var g:Number = ((backgroundColor >> 8) & 0xff)/0xff;
var b:Number = (backgroundColor & 0xff)/0xff;
if (canvas != null) {
r *= backgroundAlpha;
g *= backgroundAlpha;
b *= backgroundAlpha;
}
context.clear(r, g, b, backgroundAlpha);
}
/**
* @private
*/
alternativa3d function processMouseEvents(context:Context3D, camera:Camera3D):void {
alternativa3d function processMouseEvents(context3D:Context3D, camera:Camera3D):void {
var i:int;
// Mouse events
if (eventsLength > 0) {
if (surfacesLength > 0) {
// Calculating the depth
calculateSurfacesDepths(context, camera, _width, _height);
calculateSurfacesDepths(context3D, camera, _width, _height);
// Sorting by decreasing the depth
for (i = 0; i < raysLength; i++) {
var raySurfaces:Vector.<Surface> = raysSurfaces[i];
@@ -776,8 +762,8 @@ package alternativa.engine3d.core {
context.setVertexBufferAt(6, null);
context.setVertexBufferAt(7, null);
var drawRectGeometry:Geometry = context3DProperties.drawRectGeometry;
var drawColoredRectProgram:ShaderProgram = context3DProperties.drawColoredRectProgram;
var drawRectGeometry:Geometry = camera.context3DProperties.drawRectGeometry;
var drawColoredRectProgram:ShaderProgram = camera.context3DProperties.drawColoredRectProgram;
// Rectangle
var vLinker:Linker, fLinker:Linker;
@@ -883,7 +869,7 @@ package alternativa.engine3d.core {
var procedure:Procedure = procedures[index];
var object:Object3D = surface.object;
// Program
var drawDistanceProgram:ShaderProgram = context3DProperties.drawDistancePrograms[procedure];
var drawDistanceProgram:ShaderProgram = camera.context3DProperties.drawDistancePrograms[procedure];
if (drawDistanceProgram == null) {
// Assembling the vertex shader
var vertex:Linker = new Linker(Context3DProgramType.VERTEX);
@@ -902,7 +888,7 @@ package alternativa.engine3d.core {
drawDistanceProgram = new ShaderProgram(vertex, drawDistanceFragment);
drawDistanceProgram.fragmentShader.varyings = drawDistanceProgram.vertexShader.varyings;
drawDistanceProgram.upload(context);
context3DProperties.drawDistancePrograms[procedure] = drawDistanceProgram;
camera.context3DProperties.drawDistancePrograms[procedure] = drawDistanceProgram;
}
var buffer:VertexBuffer3D = geometry.getVertexBuffer(VertexAttributes.POSITION);
if (buffer == null) return;
@@ -1405,9 +1391,6 @@ package alternativa.engine3d.core {
}
}
import alternativa.engine3d.materials.ShaderProgram;
import alternativa.engine3d.resources.Geometry;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.MouseEvent;
@@ -1415,7 +1398,6 @@ import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.net.URLRequest;
import flash.net.navigateToURL;
import flash.utils.Dictionary;
class Logo extends Sprite {
@@ -1513,17 +1495,3 @@ class Logo extends Sprite {
}
}
class Context3DViewProperties {
public var backBufferWidth:int = -1;
public var backBufferHeight:int = -1;
public var backBufferAntiAlias:int = -1;
// Mouse events
// Key - vertex program of object, value - program.
public var drawDistancePrograms:Dictionary = new Dictionary();
public var drawColoredRectProgram:ShaderProgram;
public var drawRectGeometry:Geometry;
}

View File

@@ -310,6 +310,15 @@ package alternativa.engine3d.materials {
"mov v0, a0"
], "passLightMapUVProcedure");
/**
* @private
*/
alternativa3d static var fallbackTextureMaterial:TextureMaterial = new TextureMaterial();
/**
* @private
*/
alternativa3d static var fallbackLightMapMaterial:LightMapMaterial = new LightMapMaterial();
private var _normalMapSpace:int = NormalMapSpace.TANGENT_RIGHT_HANDED;
/**
@@ -815,6 +824,31 @@ package alternativa.engine3d.materials {
if (_normalMap != null && _normalMap._texture == null) return;
if (_reflectionMap != null && _reflectionMap._texture == null) return;
if (_lightMap != null && _lightMap._texture == null) return;
if (camera.context3DProperties.isConstrained) {
// fallback to simpler material
if (lightMap == null) {
fallbackTextureMaterial.diffuseMap = diffuseMap;
fallbackTextureMaterial.opacityMap = opacityMap;
fallbackTextureMaterial.alphaThreshold = alphaThreshold;
fallbackTextureMaterial.alpha = alpha;
fallbackTextureMaterial.opaquePass = opaquePass;
fallbackTextureMaterial.transparentPass = transparentPass;
fallbackTextureMaterial.collectDraws(camera, surface, geometry, lights, lightsLength, useShadow, objectRenderPriority);
} else {
fallbackLightMapMaterial.diffuseMap = diffuseMap;
fallbackLightMapMaterial.lightMap = lightMap;
fallbackLightMapMaterial.lightMapChannel = lightMapChannel;
fallbackLightMapMaterial.opacityMap = opacityMap;
fallbackLightMapMaterial.alphaThreshold = alphaThreshold;
fallbackLightMapMaterial.alpha = alpha;
fallbackLightMapMaterial.opaquePass = opaquePass;
fallbackLightMapMaterial.transparentPass = transparentPass;
fallbackLightMapMaterial.collectDraws(camera, surface, geometry, lights, lightsLength, useShadow, objectRenderPriority);
}
return;
}
var object:Object3D = surface.object;
// Program

View File

@@ -307,6 +307,15 @@ package alternativa.engine3d.materials {
"mov v0, a0"
], "passLightMapUVProcedure");
/**
* @private
*/
alternativa3d static var fallbackTextureMaterial:TextureMaterial = new TextureMaterial();
/**
* @private
*/
alternativa3d static var fallbackLightMapMaterial:LightMapMaterial = new LightMapMaterial();
/**
* Normal map.
*/
@@ -986,6 +995,30 @@ package alternativa.engine3d.materials {
// Check if textures uploaded in to the context.
if (opacityMap != null && opacityMap._texture == null || glossinessMap != null && glossinessMap._texture == null || specularMap != null && specularMap._texture == null || lightMap != null && lightMap._texture == null) return;
if (camera.context3DProperties.isConstrained) {
// fallback to simpler material
if (lightMap == null) {
fallbackTextureMaterial.diffuseMap = diffuseMap;
fallbackTextureMaterial.opacityMap = opacityMap;
fallbackTextureMaterial.alphaThreshold = alphaThreshold;
fallbackTextureMaterial.alpha = alpha;
fallbackTextureMaterial.opaquePass = opaquePass;
fallbackTextureMaterial.transparentPass = transparentPass;
fallbackTextureMaterial.collectDraws(camera, surface, geometry, lights, lightsLength, useShadow, objectRenderPriority);
} else {
fallbackLightMapMaterial.diffuseMap = diffuseMap;
fallbackLightMapMaterial.lightMap = lightMap;
fallbackLightMapMaterial.lightMapChannel = lightMapChannel;
fallbackLightMapMaterial.opacityMap = opacityMap;
fallbackLightMapMaterial.alphaThreshold = alphaThreshold;
fallbackLightMapMaterial.alpha = alpha;
fallbackLightMapMaterial.opaquePass = opaquePass;
fallbackLightMapMaterial.transparentPass = transparentPass;
fallbackLightMapMaterial.collectDraws(camera, surface, geometry, lights, lightsLength, useShadow, objectRenderPriority);
}
return;
}
var object:Object3D = surface.object;
// Buffers

View File

@@ -34,7 +34,7 @@ package alternativa.engine3d.materials {
use namespace alternativa3d;
/**
* The materiall fills surface with bitmap image in light-independent manner. Can draw a Skin with no more than 41 Joints per surface. See Skin.divide() for more details.
* The material fills surface with bitmap image in light-independent manner. Can draw a Skin with no more than 41 Joints per surface. See Skin.divide() for more details.
*
* To be drawn with this material, geometry shoud have UV coordinates.
* @see alternativa.engine3d.objects.Skin#divide()
@@ -113,19 +113,19 @@ package alternativa.engine3d.materials {
public var opacityMap:TextureResource;
/**
* If <code>true</code>, perform transparent pass. Parts of surface, cumulative alpha value of which is below than <code>alphaThreshold</code> draw within transparent pass.
* If <code>true</code>, perform transparent pass. Parts of surface, cumulative alpha value of which is below than <code>alphaThreshold</code> will be drawn within transparent pass.
* @see #alphaThreshold
*/
public var transparentPass:Boolean = true;
/**
* If <code>true</code>, perform opaque pass. Parts of surface, cumulative alpha value of which is greater or equal than <code>alphaThreshold</code> draw within opaque pass.
* If <code>true</code>, perform opaque pass. Parts of surface, cumulative alpha value of which is greater or equal than <code>alphaThreshold</code> will be drawn within opaque pass.
* @see #alphaThreshold
*/
public var opaquePass:Boolean = true;
/**
* alphaThreshold defines starts from which value of alpha a fragment of surface will get into transparent pass.
* alphaThreshold defines starts from which value of alpha a fragment of the surface will get into transparent pass.
* @see #transparentPass
* @see #opaquePass
*/

View File

@@ -98,6 +98,11 @@ package alternativa.engine3d.materials {
private static const _lightsProcedures:Dictionary = new Dictionary(true);
/**
* @private
*/
alternativa3d static var fallbackMaterial:TextureMaterial = new TextureMaterial();
/**
* Creates a new VertexLightTextureMaterial instance.
*
@@ -282,6 +287,18 @@ package alternativa.engine3d.materials {
override alternativa3d function collectDraws(camera:Camera3D, surface:Surface, geometry:Geometry, lights:Vector.<Light3D>, lightsLength:int, useShadow:Boolean, objectRenderPriority:int = -1):void {
if (diffuseMap == null || diffuseMap._texture == null || opacityMap != null && opacityMap._texture == null) return;
if (camera.context3DProperties.isConstrained) {
// fallback to texture material
fallbackMaterial.diffuseMap = diffuseMap;
fallbackMaterial.opacityMap = opacityMap;
fallbackMaterial.alphaThreshold = alphaThreshold;
fallbackMaterial.alpha = alpha;
fallbackMaterial.opaquePass = opaquePass;
fallbackMaterial.transparentPass = transparentPass;
fallbackMaterial.collectDraws(camera, surface, geometry, lights, lightsLength, useShadow, objectRenderPriority);
return;
}
var object:Object3D = surface.object;
// Buffers

View File

@@ -176,6 +176,7 @@ package alternativa.engine3d.objects {
* @private
*/
override alternativa3d function calculateVisibility(camera:Camera3D):void {
// TODO: optimize - use square of distance
var distance:Number = Math.sqrt(localToCameraTransform.d*localToCameraTransform.d + localToCameraTransform.h*localToCameraTransform.h + localToCameraTransform.l*localToCameraTransform.l);
for (level = levelList; level != null; level = level.next) {
if (distance <= level.distance) {
@@ -196,7 +197,7 @@ package alternativa.engine3d.objects {
// Calculation of transfer matrix from local space to camera.
child.localToCameraTransform.combine(parent.localToCameraTransform, child.transform);
if (child.mouseEnabled) camera.globalMouseHandlingType |= child.mouseHandlingType;
camera.globalMouseHandlingType |= child.mouseHandlingType;
// Pass
child.culling = parent.culling;
// Calculating visibility of the self content

View File

@@ -80,7 +80,7 @@ package alternativa.engine3d.objects {
private var bottomSurface:Surface;
private var topSurface:Surface;
private var size:Number;
private var halfSize:Number;
/**
* Creates a new SkyBox instance.
@@ -95,10 +95,7 @@ package alternativa.engine3d.objects {
* @see alternativa.engine3d.materials.Material
*/
public function SkyBox(size:Number, left:Material = null, right:Material = null, back:Material = null, front:Material = null, bottom:Material = null, top:Material = null, uvPadding:Number = 0) {
size *= 0.5;
this.size = size;
this.halfSize = size*0.5;
geometry = new Geometry(24);
@@ -111,35 +108,35 @@ package alternativa.engine3d.objects {
geometry.addVertexStream(attributes);
geometry.setAttributeValues(VertexAttributes.POSITION, Vector.<Number>([
-size, -size, size,
-size, -size, -size,
-size, size, -size,
-size, size, size,
-halfSize, -halfSize, halfSize,
-halfSize, -halfSize, -halfSize,
-halfSize, halfSize, -halfSize,
-halfSize, halfSize, halfSize,
size, size, size,
size, size, -size,
size, -size, -size,
size, -size, size,
halfSize, halfSize, halfSize,
halfSize, halfSize, -halfSize,
halfSize, -halfSize, -halfSize,
halfSize, -halfSize, halfSize,
size, -size, size,
size, -size, -size,
-size, -size, -size,
-size, -size, size,
halfSize, -halfSize, halfSize,
halfSize, -halfSize, -halfSize,
-halfSize, -halfSize, -halfSize,
-halfSize, -halfSize, halfSize,
-size, size, size,
-size, size, -size,
size, size, -size,
size, size, size,
-halfSize, halfSize, halfSize,
-halfSize, halfSize, -halfSize,
halfSize, halfSize, -halfSize,
halfSize, halfSize, halfSize,
-size, size, -size,
-size, -size, -size,
size, -size, -size,
size, size, -size,
-halfSize, halfSize, -halfSize,
-halfSize, -halfSize, -halfSize,
halfSize, -halfSize, -halfSize,
halfSize, halfSize, -halfSize,
-size, -size, size,
-size, size, size,
size, size, size,
size, -size, size
-halfSize, -halfSize, halfSize,
-halfSize, halfSize, halfSize,
halfSize, halfSize, halfSize,
halfSize, -halfSize, halfSize
]));
geometry.setAttributeValues(VertexAttributes.TEXCOORDS[0], Vector.<Number>([
@@ -214,44 +211,44 @@ package alternativa.engine3d.objects {
var dy:Number;
var dz:Number;
var len:Number;
dx = -size - cameraToLocalTransform.d;
dy = -size - cameraToLocalTransform.h;
dz = -size - cameraToLocalTransform.l;
dx = -halfSize - cameraToLocalTransform.d;
dy = -halfSize - cameraToLocalTransform.h;
dz = -halfSize - cameraToLocalTransform.l;
len = dx*dx + dy*dy + dz*dz;
if (len > max) max = len;
dx = size - cameraToLocalTransform.d;
dy = -size - cameraToLocalTransform.h;
dz = -size - cameraToLocalTransform.l;
dx = halfSize - cameraToLocalTransform.d;
dy = -halfSize - cameraToLocalTransform.h;
dz = -halfSize - cameraToLocalTransform.l;
len = dx*dx + dy*dy + dz*dz;
if (len > max) max = len;
dx = size - cameraToLocalTransform.d;
dy = size - cameraToLocalTransform.h;
dz = -size - cameraToLocalTransform.l;
dx = halfSize - cameraToLocalTransform.d;
dy = halfSize - cameraToLocalTransform.h;
dz = -halfSize - cameraToLocalTransform.l;
len = dx*dx + dy*dy + dz*dz;
if (len > max) max = len;
dx = -size - cameraToLocalTransform.d;
dy = size - cameraToLocalTransform.h;
dz = -size - cameraToLocalTransform.l;
dx = -halfSize - cameraToLocalTransform.d;
dy = halfSize - cameraToLocalTransform.h;
dz = -halfSize - cameraToLocalTransform.l;
len = dx*dx + dy*dy + dz*dz;
if (len > max) max = len;
dx = -size - cameraToLocalTransform.d;
dy = -size - cameraToLocalTransform.h;
dz = size - cameraToLocalTransform.l;
dx = -halfSize - cameraToLocalTransform.d;
dy = -halfSize - cameraToLocalTransform.h;
dz = halfSize - cameraToLocalTransform.l;
len = dx*dx + dy*dy + dz*dz;
if (len > max) max = len;
dx = size - cameraToLocalTransform.d;
dy = -size - cameraToLocalTransform.h;
dz = size - cameraToLocalTransform.l;
dx = halfSize - cameraToLocalTransform.d;
dy = -halfSize - cameraToLocalTransform.h;
dz = halfSize - cameraToLocalTransform.l;
len = dx*dx + dy*dy + dz*dz;
if (len > max) max = len;
dx = size - cameraToLocalTransform.d;
dy = size - cameraToLocalTransform.h;
dz = size - cameraToLocalTransform.l;
dx = halfSize - cameraToLocalTransform.d;
dy = halfSize - cameraToLocalTransform.h;
dz = halfSize - cameraToLocalTransform.l;
len = dx*dx + dy*dy + dz*dz;
if (len > max) max = len;
dx = -size - cameraToLocalTransform.d;
dy = size - cameraToLocalTransform.h;
dz = size - cameraToLocalTransform.l;
dx = -halfSize - cameraToLocalTransform.d;
dy = halfSize - cameraToLocalTransform.h;
dz = halfSize - cameraToLocalTransform.l;
len = dx*dx + dy*dy + dz*dz;
if (len > max) max = len;
drawUnit.setVertexConstantsFromNumbers(0, cameraToLocalTransform.d, cameraToLocalTransform.h, cameraToLocalTransform.l, camera.farClipping/Math.sqrt(max));

View File

@@ -45,9 +45,9 @@ package alternativa.engine3d.resources {
/**
* Uploads textures from <code>BitmapData</code> to GPU.
*/
public function BitmapTextureResource(data:BitmapData, resizeToPowerOfTwo:Boolean = false) {
public function BitmapTextureResource(data:BitmapData, resizeForGPU:Boolean = false) {
this.data = data;
this.resizeForGPU = resizeToPowerOfTwo;
this.resizeForGPU = resizeForGPU;
}
/**
@@ -58,7 +58,6 @@ package alternativa.engine3d.resources {
if (data != null) {
var source:BitmapData = data;
if (resizeForGPU) {
// TODO: test this
var wLog2Num:Number = Math.log(data.width)/Math.LN2;
var hLog2Num:Number = Math.log(data.height)/Math.LN2;
var wLog2:int = Math.ceil(wLog2Num);

View File

@@ -43,9 +43,9 @@ package alternativa.engine3d.shadows {
use namespace alternativa3d;
/**
* Class of shadow, that is created by one source of light(<code>DirectionalLight</code>). Shadow is rendered in fixed volume.
* Class of the shadow, that is created by one source of light(<code>DirectionalLight</code>). Shadow is rendered in fixed volume.
* For binding of shadow to light source you need:
* 1) to set <code>DirectionalLightShadow</code> as a value of property <code>shadow</code> of light source;
* 1) to set instance of the <code>DirectionalLightShadow</code> as a value of property <code>shadow</code> of light source;
* 2) to add <code>Object3D</code> to corresponding list, using the method <code>addCaster()</code>.
*
* @see #addCaster()
@@ -820,7 +820,7 @@ package alternativa.engine3d.shadows {
}
/**
* Clears the list of objects, that cast shadow.
* Clears the list of objects, which cast shadow.
*/
public function clearCasters():void {
_casters.length = 0;

View File

@@ -40,7 +40,18 @@ package alternativa.engine3d.shadows {
use namespace alternativa3d;
public class OmniLightShadow extends Shadow{
/**
* Class of the shadow, that is created by one source of light(<code>OmniLight</code>). Shadow is rendered in fixed volume.
* For binding of shadow to light source you need:
* 1) to set instance of the <code>OmniLight</code> as a value of property <code>shadow</code> of light source;
* 2) to add <code>Object3D</code> to corresponding list, using the method <code>addCaster()</code>.
*
* @see #addCaster()
* @see alternativa.engine3d.lights.OmniLight#shadow
* @see #farBoundPosition
*/
public class OmniLightShadow extends Shadow {
// TODO: calculate bias automaticaly
/**
@@ -70,7 +81,7 @@ package alternativa.engine3d.shadows {
private var cameras:Vector.<Camera3D> = new Vector.<Camera3D>();
private var debugObject:Mesh;
private var debugMaterial:ShadowDebugMaterial;
private var debugMaterial:ShadowDebugMaterial;
private var _casters:Vector.<Object3D> = new Vector.<Object3D>();
@@ -111,26 +122,26 @@ package alternativa.engine3d.shadows {
debugMaterial.alpha = 0.3;
for (var i:int = 0; i < 6; i++) {
var cam:Camera3D = new Camera3D(radius/1000, radius);
var cam:Camera3D = new Camera3D(radius / 1000, radius);
cam.fov = 1.910633237;
cameras[i] = cam;
}
// Left
cameras[1].rotationY = -Math.PI/2;
cameras[1].rotationY = -Math.PI / 2;
cameras[1].scaleY = -1;
cameras[1].composeTransforms();
// Right
cameras[0].rotationY = Math.PI/2;
cameras[0].rotationY = Math.PI / 2;
cameras[0].scaleY = -1;
cameras[0].composeTransforms();
// Back
cameras[3].rotationX = -Math.PI/2;
cameras[3].rotationX = -Math.PI / 2;
cameras[3].rotationZ = Math.PI;
cameras[3].scaleX = -1;
cameras[3].composeTransforms();
// Front
cameras[2].rotationX = -Math.PI/2;
cameras[2].rotationX = -Math.PI / 2;
cameras[2].scaleY = -1;
cameras[2].composeTransforms();
// Bottom
@@ -143,7 +154,7 @@ package alternativa.engine3d.shadows {
cameras[4].composeTransforms();
}
private function createDebugObject(material:Material, context:Context3D):Mesh{
private function createDebugObject(material:Material, context:Context3D):Mesh {
var geometry:Geometry;
var mesh:Mesh;
if (DEBUG_TYPE == "Box") {
@@ -186,7 +197,7 @@ package alternativa.engine3d.shadows {
triangles.push(c, b, a);
}
mesh.geometry.indices = triangles;
mesh.getSurface(0).numTriangles = triangles.length/3;
mesh.getSurface(0).numTriangles = triangles.length / 3;
mesh.setMaterialToAllSurfaces(material);
}
mesh.geometry.upload(context);
@@ -218,7 +229,7 @@ package alternativa.engine3d.shadows {
radius = OmniLight(_light).attenuationEnd;
for (i = 0; i < 6; i++) {
var cam:Camera3D = cameras[i];
cam.nearClipping = radius/1000;
cam.nearClipping = radius / 1000;
cam.farClipping = radius;
cam.calculateProjection(1, 1);
}
@@ -242,7 +253,7 @@ package alternativa.engine3d.shadows {
caster.localToLightTransform.combine(_light.cameraToLocalTransform, caster.localToCameraTransform);
// collect actualCasters for light
if (caster.boundBox == null || OmniLight(_light).checkBound(caster)){
if (caster.boundBox == null || OmniLight(_light).checkBound(caster)) {
actualCasters[actualCastersCount] = caster;
actualCastersCount++;
@@ -280,7 +291,7 @@ package alternativa.engine3d.shadows {
// Cube side camera
var edgeCamera:Camera3D = cameras[i];
var edgeBit:int = (1<<i);
var edgeBit:int = (1 << i);
if (actualCastersCount > 0) {
// Настройка параметров рендеринга:
renderer.camera = camera;
@@ -306,10 +317,10 @@ package alternativa.engine3d.shadows {
renderer.render(context);
prevActualCastersMask |= edgeBit;
}
else{
else {
// Если относительно одной из камер ничего не менялось, не вызываем отрисовочный вызов
if ((prevActualCastersMask & edgeBit)){
if ((prevActualCastersMask & edgeBit)) {
context.setRenderToTexture(cubeShadowMap, false, 0, i);
context.clear(1, 0, 0, 0);
@@ -331,7 +342,7 @@ package alternativa.engine3d.shadows {
if (debugObject == null) {
debugObject = createDebugObject(debugMaterial, camera.context3D);
}
debugObject.scaleX = debugObject.scaleY = debugObject.scaleZ = radius*debugRadiusScale;
debugObject.scaleX = debugObject.scaleY = debugObject.scaleZ = radius * debugRadiusScale;
debugObject.composeTransforms();
// Формируем матрицу трансформации для debugObject
@@ -344,15 +355,15 @@ package alternativa.engine3d.shadows {
actualCasters.length = 0;
}
private function collectActualChildren(root:Object3D):void{
private function collectActualChildren(root:Object3D):void {
for (var child:Object3D = root.childrenList; child != null; child = child.next) {
if (child.visible){
if (child.visible) {
// calculate transform matrices
_light.lightToObjectTransform.combine(child.cameraToLocalTransform, _light.localToCameraTransform);
child.localToLightTransform.combine(_light.cameraToLocalTransform, child.localToCameraTransform);
// collect actualCasters for light
if (child.boundBox == null || OmniLight(_light).checkBound(child)){
if (child.boundBox == null || OmniLight(_light).checkBound(child)) {
actualCasters[actualCastersCount] = child;
actualCastersCount++;
@@ -508,46 +519,45 @@ package alternativa.engine3d.shadows {
if (plane.x >= 0)
if (plane.y >= 0)
if (plane.z >= 0) {
if (bb.maxX*plane.x + bb.maxY*plane.y + bb.maxZ*plane.z >= plane.offset) result = plane.frontCameras;
if (bb.minX*plane.x + bb.minY*plane.y + bb.minZ*plane.z < plane.offset) result |= plane.backCameras;
if (bb.maxX * plane.x + bb.maxY * plane.y + bb.maxZ * plane.z >= plane.offset) result = plane.frontCameras;
if (bb.minX * plane.x + bb.minY * plane.y + bb.minZ * plane.z < plane.offset) result |= plane.backCameras;
} else {
if (bb.maxX*plane.x + bb.maxY*plane.y + bb.minZ*plane.z >= plane.offset) result = plane.frontCameras;
if (bb.minX*plane.x + bb.minY*plane.y + bb.maxZ*plane.z < plane.offset) result |= plane.backCameras;
}
else
if (plane.z >= 0) {
if (bb.maxX*plane.x + bb.minY*plane.y + bb.maxZ*plane.z >= plane.offset) result = plane.frontCameras;
if (bb.minX*plane.x + bb.maxY*plane.y + bb.minZ*plane.z < plane.offset) result |= plane.backCameras;
} else {
if (bb.maxX*plane.x + bb.minY*plane.y + bb.minZ*plane.z >= plane.offset) result = plane.frontCameras;
if (bb.minX*plane.x + bb.maxY*plane.y + bb.maxZ*plane.z < plane.offset) result |= plane.backCameras;
if (bb.maxX * plane.x + bb.maxY * plane.y + bb.minZ * plane.z >= plane.offset) result = plane.frontCameras;
if (bb.minX * plane.x + bb.minY * plane.y + bb.maxZ * plane.z < plane.offset) result |= plane.backCameras;
}
else if (plane.z >= 0) {
if (bb.maxX * plane.x + bb.minY * plane.y + bb.maxZ * plane.z >= plane.offset) result = plane.frontCameras;
if (bb.minX * plane.x + bb.maxY * plane.y + bb.minZ * plane.z < plane.offset) result |= plane.backCameras;
} else {
if (bb.maxX * plane.x + bb.minY * plane.y + bb.minZ * plane.z >= plane.offset) result = plane.frontCameras;
if (bb.minX * plane.x + bb.maxY * plane.y + bb.maxZ * plane.z < plane.offset) result |= plane.backCameras;
}
else if (plane.y >= 0)
if (plane.z >= 0) {
if (bb.minX*plane.x + bb.maxY*plane.y + bb.maxZ*plane.z >= plane.offset) result = plane.frontCameras;
if (bb.maxX*plane.x + bb.minY*plane.y + bb.minZ*plane.z < plane.offset) result |= plane.backCameras;
if (bb.minX * plane.x + bb.maxY * plane.y + bb.maxZ * plane.z >= plane.offset) result = plane.frontCameras;
if (bb.maxX * plane.x + bb.minY * plane.y + bb.minZ * plane.z < plane.offset) result |= plane.backCameras;
} else {
if (bb.minX*plane.x + bb.maxY*plane.y + bb.minZ*plane.z >= plane.offset) result = plane.frontCameras;
if (bb.maxX*plane.x + bb.minY*plane.y + bb.maxZ*plane.z < plane.offset) result |= plane.backCameras;
if (bb.minX * plane.x + bb.maxY * plane.y + bb.minZ * plane.z >= plane.offset) result = plane.frontCameras;
if (bb.maxX * plane.x + bb.minY * plane.y + bb.maxZ * plane.z < plane.offset) result |= plane.backCameras;
}
else if (plane.z >= 0) {
if (bb.minX*plane.x + bb.minY*plane.y + bb.maxZ*plane.z >= plane.offset) result = plane.frontCameras;
if (bb.maxX*plane.x + bb.maxY*plane.y + bb.minZ*plane.z < plane.offset) result |= plane.backCameras;
if (bb.minX * plane.x + bb.minY * plane.y + bb.maxZ * plane.z >= plane.offset) result = plane.frontCameras;
if (bb.maxX * plane.x + bb.maxY * plane.y + bb.minZ * plane.z < plane.offset) result |= plane.backCameras;
} else {
if (bb.minX*plane.x + bb.minY*plane.y + bb.minZ*plane.z >= plane.offset) result = plane.frontCameras;
if (bb.maxX*plane.x + bb.maxY*plane.y + bb.maxZ*plane.z < plane.offset) result |= plane.backCameras;
if (bb.minX * plane.x + bb.minY * plane.y + bb.minZ * plane.z >= plane.offset) result = plane.frontCameras;
if (bb.maxX * plane.x + bb.maxY * plane.y + bb.maxZ * plane.z < plane.offset) result |= plane.backCameras;
}
culling &= result | plane.unusedBits;
}
return culling;
}
private function collectDraws(context:Context3D, caster:Object3D, edgeCamera:Camera3D):void{
private function collectDraws(context:Context3D, caster:Object3D, edgeCamera:Camera3D):void {
// если объект является мешем, собираем для него дроуколы
var mesh:Mesh = caster as Mesh;
if (mesh != null && mesh.geometry != null) {
var program:ShaderProgram;
var programListByTransformProcedure:Vector.<ShaderProgram>;
var programListByTransformProcedure:Vector.<ShaderProgram>;
var skin:Skin = mesh as Skin;
// пробегаемся по сурфейсам
@@ -617,7 +627,7 @@ package alternativa.engine3d.shadows {
drawUnit.setProjectionConstants(edgeCamera, program.vertexShader.getVariableIndex("cProjMatrix"), casterToEdgedCameraTransform);
drawUnit.setVertexConstantsFromTransform(program.vertexShader.getVariableIndex("cCasterToOmni"), caster.localToLightTransform);
drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("cConstants"), 1 / 255, 0, 255/radius, 1);
drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("cConstants"), 1 / 255, 0, 255 / radius, 1);
renderer.addDrawUnit(drawUnit, Renderer.OPAQUE);
}
@@ -654,74 +664,73 @@ package alternativa.engine3d.shadows {
private function getProgram(transformProcedure:Procedure, programListByTransformProcedure:Vector.<ShaderProgram>, context:Context3D, alphaTest:Boolean, useDiffuseAlpha:Boolean):ShaderProgram {
var key:int = (alphaTest ? (useDiffuseAlpha ? 1 : 2) : 0);
var program:ShaderProgram = programListByTransformProcedure[key];
var key:int = (alphaTest ? (useDiffuseAlpha ? 1 : 2) : 0);
var program:ShaderProgram = programListByTransformProcedure[key];
if (program == null) {
if (program == null) {
var vLinker:Linker = new Linker(Context3DProgramType.VERTEX);
var fLinker:Linker = new Linker(Context3DProgramType.FRAGMENT);
var positionVar:String = "aPosition";
vLinker.declareVariable(positionVar, VariableType.ATTRIBUTE);
var positionVar:String = "aPosition";
vLinker.declareVariable(positionVar, VariableType.ATTRIBUTE);
if (alphaTest) {
vLinker.addProcedure(passUVProcedure);
}
if (alphaTest) {
vLinker.addProcedure(passUVProcedure);
}
if (transformProcedure != null) {
var newPosVar:String = "tTransformedPosition";
vLinker.declareVariable(newPosVar);
vLinker.addProcedure(transformProcedure, positionVar);
vLinker.setOutputParams(transformProcedure, newPosVar);
positionVar = newPosVar;
}
if (transformProcedure != null) {
var newPosVar:String = "tTransformedPosition";
vLinker.declareVariable(newPosVar);
vLinker.addProcedure(transformProcedure, positionVar);
vLinker.setOutputParams(transformProcedure, newPosVar);
positionVar = newPosVar;
}
var proc:Procedure = Procedure.compileFromArray([
"#v0=vDistance",
var proc:Procedure = Procedure.compileFromArray([
"#v0=vDistance",
"m34 t0.xyz, i0, c2",
"mov v0, t0.xyzx",
"mov v0, t0.xyzx",
"m44 o0, i0, c0"
]);
proc.assignVariableName(VariableType.CONSTANT, 0, "cProjMatrix", 4);
]);
proc.assignVariableName(VariableType.CONSTANT, 0, "cProjMatrix", 4);
proc.assignVariableName(VariableType.CONSTANT, 2, "cCasterToOmni", 3);
vLinker.addProcedure(proc, positionVar);
vLinker.addProcedure(proc, positionVar);
if (alphaTest) {
if (useDiffuseAlpha) {
fLinker.addProcedure(diffuseAlphaTestProcedure);
} else {
fLinker.addProcedure(opacityAlphaTestProcedure);
}
}
fLinker.addProcedure(Procedure.compileFromArray([
"#v0=vDistance", // xyz
"#c0=cConstants", // 1/255, 0, 255/radius, 1
if (alphaTest) {
if (useDiffuseAlpha) {
fLinker.addProcedure(diffuseAlphaTestProcedure);
} else {
fLinker.addProcedure(opacityAlphaTestProcedure);
}
}
fLinker.addProcedure(Procedure.compileFromArray([
"#v0=vDistance", // xyz
"#c0=cConstants", // 1/255, 0, 255/radius, 1
// calculate distance
"dp3 t0.z, v0.xyz, v0.xyz",
"sqt t0.z, t0.z", // x: [0, radius]
"mul t0.z, t0.z, c0.z", // x: [0, 255]
"sqt t0.z, t0.z", // x: [0, radius]
"mul t0.z, t0.z, c0.z", // x: [0, 255]
// codeing
"frc t0.y, t0.z",
"sub t0.x, t0.z, t0.y",
"mul t0.x, t0.x, c0.x",
"frc t0.y, t0.z",
"sub t0.x, t0.z, t0.y",
"mul t0.x, t0.x, c0.x",
"mov t0.w, c0.w",
"mov o0, t0"
]));
program = new ShaderProgram(vLinker, fLinker);
fLinker.varyings = vLinker.varyings;
programListByTransformProcedure[key] = program;
program.upload(context);
]));
program = new ShaderProgram(vLinker, fLinker);
fLinker.varyings = vLinker.varyings;
programListByTransformProcedure[key] = program;
program.upload(context);
}
}
return program;
}
//------------- ShadowMap Shader in material----------
/**
@@ -737,12 +746,12 @@ package alternativa.engine3d.shadows {
// Устанавливаем коеффициенты
if (_pcfOffset > 0) {
var offset:Number = Math.tan(_pcfOffset/180*Math.PI)/3;
drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cPCFOffsets"), -3/2, 1/16, 0, 0);
var offset:Number = Math.tan(_pcfOffset / 180 * Math.PI) / 3;
drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cPCFOffsets"), -3 / 2, 1 / 16, 0, 0);
drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cConstants"), -1, 1, 0, offset);
drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cDecode"), -DIFFERENCE_MULTIPLIER, -DIFFERENCE_MULTIPLIER/255, biasMultiplier*DIFFERENCE_MULTIPLIER/radius, 10);
drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cDecode"), -DIFFERENCE_MULTIPLIER, -DIFFERENCE_MULTIPLIER / 255, biasMultiplier * DIFFERENCE_MULTIPLIER / radius, 10);
} else {
drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cConstants"), -DIFFERENCE_MULTIPLIER, -DIFFERENCE_MULTIPLIER/255, biasMultiplier*DIFFERENCE_MULTIPLIER/radius, 1.0);
drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cConstants"), -DIFFERENCE_MULTIPLIER, -DIFFERENCE_MULTIPLIER / 255, biasMultiplier * DIFFERENCE_MULTIPLIER / radius, 1.0);
}
}
@@ -834,7 +843,7 @@ package alternativa.engine3d.shadows {
// shaderArr[line++] = "mov t3.z, t0.w";
shaderArr[line++] = "tex t3.xy, t2.xyz, s0 <cube, nearest>";
shaderArr[line++] = "dp3 o0." +componentByIndex[0] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число
shaderArr[line++] = "dp3 o0." + componentByIndex[0] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число
//-----
@@ -842,7 +851,7 @@ package alternativa.engine3d.shadows {
shaderArr[line++] = "add t2.xyz, t2.xyz, t1.xyz";
shaderArr[line++] = "tex t3.xy, t2.xyz, s0 <cube, nearest>";
shaderArr[line++] = "dp3 o0." +componentByIndex[j] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число
shaderArr[line++] = "dp3 o0." + componentByIndex[j] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число
}
shaderArr[line++] = "sat o0, o0";
@@ -854,13 +863,13 @@ package alternativa.engine3d.shadows {
shaderArr[line++] = "add t2.xyz, t2.xyz, t0.xyz";
shaderArr[line++] = "tex t3.xy, t2.xyz, s0 <cube, nearest>";
shaderArr[line++] = "dp3 o0." +componentByIndex[0] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число
shaderArr[line++] = "dp3 o0." + componentByIndex[0] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число
for (j = 1; j < 4; j++){
shaderArr[line++] = (i%2 == 1)?("add t2.xyz, t2.xyz, t1.xyz"):("sub t2.xyz, t2.xyz, t1.xyz");
for (j = 1; j < 4; j++) {
shaderArr[line++] = (i % 2 == 1) ? ("add t2.xyz, t2.xyz, t1.xyz") : ("sub t2.xyz, t2.xyz, t1.xyz");
shaderArr[line++] = "tex t3.xy, t2.xyz, s0 <cube, nearest>";
shaderArr[line++] = "dp3 o0." +componentByIndex[j] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число
shaderArr[line++] = "dp3 o0." + componentByIndex[j] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число
}
shaderArr[line++] = "sat o0, o0";
shaderArr[line++] = "dp4 o0.x, o0, c2.y";
@@ -876,8 +885,8 @@ package alternativa.engine3d.shadows {
private static const componentByIndex:Array = ["x", "y", "z", "w"];
/**
* Добавляет <code>object</code> в список объектов, отбрасывающих тень.
* @param object Добавляемый объект.
* Adds given object to list of objects, that cast shadow.
* @param object Added object.
*/
public function addCaster(object:Object3D):void {
if (_casters.indexOf(object) < 0) {
@@ -885,6 +894,10 @@ package alternativa.engine3d.shadows {
}
}
/**
* Removes given object from shadow casters list.
* @param object Object which should be removed from shadow casters list.
*/
public function removeCaster(object:Object3D):void {
var index:int = _casters.indexOf(object);
if (index < 0) throw new Error("Caster not found");
@@ -892,14 +905,15 @@ package alternativa.engine3d.shadows {
}
/**
* Очищает список объектов, отбрасывающих тень.
*/
* Clears the list of objects, that cast shadow.
*/
public function clearCasters():void {
_casters.length = 0;
}
/**
* Качество тени. Задает разрешение shadowmap. Может принимать значения от <code>2</code> до <code>11</code>.
* Set resolution of shadow map. This property can get value of power of 2 (up to 2048).
* OmniLightShadow uses 6 shadow maps.
*/
public function get mapSize():int {
return _mapSize;
@@ -916,7 +930,7 @@ package alternativa.engine3d.shadows {
} else if (value > 1024) {
throw new ArgumentError("Map size exceeds maximum value 1024.");
}
if ((Math.log(value)/Math.LN2 % 1) != 0) {
if ((Math.log(value) / Math.LN2 % 1) != 0) {
throw new ArgumentError("Map size must be power of two.");
}
if (cubeShadowMap != null) {
@@ -927,8 +941,7 @@ package alternativa.engine3d.shadows {
}
/**
* Смещение Percentage Closer Filtering. Этот способ фильтрации используется для смягчения границ тени.
* 1 pcfOffset equivalent 1 degree for all blur
* Offset of Percentage Closer Filtering. This way of filtering is used for mitigation of shadow bounds.
*/
public function get pcfOffset():Number {
return _pcfOffset;
@@ -971,6 +984,7 @@ import flash.utils.Dictionary;
class ShadowDebugMaterial extends Material {
use namespace alternativa3d;
/**
* Прозрачность.
* Является дополнительным множителем к прозрачности текстуры.
@@ -1015,7 +1029,7 @@ class ShadowDebugMaterial extends Material {
drawUnit.setVertexBufferAt(program.vertexShader.getVariableIndex("aPosition"), positionBuffer, geometry._attributesOffsets[VertexAttributes.POSITION], VertexAttributes.FORMATS[VertexAttributes.POSITION]);
// Установка констант
drawUnit.setProjectionConstants(camera, program.vertexShader.getVariableIndex("cProjMatrix"), object.localToCameraTransform);
drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("cDecode"), 1, 1/255, 0, alpha);
drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("cDecode"), 1, 1 / 255, 0, alpha);
drawUnit.setTextureAt(program.fragmentShader.getVariableIndex("sCubeMap"), cubeMap);
// Отправка на отрисовку

View File

@@ -42,8 +42,13 @@ package alternativa.utils {
}
/**
* @private
* Performs calculation of bound box of objects hierarchy branch.
* Calculates a BoundBox of hierarchy of objects.
*
* @param object Container which contains the hierarchy.
* @param boundBoxSpace <code>Object3D</code> in coordinates of which the BoundBox will be calculated.
* @param result Instance of <code>BoundBox</code> to which calculated properties will be set.
*
* @return Instance given as <code>result</code> property with properties updated according to calculations. If <code>result</code> property was not set, new instance of <code>BoundBox</code> will be created.
*/
public static function calculateHierarchyBoundBox(object:Object3D, boundBoxSpace:Object3D = null, result:BoundBox = null):BoundBox {
if (result == null) result = new BoundBox();