Stephane Chantepie
2012-Aug-27 17:47 UTC
[R] RGL plot : lighting problem when triangle3d and persp3d are used in the same plot
Dear all, I have tried to plot a triangular matrix with the function persp3d(rgl). for example z=rbind(c(1,NA,NA,NA),c(5,3,NA,NA),c(4,2,9,NA),c(8,6,5,11)) x=1:4 y=1:4 persp3d(x,y,z,color="gray") The two extreme points are not plotted (value=1 and value=10). It seems because the half of the matrix have 'NA' and perp3d need planar quadrilateral face. So I decided to use the function triangle3d to integrate these points into the scene. So, for the first point I did : triangles3d(x=c(1,2,2),y=c(1,1,2),z=c(1,5,3)) and it worked But a problem remains because the light movment on this triangle looks independant and I did not find how to solve this issue. How can I prefectly integrate this triangle into the scene? Thank for help [[alternative HTML version deleted]]
Duncan Murdoch
2012-Aug-27 20:41 UTC
[R] RGL plot : lighting problem when triangle3d and persp3d are used in the same plot
On 27/08/2012 1:47 PM, Stephane Chantepie wrote:> Dear all, > > I have tried to plot a triangular matrix with the function persp3d(rgl). > > for example > > z=rbind(c(1,NA,NA,NA),c(5,3,NA,NA),c(4,2,9,NA),c(8,6,5,11)) > x=1:4 > y=1:4 > persp3d(x,y,z,color="gray") > > The two extreme points are not plotted (value=1 and value=10). It seems > because the half of the matrix have 'NA' and perp3d need planar > quadrilateral face. So I decided to use the function triangle3d to > integrate these points into the scene. > > So, for the first point I did : > > triangles3d(x=c(1,2,2),y=c(1,1,2),z=c(1,5,3)) and it worked > > But a problem remains because the light movment on this triangle looks > independant and I did not find how to solve this issue. > > How can I prefectly integrate this triangle into the scene?You need to set the normals at the vertices that are shared with the persp3d vertices. rgl internally averages the normals to the pieces making up each facet; you don't have enough access to the internals to do that. (You'd want to change the normal on the surface, as well, because your triangles should participate in the averaging.) But you could set the normals to the new triangle to match the normal to the one it joins to, and get something that looks sort of okay. It's not going to be a simple calculation: you need to figure out the coordinates of the edges joining at those vertices, take a cross product, and use that. See ?rgl.primitive for how to send the normals to points3d; I think the normals need to be length 1, but that may be forced internally. If you were really ambitious, you could take a look at the C++ code that draws the surface, and contribute code to smooth the edge properly; I think it would be an improvement over the current behaviour, but it is tedious to write. Duncan Murdoch