Created
May 18, 2011 03:01
-
-
Save gotoken/977922 to your computer and use it in GitHub Desktop.
patched src/org/papervision3d/materials/BitmapMaterial.as based on http://sixwish.blogspot.com/2010/09/pv3d-quadrantrenderengine.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.papervision3d.materials | |
{ | |
import org.papervision3d.Papervision3D; | |
import org.papervision3d.core.geom.renderables.Triangle3D; | |
import org.papervision3d.core.geom.renderables.Vertex3DInstance; | |
import org.papervision3d.core.log.PaperLogger; | |
import org.papervision3d.core.material.TriangleMaterial; | |
import org.papervision3d.core.proto.MaterialObject3D; | |
import org.papervision3d.core.render.command.RenderTriangle; | |
import org.papervision3d.core.render.data.RenderSessionData; | |
import org.papervision3d.core.render.draw.ITriangleDrawer; | |
import org.papervision3d.materials.utils.PrecisionMode; | |
import org.papervision3d.materials.utils.RenderRecStorage; | |
import flash.display.BitmapData; | |
import flash.display.Graphics; | |
import flash.geom.Matrix; | |
import flash.geom.Point; | |
import flash.geom.Rectangle; | |
import flash.utils.Dictionary; | |
/** | |
* The BitmapMaterial class creates a texture from a BitmapData object. | |
* | |
* Materials collect data about how objects appear when rendered. | |
* | |
*/ | |
public class BitmapMaterial extends TriangleMaterial implements ITriangleDrawer | |
{ | |
protected static const DEFAULT_FOCUS:Number = 200; | |
protected static var hitRect:Rectangle = new Rectangle(); | |
protected var renderRecStorage:Array; | |
protected var focus:Number = 200; | |
protected var _precise:Boolean; | |
protected var _precision:int = 8; | |
protected var _perPixelPrecision:int = 8; | |
public var minimumRenderSize:Number = 4; | |
protected var _texture :Object; | |
/** | |
* Indicates if mip mapping is forced. | |
*/ | |
public static var AUTO_MIP_MAPPING :Boolean = false; | |
/** | |
* Levels of mip mapping to force. | |
*/ | |
public static var MIP_MAP_DEPTH :Number = 8; | |
/** | |
* Precision mode indicates how triangles are created for precise texture render. | |
*/ | |
public var precisionMode:int = PrecisionMode.ORIGINAL; | |
public var uvMatrices:Dictionary = new Dictionary(true); | |
/** | |
* @private | |
*/ | |
protected static var _triMatrix:Matrix = new Matrix(); | |
protected static var _triMap:Matrix; | |
/** | |
* @private | |
*/ | |
protected static var _localMatrix:Matrix = new Matrix(); | |
/** | |
* The BitmapMaterial class creates a texture from a BitmapData object. | |
* | |
* @param asset A BitmapData object. | |
*/ | |
public function BitmapMaterial( asset:BitmapData=null, precise:Boolean = false) | |
{ | |
// texture calls createBitmap. That's where all the init happens. This allows to reinit when changing texture. -C4RL05 | |
// if we have an asset passed in, this means we're the subclass, not the super. Set the texture, let the fun begin. | |
if( asset ) texture = asset; | |
this.precise = precise; | |
createRenderRecStorage(); | |
} | |
protected function createRenderRecStorage():void | |
{ | |
this.renderRecStorage = new Array(); | |
for(var a:int = 0; a<=100; a++){ | |
this.renderRecStorage[a] = new RenderRecStorage(); | |
} | |
} | |
/** | |
* Resets the mapping coordinates. Use when the texture has been resized. | |
*/ | |
public function resetMapping():void | |
{ | |
for ( var obj:* in uvMatrices ) { | |
uvMatrices[obj] = null; | |
} | |
} | |
//Local storage. Avoid var's in high usage functions. | |
private var x0:Number; | |
private var y0:Number; | |
private var x1:Number; | |
private var y1:Number; | |
private var x2:Number; | |
private var y2:Number; | |
/** | |
* drawTriangle | |
*/ | |
override public function drawTriangle(tri:RenderTriangle, graphics:Graphics, renderSessionData:RenderSessionData, altBitmap:BitmapData = null, altUV:Matrix = null):void | |
{ | |
// trace("at drawing triangle???"); | |
_triMap = altUV ? altUV : (uvMatrices[tri] || transformUVRT(tri)); | |
if(!_precise || !_triMap){ | |
if( lineAlpha ) | |
graphics.lineStyle( lineThickness, lineColor, lineAlpha ); | |
if( bitmap ) | |
{ | |
x0 = tri.v0.x; | |
y0 = tri.v0.y; | |
x1 = tri.v1.x; | |
y1 = tri.v1.y; | |
x2 = tri.v2.x; | |
y2 = tri.v2.y; | |
_triMatrix.a = x1 - x0; | |
_triMatrix.b = y1 - y0; | |
_triMatrix.c = x2 - x0; | |
_triMatrix.d = y2 - y0; | |
_triMatrix.tx = x0; | |
_triMatrix.ty = y0; | |
_localMatrix.a = _triMap.a; | |
_localMatrix.b = _triMap.b; | |
_localMatrix.c = _triMap.c; | |
_localMatrix.d = _triMap.d; | |
_localMatrix.tx = _triMap.tx; | |
_localMatrix.ty = _triMap.ty; | |
_localMatrix.concat(_triMatrix); | |
graphics.beginBitmapFill( altBitmap ? altBitmap : bitmap, _localMatrix, tiled, smooth); | |
} | |
graphics.moveTo( x0, y0 ); | |
graphics.lineTo( x1, y1 ); | |
graphics.lineTo( x2, y2 ); | |
graphics.lineTo( x0, y0 ); | |
if( bitmap ) | |
graphics.endFill(); | |
if( lineAlpha ) | |
graphics.lineStyle(); | |
renderSessionData.renderStatistics.triangles++; | |
}else{ | |
if(bitmap){ | |
focus = renderSessionData.camera.focus; | |
tempPreBmp = altBitmap ? altBitmap : bitmap; | |
tempPreRSD = renderSessionData; | |
tempPreGrp = graphics; | |
cullRect = renderSessionData.viewPort.cullingRectangle; | |
renderRec(_triMap, tri.v0, tri.v1, tri.v2, 0); | |
} | |
} | |
} | |
/** | |
* Applies the updated UV texture mapping values to the triangle. This is required to speed up rendering. | |
* | |
*/ | |
public function transformUV(face3D:Triangle3D):Matrix | |
{ | |
if( ! face3D.uv ) | |
{ | |
PaperLogger.error( "MaterialObject3D: transformUV() uv not found!" ); | |
} | |
else if( bitmap ) | |
{ | |
var uv :Array = face3D.uv; | |
var w :Number = bitmap.width * maxU; | |
var h :Number = bitmap.height * maxV; | |
var u0 :Number = w * face3D.uv0.u; | |
var v0 :Number = h * ( 1 - face3D.uv0.v ); | |
var u1 :Number = w * face3D.uv1.u; | |
var v1 :Number = h * ( 1 - face3D.uv1.v); | |
var u2 :Number = w * face3D.uv2.u; | |
var v2 :Number = h * ( 1 - face3D.uv2.v ); | |
// Fix perpendicular projections | |
if( (u0 == u1 && v0 == v1) || (u0 == u2 && v0 == v2) ) | |
{ | |
u0 -= (u0 > 0.05)? 0.05 : -0.05; | |
v0 -= (v0 > 0.07)? 0.07 : -0.07; | |
} | |
if( u2 == u1 && v2 == v1 ) | |
{ | |
u2 -= (u2 > 0.05)? 0.04 : -0.04; | |
v2 -= (v2 > 0.06)? 0.06 : -0.06; | |
} | |
// Precalculate matrix & correct for mip mapping | |
var at :Number = ( u1 - u0 ); | |
var bt :Number = ( v1 - v0 ); | |
var ct :Number = ( u2 - u0 ); | |
var dt :Number = ( v2 - v0 ); | |
var m :Matrix = new Matrix( at, bt, ct, dt, u0, v0 ); | |
// Need to mirror over X-axis when righthanded | |
if(Papervision3D.useRIGHTHANDED) | |
{ | |
m.scale(-1, 1); | |
m.translate(w, 0); | |
} | |
m.invert(); | |
var mapping:Matrix = uvMatrices[face3D] = m.clone(); | |
mapping.a = m.a; | |
mapping.b = m.b; | |
mapping.c = m.c; | |
mapping.d = m.d; | |
mapping.tx = m.tx; | |
mapping.ty = m.ty; | |
} | |
else PaperLogger.error( "MaterialObject3D: transformUV() material.bitmap not found!" ); | |
return mapping; | |
} | |
/** | |
* Applies the updated UV texture mapping values to the triangle. This is required to speed up rendering. | |
* | |
*/ | |
public function transformUVRT(tri:RenderTriangle):Matrix | |
{ | |
if( bitmap ) | |
{ | |
//var uv :Array = face3D.uv; | |
var w :Number = bitmap.width * maxU; | |
var h :Number = bitmap.height * maxV; | |
var u0 :Number = w * tri.uv0.u; | |
var v0 :Number = h * ( 1 - tri.uv0.v ); | |
var u1 :Number = w * tri.uv1.u; | |
var v1 :Number = h * ( 1 - tri.uv1.v); | |
var u2 :Number = w * tri.uv2.u; | |
var v2 :Number = h * ( 1 - tri.uv2.v ); | |
// Fix perpendicular projections | |
if( (u0 == u1 && v0 == v1) || (u0 == u2 && v0 == v2) ) | |
{ | |
u0 -= (u0 > 0.05)? 0.05 : -0.05; | |
v0 -= (v0 > 0.07)? 0.07 : -0.07; | |
} | |
if( u2 == u1 && v2 == v1 ) | |
{ | |
u2 -= (u2 > 0.05)? 0.04 : -0.04; | |
v2 -= (v2 > 0.06)? 0.06 : -0.06; | |
} | |
// Precalculate matrix & correct for mip mapping | |
var at :Number = ( u1 - u0 ); | |
var bt :Number = ( v1 - v0 ); | |
var ct :Number = ( u2 - u0 ); | |
var dt :Number = ( v2 - v0 ); | |
var m :Matrix = new Matrix( at, bt, ct, dt, u0, v0 ); | |
// Need to mirror over X-axis when righthanded | |
if(Papervision3D.useRIGHTHANDED) | |
{ | |
m.scale(-1, 1); | |
m.translate(w, 0); | |
} | |
m.invert(); | |
var mapping:Matrix = uvMatrices[tri] = m.clone(); | |
mapping.a = m.a; | |
mapping.b = m.b; | |
mapping.c = m.c; | |
mapping.d = m.d; | |
mapping.tx = m.tx; | |
mapping.ty = m.ty; | |
} | |
else PaperLogger.error( "MaterialObject3D: transformUV() material.bitmap not found!" ); | |
return mapping; | |
} | |
protected var ax:Number; | |
protected var ay:Number; | |
protected var az:Number; | |
protected var bx:Number; | |
protected var by:Number; | |
protected var bz:Number; | |
protected var cx:Number; | |
protected var cy:Number; | |
protected var cz:Number; | |
protected var faz:Number; | |
protected var fbz:Number; | |
protected var fcz:Number; | |
protected var mabz:Number; | |
protected var mbcz:Number; | |
protected var mcaz:Number; | |
protected var mabx:Number; | |
protected var maby:Number; | |
protected var mbcx:Number; | |
protected var mbcy:Number; | |
protected var mcax:Number; | |
protected var mcay:Number; | |
protected var dabx:Number; | |
protected var daby:Number; | |
protected var dbcx:Number; | |
protected var dbcy:Number; | |
protected var dcax:Number; | |
protected var dcay:Number; | |
protected var dsab:Number; | |
protected var dsbc:Number; | |
protected var dsca:Number; | |
protected var dmax:Number; | |
protected var cullRect:Rectangle; | |
protected var tempPreGrp:Graphics; | |
protected var tempPreBmp:BitmapData; | |
protected var tempPreRSD:RenderSessionData; | |
protected var tempTriangleMatrix:Matrix = new Matrix(); | |
private var a2:Number; | |
private var b2:Number; | |
private var c2:Number; | |
private var d2:Number; | |
private var dx:Number, dy:Number, d2ab:Number, d2bc:Number, d2ca:Number; | |
protected function renderRec(emMap:Matrix, v0:Vertex3DInstance, v1:Vertex3DInstance, v2:Vertex3DInstance, index:Number):void | |
{ | |
az = v0.z; | |
bz = v1.z; | |
cz = v2.z; | |
//Cull if a vertex behind near. | |
if((az <= 0) && (bz <= 0) && (cz <= 0)) | |
return; | |
cx = v2.x; | |
cy = v2.y; | |
bx = v1.x; | |
by = v1.y; | |
ax = v0.x; | |
ay = v0.y; | |
//Cull if outside of viewport. | |
if(cullRect){ | |
hitRect.x = (bx < ax ? (bx < cx ? bx : cx) : (ax < cx ? ax : cx )); | |
hitRect.width = (bx > ax ? (bx > cx ? bx : cx) : (ax > cx ? ax : cx )) + (hitRect.x < 0 ? -hitRect.x : hitRect.x); | |
hitRect.y = (by < ay ? (by < cy ? by : cy) : (ay < cy ? ay : cy )); | |
hitRect.height = (by > ay ? (by > cy ? by : cy) : (ay > cy ? ay : cy )) + (hitRect.y < 0 ? -hitRect.y : hitRect.y); | |
if(!((hitRect.right<cullRect.left)||(hitRect.left>cullRect.right))){ | |
if(!((hitRect.bottom<cullRect.top)||(hitRect.top>cullRect.bottom))){ | |
}else{ | |
return; | |
} | |
}else{ | |
return; | |
} | |
} | |
//cull if max iterations is reached, focus is invalid or if tesselation is to small. | |
if (index >= 100 || (hitRect.width < minimumRenderSize) || (hitRect.height < minimumRenderSize) || (focus == Infinity)) | |
{ | |
//Draw this triangle. | |
a2 = v1.x - v0.x; | |
b2 = v1.y - v0.y; | |
c2 = v2.x - v0.x; | |
d2 = v2.y - v0.y; | |
tempTriangleMatrix.a = emMap.a*a2 + emMap.b*c2; | |
tempTriangleMatrix.b = emMap.a*b2 + emMap.b*d2; | |
tempTriangleMatrix.c = emMap.c*a2 + emMap.d*c2; | |
tempTriangleMatrix.d = emMap.c*b2 + emMap.d*d2; | |
tempTriangleMatrix.tx = emMap.tx*a2 + emMap.ty*c2 + v0.x; | |
tempTriangleMatrix.ty = emMap.tx*b2 + emMap.ty*d2 + v0.y; | |
if(lineAlpha){ | |
tempPreGrp.lineStyle( lineThickness, lineColor, lineAlpha ); | |
} | |
tempPreGrp.beginBitmapFill(tempPreBmp, tempTriangleMatrix, tiled, smooth); | |
tempPreGrp.moveTo(v0.x, v0.y); | |
tempPreGrp.lineTo(v1.x, v1.y); | |
tempPreGrp.lineTo(v2.x, v2.y); | |
tempPreGrp.endFill(); | |
if(lineAlpha){ | |
tempPreGrp.lineStyle(); | |
} | |
tempPreRSD.renderStatistics.triangles++; | |
return; | |
} | |
faz = focus + az; | |
fbz = focus + bz; | |
fcz = focus + cz; | |
mabz = 2 / (faz + fbz); | |
mbcz = 2 / (fbz + fcz); | |
mcaz = 2 / (fcz + faz); | |
mabx = (ax*faz + bx*fbz)*mabz; | |
maby = (ay*faz + by*fbz)*mabz; | |
mbcx = (bx*fbz + cx*fcz)*mbcz; | |
mbcy = (by*fbz + cy*fcz)*mbcz; | |
mcax = (cx*fcz + ax*faz)*mcaz; | |
mcay = (cy*fcz + ay*faz)*mcaz; | |
dabx = ax + bx - mabx; | |
daby = ay + by - maby; | |
dbcx = bx + cx - mbcx; | |
dbcy = by + cy - mbcy; | |
dcax = cx + ax - mcax; | |
dcay = cy + ay - mcay; | |
dsab = (dabx*dabx + daby*daby); | |
dsbc = (dbcx*dbcx + dbcy*dbcy); | |
dsca = (dcax*dcax + dcay*dcay); | |
var nIndex:int = index+1; | |
var nRss:RenderRecStorage = RenderRecStorage(renderRecStorage[int(index)]); | |
var renderRecMap:Matrix = nRss.mat; | |
if ((dsab <= _precision) && (dsca <= _precision) && (dsbc <= _precision)){ | |
//Draw this triangle. | |
a2 = v1.x - v0.x; | |
b2 = v1.y - v0.y; | |
c2 = v2.x - v0.x; | |
d2 = v2.y - v0.y; | |
tempTriangleMatrix.a = emMap.a*a2 + emMap.b*c2; | |
tempTriangleMatrix.b = emMap.a*b2 + emMap.b*d2; | |
tempTriangleMatrix.c = emMap.c*a2 + emMap.d*c2; | |
tempTriangleMatrix.d = emMap.c*b2 + emMap.d*d2; | |
tempTriangleMatrix.tx = emMap.tx*a2 + emMap.ty*c2 + v0.x; | |
tempTriangleMatrix.ty = emMap.tx*b2 + emMap.ty*d2 + v0.y; | |
if(lineAlpha){ | |
tempPreGrp.lineStyle( lineThickness, lineColor, lineAlpha ); | |
} | |
tempPreGrp.beginBitmapFill(tempPreBmp, tempTriangleMatrix, tiled, smooth); | |
tempPreGrp.moveTo(v0.x, v0.y); | |
tempPreGrp.lineTo(v1.x, v1.y); | |
tempPreGrp.lineTo(v2.x, v2.y); | |
tempPreGrp.endFill(); | |
if(lineAlpha){ | |
tempPreGrp.lineStyle(); | |
} | |
tempPreRSD.renderStatistics.triangles++; | |
return; | |
} | |
if ((dsab > _precision) && (dsca > _precision) && (dsbc > _precision)){ | |
renderRecMap.a = emMap.a*2; | |
renderRecMap.b = emMap.b*2; | |
renderRecMap.c = emMap.c*2; | |
renderRecMap.d = emMap.d*2; | |
renderRecMap.tx = emMap.tx*2; | |
renderRecMap.ty = emMap.ty*2; | |
nRss.v0.x = mabx * 0.5; | |
nRss.v0.y = maby * 0.5; | |
nRss.v0.z = (az+bz) * 0.5; | |
nRss.v1.x = mbcx * 0.5; | |
nRss.v1.y = mbcy * 0.5; | |
nRss.v1.z = (bz+cz) * 0.5; | |
nRss.v2.x = mcax * 0.5; | |
nRss.v2.y = mcay * 0.5; | |
nRss.v2.z = (cz+az) * 0.5; | |
renderRec(renderRecMap, v0, nRss.v0, nRss.v2, nIndex); | |
renderRecMap.tx -=1; | |
renderRec(renderRecMap, nRss.v0, v1, nRss.v1, nIndex); | |
renderRecMap.ty -=1; | |
renderRecMap.tx = emMap.tx*2; | |
renderRec(renderRecMap, nRss.v2, nRss.v1, v2, nIndex); | |
renderRecMap.a = -emMap.a*2; | |
renderRecMap.b = -emMap.b*2; | |
renderRecMap.c = -emMap.c*2; | |
renderRecMap.d = -emMap.d*2; | |
renderRecMap.tx = -emMap.tx*2+1; | |
renderRecMap.ty = -emMap.ty*2+1; | |
renderRec(renderRecMap, nRss.v1, nRss.v2, nRss.v0, nIndex); | |
return; | |
} | |
if( precisionMode == PrecisionMode.ORIGINAL ) | |
{ | |
d2ab = dsab; | |
d2bc = dsbc; | |
d2ca = dsca; | |
dmax = (dsca > dsbc ? (dsca > dsab ? dsca : dsab) : (dsbc > dsab ? dsbc : dsab )); | |
} | |
else | |
{ | |
// Calculate best tessellation edge | |
dx = v0.x - v1.x; | |
dy = v0.y - v1.y; | |
d2ab = dx * dx + dy * dy; | |
dx = v1.x - v2.x; | |
dy = v1.y - v2.y; | |
d2bc = dx * dx + dy * dy; | |
dx = v2.x - v0.x; | |
dy = v2.y - v0.y; | |
d2ca = dx * dx + dy * dy; | |
dmax = (d2ca > d2bc ? (d2ca > d2ab ? d2ca : d2ab) : (d2bc > d2ab ? d2bc : d2ab )); // dmax = Math.max( d2ab, d2bc, d2ac ); | |
} | |
// Break triangle along edge | |
if (d2ab == dmax) | |
{ | |
renderRecMap.a = emMap.a*2; | |
renderRecMap.b = emMap.b; | |
renderRecMap.c = emMap.c*2; | |
renderRecMap.d = emMap.d; | |
renderRecMap.tx = emMap.tx*2; | |
renderRecMap.ty = emMap.ty; | |
nRss.v0.x = mabx * 0.5; | |
nRss.v0.y = maby * 0.5; | |
nRss.v0.z = (az+bz) * 0.5; | |
renderRec(renderRecMap, v0, nRss.v0, v2, nIndex); | |
renderRecMap.a = emMap.a*2+emMap.b; | |
renderRecMap.c = 2*emMap.c+emMap.d; | |
renderRecMap.tx = emMap.tx*2+emMap.ty-1; | |
renderRec(renderRecMap, nRss.v0, v1, v2, nIndex); | |
return; | |
} | |
if (d2ca == dmax){ | |
renderRecMap.a = emMap.a; | |
renderRecMap.b = emMap.b*2; | |
renderRecMap.c = emMap.c; | |
renderRecMap.d = emMap.d*2; | |
renderRecMap.tx = emMap.tx; | |
renderRecMap.ty = emMap.ty*2; | |
nRss.v2.x = mcax * 0.5; | |
nRss.v2.y = mcay * 0.5; | |
nRss.v2.z = (cz+az) * 0.5; | |
renderRec(renderRecMap, v0, v1, nRss.v2, nIndex); | |
renderRecMap.b += emMap.a; | |
renderRecMap.d += emMap.c; | |
renderRecMap.ty += emMap.tx-1; | |
renderRec(renderRecMap, nRss.v2, v1, v2, nIndex); | |
return; | |
} | |
renderRecMap.a = emMap.a-emMap.b; | |
renderRecMap.b = emMap.b*2; | |
renderRecMap.c = emMap.c-emMap.d; | |
renderRecMap.d = emMap.d*2; | |
renderRecMap.tx = emMap.tx-emMap.ty; | |
renderRecMap.ty = emMap.ty*2; | |
nRss.v1.x = mbcx * 0.5; | |
nRss.v1.y = mbcy * 0.5; | |
nRss.v1.z = (bz+cz)*0.5; | |
renderRec(renderRecMap, v0, v1, nRss.v1, nIndex); | |
renderRecMap.a = emMap.a*2; | |
renderRecMap.b = emMap.b-emMap.a; | |
renderRecMap.c = emMap.c*2; | |
renderRecMap.d = emMap.d-emMap.c; | |
renderRecMap.tx = emMap.tx*2; | |
renderRecMap.ty = emMap.ty-emMap.tx; | |
renderRec(renderRecMap, v0, nRss.v1, v2, nIndex); | |
} | |
/** | |
* Returns a string value representing the material properties in the specified BitmapMaterial object. | |
* | |
* @return A string. | |
*/ | |
public override function toString(): String | |
{ | |
return 'Texture:' + this.texture + ' lineColor:' + this.lineColor + ' lineAlpha:' + this.lineAlpha; | |
} | |
// ______________________________________________________________________ CREATE BITMAP | |
protected function createBitmap( asset:BitmapData ):BitmapData | |
{ | |
resetMapping(); | |
var bm:BitmapData; | |
if( AUTO_MIP_MAPPING ) | |
{ | |
bm = correctBitmap( asset ); | |
} | |
else | |
{ | |
this.maxU = this.maxV = 1; | |
bm = asset; | |
} | |
return bm; | |
} | |
// ______________________________________________________________________ CORRECT BITMAP FOR MIP MAPPING | |
protected function correctBitmap( bitmap :BitmapData ):BitmapData | |
{ | |
var okBitmap :BitmapData; | |
var levels :Number = 1 << MIP_MAP_DEPTH; | |
// this is faster than Math.ceil | |
var bWidth :Number = bitmap.width / levels; | |
bWidth = bWidth == uint(bWidth) ? bWidth : uint(bWidth)+1; | |
var bHeight :Number = bitmap.height / levels; | |
bHeight = bHeight == uint(bHeight) ? bHeight : uint(bHeight)+1; | |
var width :Number = levels * bWidth; | |
var height :Number = levels * bHeight; | |
// Check for BitmapData maximum size | |
var ok:Boolean = true; | |
if( width > 2880 ) | |
{ | |
width = bitmap.width; | |
ok = false; | |
} | |
if( height > 2880 ) | |
{ | |
height = bitmap.height; | |
ok = false; | |
} | |
if( ! ok ) PaperLogger.warning( "Material " + this.name + ": Texture too big for mip mapping. Resizing recommended for better performance and quality." ); | |
// Create new bitmap? | |
if( bitmap && ( bitmap.width % levels !=0 || bitmap.height % levels != 0 ) ) | |
{ | |
okBitmap = new BitmapData( width, height, bitmap.transparent, 0x00000000 ); | |
// this is for ISM and offsetting bitmaps that have been resized | |
widthOffset = bitmap.width; | |
heightOffset = bitmap.height; | |
this.maxU = bitmap.width / width; | |
this.maxV = bitmap.height / height; | |
okBitmap.draw( bitmap ); | |
// PLEASE DO NOT REMOVE | |
extendBitmapEdges( okBitmap, bitmap.width, bitmap.height ); | |
} | |
else | |
{ | |
this.maxU = this.maxV = 1; | |
okBitmap = bitmap; | |
} | |
return okBitmap; | |
} | |
protected function extendBitmapEdges( bmp:BitmapData, originalWidth:Number, originalHeight:Number ):void | |
{ | |
var srcRect :Rectangle = new Rectangle(); | |
var dstPoint :Point = new Point(); | |
var i :int; | |
// Check width | |
if( bmp.width > originalWidth ) | |
{ | |
// Extend width | |
srcRect.x = originalWidth-1; | |
srcRect.y = 0; | |
srcRect.width = 1; | |
srcRect.height = originalHeight; | |
dstPoint.y = 0; | |
for( i = originalWidth; i < bmp.width; i++ ) | |
{ | |
dstPoint.x = i; | |
bmp.copyPixels( bmp, srcRect, dstPoint ); | |
} | |
} | |
// Check height | |
if( bmp.height > originalHeight ) | |
{ | |
// Extend height | |
srcRect.x = 0; | |
srcRect.y = originalHeight-1; | |
srcRect.width = bmp.width; | |
srcRect.height = 1; | |
dstPoint.x = 0; | |
for( i = originalHeight; i < bmp.height; i++ ) | |
{ | |
dstPoint.y = i; | |
bmp.copyPixels( bmp, srcRect, dstPoint ); | |
} | |
} | |
} | |
// ______________________________________________________________________ | |
/** | |
* resetUVMatrices(); | |
* | |
* Resets the precalculated uvmatrices, so they can be recalculated | |
*/ | |
public function resetUVS():void | |
{ | |
for ( var obj:* in uvMatrices ) { | |
uvMatrices[obj] = null; | |
} | |
} | |
/** | |
* Copies the properties of a material. | |
* | |
* @param material Material to copy from. | |
*/ | |
override public function copy( material :MaterialObject3D ):void | |
{ | |
super.copy( material ); | |
this.maxU = material.maxU; | |
this.maxV = material.maxV; | |
} | |
/** | |
* Creates a copy of the material. | |
* | |
* @return A newly created material that contains the same properties. | |
*/ | |
override public function clone():MaterialObject3D | |
{ | |
var cloned:MaterialObject3D = super.clone(); | |
cloned.maxU = this.maxU; | |
cloned.maxV = this.maxV; | |
return cloned; | |
} | |
/** | |
* Sets the material's precise rendering mode. If set to true, material will adaptively render triangles to conquer texture distortion. | |
*/ | |
public function set precise(boolean:Boolean):void | |
{ | |
_precise = boolean; | |
} | |
public function get precise():Boolean | |
{ | |
return _precise; | |
} | |
/** | |
* If the material is rendering with @see precise to true, this sets tesselation per pixel ratio. | |
*/ | |
public function set precision(precision:int):void | |
{ | |
_precision = precision; | |
} | |
public function get precision():int | |
{ | |
return _precision; | |
} | |
/** | |
* If the material is rendering with @see precise to true, this sets tesselation per pixel ratio. | |
* | |
* corrected to set per pixel precision exactly. | |
*/ | |
public function set pixelPrecision(precision:int):void | |
{ | |
_precision = precision*precision*1.4; | |
_perPixelPrecision = precision; | |
} | |
public function get pixelPrecision():int | |
{ | |
return _perPixelPrecision; | |
} | |
/** | |
* A texture object. | |
*/ | |
public function get texture():Object | |
{ | |
return this._texture; | |
} | |
/** | |
* @private | |
*/ | |
public function set texture( asset:Object ):void | |
{ | |
if( asset is BitmapData == false ) | |
{ | |
PaperLogger.error("BitmapMaterial.texture requires a BitmapData object for the texture"); | |
return; | |
} | |
bitmap = createBitmap( BitmapData(asset) ); | |
_texture = asset; | |
} | |
override public function destroy():void | |
{ | |
super.destroy(); | |
if(uvMatrices){ | |
uvMatrices = null; | |
} | |
if(bitmap){ | |
bitmap.dispose(); | |
} | |
this.renderRecStorage = null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment