[]viewportPointToRay产生的射线始终有偏差,是为什么?

我使用这种方式构造了一个射线:
let point = new Vector2(Laya.stage.mouseX, Laya.stage.mouseY);
camera.viewportPointToRay(point, this._ray);
然后发现ray构造出来的位置始终不对,我沿着ray的方向放了一组3D物体,和从屏幕点击下去的位置始终有一定偏差~
请教一下有哪些可能可以排查这个问题?
已邀请:

myala34

赞同来自: 155*****359

请问这个问题有解决吗?

watsonsong

赞同来自:

我添加了一个SceneScript来绘制Ray的射线,发现确实位置不正确:
    import Camera = Laya.Camera;
import PhasorSpriter3D = Laya.PhasorSpriter3D;
import Ray = Laya.Ray;
import RenderState = Laya.RenderState;
import Script = Laya.Script;
import Vector2 = Laya.Vector2;
import Vector3 = Laya.Vector3;
import Vector4 = Laya.Vector4;
import WebGLContext = Laya.WebGLContext;

export class SceneScript extends Script {
private _originPosition:Vector3 = new Vector3(0, -1, 1);
private _phasorSpriter3D:PhasorSpriter3D;
private _color:Vector4 = new Vector4(1, 0, 0, 1);
private _point:Vector2 = new Vector2();
private _camera:Camera;
private _ray:Ray = new Ray(new Vector3(0, 0, 0), new Vector3(0, 0, 0));

public _start(state:RenderState):void {
super._start(state);

this._phasorSpriter3D = new PhasorSpriter3D();
this._camera = this._owner.getChildByName("Camera") as Camera;
}

public _postRenderUpdate(state:RenderState):void {
super._update(state);

this._point.elements[0] = Laya.stage.mouseX;
this._point.elements[1] = Laya.stage.mouseY;
this._camera.viewportPointToRay(this._point, this._ray);

this._phasorSpriter3D.begin(WebGLContext.LINES, this._camera);

//绘出射线
this._phasorSpriter3D.line(
this._ray.origin,
this._color,
this._originPosition,
this._color);

this._phasorSpriter3D.end();
}
}
结果出来是图片中的结果:

QQ截图20180201151504.png


鼠标的位置在戒指的图标处,但是摄像的终点位置却不对。
 

watsonsong

赞同来自:

附件中就是测试工程,Ray和鼠标之间有偏差~
测试主要是因为:
Laya.stage.scaleMode = Laya.Stage.SCALE_SHOWALL;
这个缩放模式引起的,这种模式下有什么特别要注意的地方么,构造Ray的时候~
import Camera = Laya.Camera;
import PhasorSpriter3D = Laya.PhasorSpriter3D;
import Ray = Laya.Ray;
import RenderState = Laya.RenderState;
import Script = Laya.Script;
import Vector2 = Laya.Vector2;
import Vector3 = Laya.Vector3;
import Vector4 = Laya.Vector4;
import WebGLContext = Laya.WebGLContext;

class SceneScript extends Script {
private _originPosition: Vector3 = new Vector3(0, 0, 0);
private _phasorSpriter3D: PhasorSpriter3D;
private _color: Vector4 = new Vector4(1, 0, 0, 1);
private _point: Vector2 = new Vector2();
private _camera: Camera;
private _ray: Ray = new Ray(new Vector3(0, 0, 0), new Vector3(0, 0, 0));

public _start(state: RenderState): void {
super._start(state);

this._phasorSpriter3D = new PhasorSpriter3D();
this._camera = this._owner.getChildByName("Camera") as Camera;
}

public _postRenderUpdate(state: RenderState): void {
super._update(state);

this._point.elements[0] = Laya.stage.mouseX;
this._point.elements[1] = Laya.stage.mouseY;
this._camera.viewportPointToRay(this._point, this._ray);

this._phasorSpriter3D.begin(WebGLContext.LINES, this._camera);

// 绘出射线
this._phasorSpriter3D.line(
this._ray.origin,
this._color,
this._originPosition,
this._color);

this._phasorSpriter3D.end();
}
}

// 程序入口
class GameMain {
constructor() {
Laya3D.init(1334, 768, true, true);

Laya.stage.alignV = Laya.Stage.ALIGN_MIDDLE;
Laya.stage.alignH = Laya.Stage.ALIGN_CENTER;

Laya.stage.scaleMode = Laya.Stage.SCALE_SHOWALL;
Laya.stage.bgColor = "#232628";

Laya.Stat.show();

let camera: Laya.Camera = new Laya.Camera();
camera.name = "Camera";
camera.transform.position = new Laya.Vector3(
-6.87492561340332, 3.95000958442688, 1.06434166431427);
camera.transform.rotation = new Laya.Quaternion(
-0.19387270510196686,
-0.6291995048522949,
-0.16616787016391754,
0.7341046333312988);
let scene: Laya.Scene = new Laya.Scene();
scene.addChild(camera);
scene.addScript(SceneScript);
Laya.stage.addChild(scene);
}
}

new GameMain();

qian

赞同来自:

自己new的摄像机和射线检测误差没有关系
参考 引擎示例 -3d--射线检测--射线检测
这个示例
这恶鬼示例没有误差

watsonsong

赞同来自:

Laya.stage.scaleMode = Laya.Stage.SCALE_SHOWALL;
设置了这种scaleMode之后,计算射线就会出问题,请看看附件的工程。

aSong

赞同来自:

 
要射出的点进行以下处理之后就可以了
this.point = this.changeToClientWorld(this.point)
//在showall模式下将屏幕坐标转换到client空间坐标,为射线检测偏差使用
public changeToClientWorld(input:Laya.Vector2):Laya.Vector2
{
let ratioX = (input.x / Laya.stage.width);
let ratioY = (input.y / Laya.stage.height);
let clientWidth = Laya.stage.clientScaleX * Laya.stage.width
let clientHeight = Laya.stage.clientScaleY * Laya.stage.height
 
// let singleX = (Laya.Browser.width - clientWidth)/2;
// let singleY = (Laya.Browser.height - clientHeight)/2;
input.x = ratioX * clientWidth;//singleX,Y 看效果自行修改
input.y = ratioY * clientHeight;
return input;
}

要回复问题请先

商务合作
商务合作