AS3 - 几何学 - 在二维平面上进行点的透视投影

7
我目前遇到的问题似乎远远超出了我的数学能力(我已经很久没有做过一些适当的数学练习了),希望能得到一些帮助。
这是我的场景: 我有一些简单的形状(矩形),并且我将它们的底部点“投射”到从原点开始的一条线上。到此为止一切都好。但现在我想画出原始形状,仿佛它被投影到一个平面上的透视图中一样。
请注意,我的代码与任何旋转、等轴或任何3D或虚假的2D透视无关,我只是试图使用图形库来绘制一些形状,以便只有一种真实感觉。
这是我正在尝试做的事情的快速绘图:
我知道:
1. 原点坐标 2. 矩形位置和大小 3. 红线的位置 4. A和B点的坐标
我想确定C和D点的坐标,这个问题如果我能找到“原点角”的坐标就很容易解决了。
我试图伪造我的矩形在可以被视为“地板”的东西上的投影(与我的原始矩形所在的平面相关,可以视为墙壁)。
也许我正在过度复杂化问题,或者我没有看到其他更容易的方法来解决它,但是我真的不再擅长任何几何学或数学方面的事情。谢谢你们!

我不明白,您是只看矩形底部的投影吗?如果是这样,在不同角度观察时,您将只看到一条线而不是整个矩形。如果想要整个矩形,您必须将其全部投影在红线上。 - Bitwise
那么,Origin bis是必须生成的东西,还是在某个设定变量中?如果我们有一个原点Bi坐标或一个绿线之类的东西,这将更容易。绿线将使我们能够创建虚假的直角三角形。像相机一样使用Origin Bis在3D场景中。 - Joe Plante
是的,这正是我担心的...我希望有一些神奇的东西可以帮助我在没有3D的情况下伪造一些3D透视效果...至少我会考虑使用3D进行计算,谢谢! - elFlashor
我认为这个问题非常适合 Adobe 在 Flash 中提供的有限的 3D 功能。你不能使用它的具体原因是什么? 因为你的问题可以在 1 分钟内解决:复制矩形,并围绕其 X 轴旋转。你可以设置透视点,甚至移动它。你可以拥有多个矩形和阴影,它们都会“感觉”非常真实。 - Kokodoko
换句话说:使用图形引擎绘制一个矩形,然后:myRectangle.rotationX = 45; - Kokodoko
显示剩余5条评论
3个回答

0

如果我没错的话,这段代码将展示你想要看到的内容。

首先,我忽略了你最初设置的对象和信息,并专注于示例情况本身;为“单块”(使用下面的示例,任何对象都可以,甚至是纹理)伪投影阴影。 我的理由是,使用 ActionScript 的 Matrix 类非常容易,这是一个值得学习的方便工具。

解决方案: 您可以使用内置的 Matrix 类对 DisplayObject 进行扭曲变换。 尝试这个示例:

(“有用”的部分在 _EF EnterFrame 处理程序中 ;) )

import flash.display.MovieClip;
import flash.geom.Matrix;
import flash.events.Event;
import flash.display.BitmapData;

const PIP180:Number = Math.PI / 180;
const MAX_SHADOW_HEIGHT_MULTIPLIER:Number = 0.25; // you can also calculate this from an angle, like ... = Math.sin(angle * PIP180);
const ANIM_DEG_PER_FRAME:Number = 1.0 * PIP180; // the shadow creeps at a +1 degree per frame rate

var tx:BitmapData = new MonolithTexture(); // define this BitmapData in the library
var skew:Number = -10 * PIP180; // initial 

var mono:MovieClip = new MovieClip();
mono.graphics.beginBitmapFill(tx);
// drawn that way the registration point is 0,0, so it's standing on the ground
mono.graphics.drawRect(0, -tx.height, tx.width, tx.height);
mono.graphics.endFill();

// align monolith to the "ground"
mono.x = stage.stageWidth / 2;
mono.y = stage.stageHeight - 100;
// make it be 100x300 pixel
mono.width = 100;
mono.height = 300;

var shad:MovieClip = new MovieClip();
// colored:
shad.graphics.beginFill(0x000000);
// or textured:
//shad.graphics.beginBitmapFill(tx);
shad.graphics.drawRect(0, -tx.height, tx.width, tx.height);
shad.graphics.endFill();

addChild(shad); // shadow first
addChild(mono); // then the caster object

