简体   繁体   English

如何使用透视投影获取DisplayObject的可见大小

[英]How to get visible size of DisplayObject with perspective projection

The following is entirely a math question. 以下完全是一个数学问题。

As we know, PerspectiveProjection delivers perspective transformations in 3D represented by the interdependent values of fieldOfView and focalLength according to the following formula: 众所周知, PerspectiveProjection根据以下公式,以fieldOfViewfocalLength的相互依赖值表示的3D透视图转换:

focalLength = stageWidth/2 * (cos(fieldOfView/2) / sin(fieldOfView/2)

BjørnGunnar Staal的插图
(source: bgstaal.net ) (来源: bgstaal.net

Q: How to get the visible on-screen size of the DisplayObject (Cube on the above-linked image) to which PerspectiveProjection has been applied? 问: 如何获取已应用PerspectiveProjection的DisplayObject(在上面链接的图像上为多维数据集)的可见屏幕大小?

A more thorough description and illustrative code on the issue in ActionScript 3 lacks functionality for visible bounds of DisplayObject . 有关ActionScript 3中问题的更详尽的描述和说明性代码缺少DisplayObject可见范围的功能

I think I'm missing the point. 我想我没说清楚。

I did a simple test in the ide, put 3 clips together like so: 我在ide中做了一个简单的测试,将3个剪辑放在一起,如下所示: 3D尺寸

The width and height report the size of the visible 3d area, as you can see in the property inspector as well. 宽度和高度报告可见3d区域的大小,您也可以在属性检查器中看到。 You can access just as simple as 您可以像访问一样简单

trace(cube.width + ' by ' + cube.height);

at runtime or with a bit of jsfl: 在运行时或使用jsfl:

var doc = fl.getDocumentDOM();
fl.outputPanel.clear();
fl.trace(doc.selection[0].width + ' by ' + doc.selection[0].height);

for one selected clip at authortime, within the IDE. 在IDE中在创作时针对一个选定的剪辑。

I did a similar test with a bit of actionscript: 我用一些动作脚本做了类似的测试:

//draw faces
var front:Sprite = drawFace();
var back:Sprite = drawFace();
var left:Sprite = drawFace();
var right:Sprite = drawFace();
var top:Sprite = drawFace();
var bottom:Sprite = drawFace();
//transform faces
front.z  = -50;
back.z   =  50;
left.x   = -50;
right.x  =  50;
top.y    = -50;
bottom.y =  50;
left.rotationY = right.rotationY = 90;
top.rotationX = bottom.rotationX = 90;
//putem them all together
var cube:Sprite = new Sprite();
cube.addChild(front);
cube.addChild(back);
cube.addChild(left);
cube.addChild(right);
cube.addChild(top);
cube.addChild(bottom);
addChild(cube);
cube.x = stage.stageWidth * .5;
cube.y = stage.stageHeight* .5;
cube.z = -100;
cube.rotationX = cube.rotationY = 30;

trace(cube.width + ' by ' + cube.height);
trace(cube.getBounds(this));
trace(cube.transform.pixelBounds);
this.addEventListener(Event.ENTER_FRAME, loop);
function loop(event:Event):void {
    cube.rotationY += 3;
    var b:Rectangle = cube.getBounds(this);
    graphics.clear();
    graphics.lineStyle(1,0x009900);
    graphics.drawRect(b.x,b.y,b.width,b.height);
}

function drawFace():Sprite{
    var s:Sprite = new Sprite();
    s.graphics.beginFill(0x000099,.5);
    s.graphics.drawRect(-50,-50,100,100);
    s.graphics.endFill();
    return s;
}

Here is a modified sample from Programming Actionscript 3.0 这是《 ActionScript 3.0》的修改后示例

package {  
    import flash.display.*  
    import flash.events.*;  
    import flash.utils.getTimer;  
    import flash.geom.*;

    public class Triangles extends Sprite {  
        var x1:Number = -100,y1:Number = -100,z1:Number = 0,t1:Number = 0;  
        var x2:Number = 100,y2:Number = -100,z2:Number = 0,t2:Number = 0;  
        var x3:Number = 100,y3:Number = 100,z3:Number = 0,t3:Number = 0;  
        var x4:Number = -100,y4:Number = 100,z4:Number = 0,t4:Number = 0;  
        var v1 = new Vector3D(-100,-100,0,0);
        var v2 = new Vector3D(100,-100,0,0);
        var v3 = new Vector3D(100,100,0,0);
        var v4 = new Vector3D(-100,100,0,0);
        var focalLength:Number = 200;   
        var indices:Vector.<int>;  

        var container:Sprite;  

        var bitmapData:BitmapData; // texture  
        var imageLoader:ImageLoader;  

        public function Triangles():void {  
            indices =  new Vector.<int>();  
            indices.push(0,1,3, 1,2,3);  

            container = new Sprite(); // container to draw triangles in  
            container.x = 200;  
            container.y = 200;  
            addChild(container);  

            imageLoader = new ImageLoader("head.jpg");  
            imageLoader.addEventListener(Event.COMPLETE, onImageLoaded);  
        }  

        function onImageLoaded(event:Event):void {  
            bitmapData = imageLoader.bitmap.bitmapData; 
            addEventListener(Event.ENTER_FRAME, rotatePlane);  
        }  
        function rotatePlane(event:Event):void {  
            var ticker = getTimer()/1600;  
            z2 = z3 = -(z1 = z4 = 100*Math.sin(ticker));  
            x2 = x3 = -(x1 = x4 = 100*Math.cos(ticker));  

            v2.z = v3.z = -(v1.z = v4.z = 100*Math.sin(ticker));
            v2.x = v3.x = -(v1.x = v4.x = 100*Math.cos(ticker));


            t1 = focalLength/(focalLength + z1);  
            t2 = focalLength/(focalLength + z2);  
            t3 = focalLength/(focalLength + z3);  
            t4 = focalLength/(focalLength + z4);  

            v1.w = focalLength/(focalLength + v1.z);  
            v2.w = focalLength/(focalLength + v2.z);  
            v3.w = focalLength/(focalLength + v3.z);  
            v4.w = focalLength/(focalLength + v4.z);  

            // determine triangle vertices based on t values  
            var vertices:Vector.<Number> = new Vector.<Number>();  
            //vertices.push(x1*t1,y1*t1, x2*t2,y2*t2, x3*t3,y3*t3, x4*t4,y4*t4);  

            vertices.push(v1.x*v1.w,v1.y*v1.w, v2.x*v2.w,v2.y*v2.w, v3.x*v3.w,v3.y*v3.w, v4.x*v4.w,v4.y*v4.w);  
            var uvtData:Vector.<Number> = new Vector.<Number>();  
            uvtData.push(0,0,v1.w, 1,0,v2.w, 1,1,v3.w, 0,1,v4.w);  

            // draw  
            container.graphics.clear();  
            container.graphics.beginBitmapFill(bitmapData);  
            container.graphics.drawTriangles(vertices, indices, uvtData);  
            var b:Rectangle = container.transform.pixelBounds;
            graphics.clear();
            graphics.lineStyle(1,0x009900);
            graphics.drawRect(b.x,b.y,b.width,b.height);
        }  
    }  
} 

pixelBounds work well here, but it's a simple plane. pixelBounds在这里可以很好地工作,但这是一个简单的平面。 pixelBounds wouldn't work in the previous example, but getBounds() seems to work fine. pixelBounds在上一个示例中不起作用,但是getBounds()似乎可以正常工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM