SCM

Forum: help

Monitor Forum | Start New Thread Start New Thread
RE: Prevent re-calculation of modelMatrix and modify culling near/far planes in rgl [ Reply ]
By: Duncan Murdoch on 2017-06-30 22:56
[forum:45217]
The issue is that matrices don't commute. This could be documented better, but it's not easy stuff, so it's not easy to document.

I haven't read through your code in detail, but some comments:

- Avoid using rgl.* functions when *3d ones exist. They aren't the same, and the rgl.* functions often have nasty global side effects. In your case, I see rgl.open, where open3d is usually better, and rgl.surface, where surface3d is almost always better. I think the others are probably fine (or you have no choice).

- par3d()$userMatrix is less efficient than par3d("userMatrix"), because it computes the full list of values, then extracts just one. This probably doesn't matter, but there might be situations where it does.

RE: Prevent re-calculation of modelMatrix and modify culling near/far planes in rgl [ Reply ]
By: S Nielsen on 2017-06-30 22:08
[forum:45216]
Actually those libraries are not required.

I had a closer look at your (I guess?) panning example (included on button 3), and the differences basically boil down to using userMatrix = userMatrix0 %*% t(translationMatrix(...)) rather than userMatrix = translate3d(userMatrix0, ...), though they should be essentially the same - if properly called.

The switch "worksNotFails" changes between methods in the button 2 callback.

I think I can take it from here, even though the near culling plane clips quite early.
But thanks for reading, and bearing with the double post...

library("rgl")

rglInit <- function()
{
rgl.open()
rgl.viewpoint(fov=110, type="userviewpoint")
}