addEventListener(Event.ENTER_FRAME, _EF);

function _EF(e:Event):void {
    // animate skew on the positive half circle
    skew = (skew + ANIM_DEG_PER_FRAME) % Math.PI;

    // Matrix takes 6 parameters: a, b, c, d, x, y
    // for this shadow trick, use them as follows:
    // a = width scaling (as mono and shad are drawn in the same way, copy mono.scaleX for a perfect fit
    // b = 0, because we don't want to project the vertical axis of transformation to the horizontal
    // c = horizontal skew
    // d = height scaling * skew * making it a bit flat using the constant
    // x = mono.x, ...
    // y = mono.y since originally mono and shad look alike, only the Matrix makes shad render differently
    var mtx:Matrix = new Matrix(mono.scaleX, 0, Math.cos(skew), mono.scaleY * Math.sin(skew) * MAX_SHADOW_HEIGHT_MULTIPLIER, mono.x, mono.y);
    shad.transform.matrix = mtx;
}

现在你需要知道的是如何将这个应用到你的情况中,以下是N个因素:
Q1:你想从什么角度投影阴影?
A1:水平因素是skew变量本身,而垂直角度在此处被存储为常量,称为MAX_SHADOW_HEIGHT_MULTIPLIER

Q2:你只想向上投影阴影还是自由投影? A2:如果只向上投影阴影,则保持skew在正范围内,否则让它取负值以获得“向下”阴影。

P.S.:如果您将对象的内部呈现为不与0 y对齐的基点,则可以使它们看起来漂浮/下沉,或者使用相反符号的预定义值垂直偏移两个对象。


0

你面临一个非常简单的问题,就像你所说的:

“我想确定C和D点的坐标,如果我不努力寻找“原点bis”坐标,这可能很容易。”

但是这些坐标彼此相关,因此如果没有其中一个(或另一个值,例如角度),则无法获得另一个。如果您要在3D中尝试此操作,则只需允许3D引擎定义“原点bis”并自行计算C和D的位置。

因此,无论如何,您都需要一个“原始bis”,即与红线或矩形相关的另一个值,以计算C和D的位置。

我记得做这样的东西有时候最好还是简单点,你可以自己定义一个“原始 bis”(它可以是静止的或者随着玩家/背景移动),并且用与获取 A 和 B 相同的方式获取 C 和 D,只不过你使用比红线低的线条,或者像我一样,一旦你有了 A 和 B,就简单地扭曲/旋转你从这些点投射下去的图像,再往下一点,你就会得到一个跟随玩家的“原始 bis”。这在模拟“真实感”方面效果很好,但遗憾的是,正如已经说过的那样,它看起来真实取决于你所描绘的内容。我们不知道红线上方或下方的区域是什么(天空/地面、地面/水面),以及“原点”和“原始 bis”是否是你的光源、消失点等。


0

嗯,我不确定我是否理解正确,但我认为您的输入参数太少了:

您提到以下信息已知:

  • 起点坐标
  • 矩形位置和大小
  • 红线位置
  • A和B点坐标

仅凭这些信息似乎无法得出所需的投影矩形。此外,我认为您的绿线和“origin Bis”也没有帮助。

也许可以尝试这样做: 假设还有一条蓝线穿过C和D两点。 然后,您可以将矩形顶部投影到该蓝线上,从而找到所需的投影矩形。

因此,总结一下: 您需要定义一个起点和两条平行线,一条红线和一条蓝线。 然后,您可以将矩形的顶部投影到蓝线上,将底部投影到红线上,从而得到A、B、C、D四个点。

希望这能帮到您。


谢谢你的回答,但是我在我的帖子中没有提到你所说的那条蓝线,因为我忘了 :-) 事实是:如果我有那条蓝线,我怎么能将矩形的顶部投影到它上面呢?我不能简单地从相同的原点投影它们,这会感觉像一些光线击中了地板,我需要知道/找到顶部投影和底部投影之间的水平偏移量,以使我的投影矩形真正感受到从原始形状投影出来的正确角度(因此,原点的双分点旨在给我这个角度差异...) - elFlashor
嗯,我不知道关于投影应该“感觉”如何的任何信息,但主要有两种类型的投影被使用:正交或透视。在透视投影中,您有一个原点,并通过从原点通过矩形点绘制线条来进行投影。那是我建议的版本。在正交投影中,您只需预定义一个方向向量并将点投射到该方向。 - D-rk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接