代码之家  ›  专栏  ›  技术社区  ›  Ain Tohvri

如何利用透视投影获取显示对象的可见尺寸

  •  0
  • Ain Tohvri  · 技术社区  · 15 年前

    如我们所知, 透视投影 根据以下公式,在由 视场 聚焦长度 的相互依赖值表示的3D中提供透视变换:


    (来源:bgstal.net/blog/wp-content/uploads/2009/06/figure11.jpg“rel=”nofollow noreferrer“>bgstal.net)

    关于这个问题的更详细的描述和说明性代码,请参见 actionscript 3缺少displayobject的可见边界功能

    提供由以下相互依赖的值表示的三维透视转换 fieldOfView focalLength

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

    Illustration by Bjørn Gunnar Staal
    (来源: bgstaal.net )

    如何获取已应用透视投影的显示对象(上面链接图像上的立方体)的可见屏幕大小?

    中有关此问题的更详细描述和说明性代码 ActionScript 3 lacks functionality for visible bounds of DisplayObject .

    1 回复  |  直到 6 年前
        1
  •  2
  •   Community CDub    8 年前

    我想我没抓住重点。

    我在ide中做了一个简单的测试,将3个剪辑放在一起,如下所示: 3d size

    宽度和高度报告可见三维区域的大小, 正如您在属性检查器中看到的那样。 您可以访问

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

    在运行时或使用一点jsfl:

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

    我做了一个类似的测试,使用了一点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;
    }
    

    下面是来自编程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);
            }  
        }  
    }