addTestScene <- function()
{
data(volcano)

y <- 2 * volcano # Exaggerate the relief

x <- 10 * (1:nrow(y)) # 10 meter spacing (S to N)
z <- 10 * (1:ncol(y)) # 10 meter spacing (E to W)

ylim <- range(y)
ylen <- ylim[2] - ylim[1] + 1

colorlut <- terrain.colors(ylen) # height color lookup table

col <- colorlut[ y-ylim[1]+1 ] # assign colors to heights for each point

rgl.surface(x, z, y, 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")
}

setMouseCallbacks <- function()
{
clickBegin <- list()

rgl.setMouseCallbacks(1,
begin = function(x, y)
{
cat("b1", x, y, "\n")
clickBegin$x1 <<- x
clickBegin$y1 <<- y
clickBegin$userMatrix <<- par3d()$userMatrix
},
update = function(x, y)
{
cat("u1", x - clickBegin$x1, y - clickBegin$y1, "\n")
userView = rotate3d(clickBegin$userMatrix, angle = (x - clickBegin$x1) / 100, x = 0, y = 1, z = 0)
userView = rotate3d(userView, angle = (y - clickBegin$y1) / 100, x = 1, y = 0, z = 0)
par3d(userMatrix = userView)
},
end = function()
{
cat("e1\n")
}
)
rgl.setMouseCallbacks(2,
begin = function(x, y)
{
cat("b2", x, y, "\n")
clickBegin$x2 <<- x
clickBegin$y2 <<- y
clickBegin$userMatrix <<- par3d()$userMatrix

print(par3d()$userMatrix)
print(par3d()$modelMatrix)
print(par3d()$projMatrix)
},
update = function(x, y)
{
cat("u2", x, y, "\n")

worksNotFails = T # set to FALSE for transformation problem
if (worksNotFails)
{
userView = translationMatrix(x = (x - clickBegin$x2), y = 0, z = (y - clickBegin$y2))
par3d(userMatrix = clickBegin$userMatrix %*% t(userView) )
}
else
{
userView = translate3d(clickBegin$userMatrix, x = (x - clickBegin$x2) / 10000.0, y = 0, z = (y - clickBegin$y2) / 10000.0)
par3d(userMatrix = userView)
}

print(par3d()$userMatrix)
print(par3d()$modelMatrix)
print(par3d()$projMatrix)
},
end = function()
{
cat("e2\n")
}
)

rgl.setMouseCallbacks(3,
begin = function(x, y)
{
cat("b3", x, y, "\n")
clickBegin$x3 <<- x
clickBegin$y3 <<- y

clickBegin$userMatrix <<- par3d()$userMatrix
clickBegin$viewport <<- par3d("viewport")
clickBegin$scale <<- par3d("scale")
clickBegin$projection <<- rgl.projection()
clickBegin$pos <<- rgl.window2user( x/clickBegin$viewport[3], 1 - y/clickBegin$viewport[4], 0.5,
projection = clickBegin$projection)

print(par3d()$userMatrix)
print(par3d()$modelMatrix)
print(par3d()$projMatrix)
},
update = function(x, y)
{
cat("u3", x, y, "\n")
xlat <- (rgl.window2user( x/clickBegin$viewport[3], 1 - y/clickBegin$viewport[4], 0.5,
projection = clickBegin$projection) - clickBegin$pos)*clickBegin$scale

mouseMatrix <- translationMatrix(xlat[1], xlat[2], xlat[3])

par3d(userMatrix = clickBegin$userMatrix %*% t(mouseMatrix) )


print(par3d()$userMatrix)
print(par3d()$modelMatrix)
print(par3d()$projMatrix)
},
end = function()
{
cat("e3\n")
}
)

}

rglInit()
addTestScene()
setMouseCallbacks()

RE: Prevent re-calculation of modelMatrix and modify culling near/far planes in rgl [ Reply ]
By: Duncan Murdoch on 2017-06-30 18:00
[forum:45215]
You are using plot3D and plot3Drgl, not just rgl. I have no idea what those packages are doing. They could well be messing you up.

Post an example using just rgl if you want advice.

RE: Prevent re-calculation of modelMatrix and modify culling near/far planes in rgl [ Reply ]
By: S Nielsen on 2017-06-30 09:48
[forum:45214]
So, my sample has a little typo, x1/y1 should be x2/y2 for button 2:
userView = translate3d(clickBegin$userMatrix, x = (x - clickBegin$x2) / 10000.0, z = 0, y = (y - clickBegin$y2) / 10000.0)

Also one should probably regard the translation in view coordinates [0-1] rather than model space, so one "pixel" is already a lot. Still, the translation just skews the perspective extremely without actually moving the scene.

RE: Prevent re-calculation of modelMatrix and modify culling near/far planes in rgl [ Reply ]
By: S Nielsen on 2017-06-30 07:13
[forum:45213]
I have made a minimal example applying rotation and translation with the mouse just to demonstrate the behavior.

If you translate slightly (right button) after having rotated (left button), the model matrix almost explodes, turning the scene into a flare. Rotation is working as expected though.

Ideally, I would like to achieve the functionality of gluLookAt:
https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluLookAt.xml
- but I have a feeling that things happen behind the scenes beyond my control...

require("plot3D")
require("plot3Drgl")

rglInit <- function()
{
rgl.open()
rgl.viewpoint(fov=60, type="userviewpoint")
}

addTestScene <- function()
{
data(volcano)

y <- 2 * volcano # Exaggerate the relief

x <- 10 * (1:nrow(y)) # 10 meter spacing (S to N)
z <- 10 * (1:ncol(y)) # 10 meter spacing (E to W)

ylim <- range(y)
ylen <- ylim[2] - ylim[1] + 1

colorlut <- terrain.colors(ylen) # height color lookup table

col <- colorlut[ y-ylim[1]+1 ] # assign colors to heights for each point

rgl.surface(x, z, y, 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")
}

setMouseCallbacks <- function()
{
clickBegin <- list()

rgl.setMouseCallbacks(1,
begin = function(x, y)
{
cat("b1", x, y, "\n")
clickBegin$x1 <<- x
clickBegin$y1 <<- y
clickBegin$userMatrix <<- par3d()$userMatrix
},
update = function(x, y)
{
cat("u1", x - clickBegin$x1, y - clickBegin$y1, "\n")
userView = rotate3d(clickBegin$userMatrix, angle = (x - clickBegin$x1) / 100, x = 0, y = 1, z = 0)
userView = rotate3d(userView, angle = (y - clickBegin$y1) / 100, x = 1, y = 0, z = 0)
par3d(userMatrix = userView)
},
end = function()
{
cat("e1\n")
}
)
rgl.setMouseCallbacks(2,
begin = function(x, y)
{
cat("b2", x, y, "\n")
clickBegin$x2 <<- x
clickBegin$y2 <<- y
clickBegin$userMatrix <<- par3d()$userMatrix

print(par3d()$userMatrix)
print(par3d()$modelMatrix)
print(par3d()$projMatrix)
},
update = function(x, y)
{
cat("u2", x, y, "\n")
userView = translate3d(clickBegin$userMatrix, x = (x - clickBegin$x1) / 100, 0, y = (y - clickBegin$y1) / 100)
par3d(userMatrix = userView) #, type="userviewpoint")

print(par3d()$userMatrix)
print(par3d()$modelMatrix)
print(par3d()$projMatrix)
},
end = function()
{
cat("e2\n")
}
)
}

rglInit()
addTestScene()
setMouseCallbacks()


RE: Prevent re-calculation of modelMatrix and modify culling near/far planes in rgl [ Reply ]
By: S Nielsen on 2017-06-30 06:28
[forum:45212]
Thanks for the answer (and sorry for re-posting on stack overflow, I noticed that it is not so active around here)

Reading over the chain of transformations again, it should actually be possible to add simple user translation and rotation without distorting the projection as I experienced. But what about the perspective? Rgl seems to compensate for a low fov by translating the viewpoint far away from the scene?

When I read that rgl translates the scene to origin and does all the other things, I quickly thought I would not be able to control it fully. I will give it another go, thanks again.

RE: Prevent re-calculation of modelMatrix and modify culling near/far planes in rgl [ Reply ]
By: Duncan Murdoch on 2017-06-29 16:28
[forum:45209]
If you change the userMatrix, the only way that will be displayed is by being multiplied into the modelMatrix. See ?par3d section "Rendering" for a description of the calculations that are done.

The default clipping planes are forced by OpenGL. After the model and projection transformations are done, anything outside the display cube is culled. If you want to affect the clipping depth in user coordinates, you need to play with the projection matrix. You can't do that directly, but it is affected by the FOV parameter to par3d. (In raw OpenGL, you have more control, but I've never heard of a need for that, so it's not in rgl.)

Prevent re-calculation of modelMatrix and modify culling near/far planes in rgl [ Reply ]
By: S Nielsen on 2017-06-29 10:39
[forum:45208]
Hello,

I am trying to use par3d() to set a custom userMatrix in rgl, but due to the re-calculations of the read only modelMatrix, unwanted side effects happen to the resulting view.
Additionally the near and far culling/clipping planes (that I cannot seem to modify either) cut the objects when moved closer to the viewport.

My goal is to navigate a point cloud and regression planes/surfaces more freely than otherwise possible with spin and zoom centered on the scene (I have seen the panning example).

Re-drawing the scene all over is not really an option, but applying a custom transformation to some of the scene objects could be another approach, but more like a work-around.

Thanks in advance for your feedback, and thanks for the good work,
S

Thanks to:
Vienna University of Economics and Business Powered By FusionForge