我正在尝试使用par3d()在rgl中设置自定义userMatrix,但由于只读modelMatrix的重新计算,所产生的视图会产生不必要的副作用。 (https://www.rdocumentation.org/packages/rgl/versions/0.97.0/topics/par3d,章节:渲染) 此外,近距离和远距离剔除平面(我似乎无法修改)在靠近/远离视点时过早地切割物体。
我的目标是以交互方式导航(使用Z轴向上)一个带有回归平面和曲面的点云,比在场景中居中的旋转和缩放更自由(我已经看到使用rgl.setMouseCallbacks的平移示例) )。
重新绘制场景以移动它实际上不是一个选项,但是对一些场景对象应用自定义转换可能是另一种方法,但更像是一种解决方法。
提前感谢您的反馈!
答案 0 :(得分:0)
你的问题太模糊了。什么是“不必要的副作用”?但我会尝试:
在最简单的情况下,模型矩阵M设置为U V,其中V由系统设置(如?par3d中所述),U完全在您的控制之下。因此,如果您想要完全控制M,首先将U设置为标识并读取M以获得V,然后为了获得新的M',将U设置为M'V ^ -1。
剪切平面是投影矩阵的一个特征。那里你没有很多控制权。
答案 1 :(得分:0)
因此,此示例代码在rgl中生成FPV或第三人称视图,包括hack(微调-550常量)以使视图更接近枢轴点(如果有人的话,这不应该是必要的完全控制所有矩阵)。 近距离裁剪/剔除仍在那里,但可以接受。
library("rgl")
library("Morpho")
rglInit <- function()
{
rgl.open()
rgl.viewpoint(fov=110, type="userviewpoint")
defaultUserMatrix <<- par3d()$userMatrix
}
lookAt3d <-function(eye, center, up)
{
cat("*** lookat\n")
cat("eye\n")
print(eye)
cat("center\n")
print(center)
cat("up\n")
print(up)
fwd = center - eye
fwd = fwd / sqrt(sum(fwd^2))
upn = up / sqrt(sum(up^2))
side = crossProduct(fwd, up)
upnt = crossProduct(side, fwd)
M = rbind(c(side, 0), c(upnt, 0), c(-fwd, 0), c(0,0,0,1))
M = M %*% t(translationMatrix(-550 * fwd[1] - eye[1],
-550 * fwd[2] - eye[2],
-550 * fwd[3] - eye[3])) # -550 hack seems to put the view closer to the pivot point
cat("result\n")
print(M)
return (M)
}
yawPitchDirection3d <- function(yawAngle, pitchAngle)
{
c(
cos(pitchAngle) * cos(yawAngle),
cos(pitchAngle) * sin(yawAngle),
sin(pitchAngle))
}
lookAtYawPitch3d <- function(eye, yawAngle, pitchAngle)
{
fwd = yawPitchDirection3d(yawAngle, pitchAngle)
lookAt3d(eye, eye + fwd, c(0,0,1))
}
addTestScene <- function()
{
data(volcano)
z <- 2 * volcano # Exaggerate the relief
x <- 10 * (1:nrow(z)) # 10 meter spacing (S to N)
y <- 10 * (1:ncol(z)) # 10 meter spacing (E to W)
zlim <- range(z)
zlen <- zlim[2] - zlim[1] + 1
colorlut <- terrain.colors(zlen) # height color lookup table
col <- colorlut[ z-zlim[1]+1 ] # assign colors to heights for each point
rgl.surface(x, y, z, coords = c(1,3,2), color=col, back="lines")
axis3d('x', pos=c( NA, 0, 0 ), col = "red")
axis3d('y', pos=c( 0, NA, 0 ), col = "green")
axis3d('z', pos=c( 0, 0, NA ), col = "blue")
}
view = list()
resetView <- function()
{
view$yaw <<- 0.6
view$pitch <<- -1
view$eye <<- c(-360, -250,115)
setView()
}
setView <- function(yawDiff = 0.0, pitchDiff = 0.0, fwdDiff = 0.0, sideDiff = 0.0,
newView = NULL, delta = T)
{
view$yaw <<- view$yaw + yawDiff
view$pitch <<- view$pitch + pitchDiff
if (view$pitch > 0.99 * pi / 2)
{
view$pitch <<- 0.99 * pi / 2
}
if (view$pitch < -0.99 * pi / 2)
{
view$pitch <<- -0.99 * pi / 2
}
cat("*** Setview\n")
cat("Yaw\n")
print(view$yaw)
cat("Pitch\n")
print(view$pitch)
cat("Eye\n")
print(view$eye)
fwd = yawPitchDirection3d(view$yaw, view$pitch)
up = c(0,0,1)
upn = up / sqrt(sum(up^2))
side = crossProduct(fwd, up)
view$eye <<- view$eye + sideDiff * side + fwdDiff * fwd
userView = lookAtYawPitch3d(eye = view$eye,
yawAngle = view$yaw,
pitchAngle = view$pitch)
par3d(userMatrix = userView)
}
setMouseCallbacks <- function()
{
clickPrev <- list()
rgl.setMouseCallbacks(1,
begin = function(x, y)
{
clickPrev$x1 <<- x
clickPrev$y1 <<- y
},
update = function(x, y)
{
setView(yawDiff = -0.05 * (x - clickPrev$x1) / pi,
pitchDiff = -0.05 * (y - clickPrev$y1) / pi)
clickPrev$x1 <<- x
clickPrev$y1 <<- y
cat("*** Drag MB1\n")
cat("userMatrix\n")
print(par3d()$userMatrix)
cat("modelMatrix\n")
print(par3d()$modelMatrix)
cat("projMatrix\n")
print(par3d()$projMatrix)
}
)
rgl.setMouseCallbacks(2,
begin = function(x, y)
{
clickPrev$x2 <<- x
clickPrev$y2 <<- y
},
update = function(x, y)
{
setView(fwdDiff = -0.5 * (y - clickPrev$y2),
sideDiff = -0.5 * (x - clickPrev$x2))
clickPrev$x2 <<- x
clickPrev$y2 <<- y
cat("*** Drag MB2\n")
cat("userMatrix\n")
print(par3d()$userMatrix)
cat("modelMatrix\n")
print(par3d()$modelMatrix)
cat("projMatrix\n")
print(par3d()$projMatrix)
}
)
}
rglInit()
resetView()
addTestScene()
setMouseCallbacks()