[Closed] Ray grid between 2 points and a direction
I would like to create a grid of rays given 2 points (P1, P2) and a direction D1.
Imagine this grid as a plane, P1 will be the lower-left corner and P2 the upper right, the plane will have the direction D1 as normal.
In the script you see there are 2 problems :
The 2 points red and black (that should represent the bbox of the projection of the teapot on the light plane) are not planar at all.
The grid it’s not build correctly it’s shifted and anyway not between the red and black point.
Here’s the code so far (sorry it’s not cleaned) but should make clear what’s going on :
function ProjectPointOnPlane thePoint thePlanePos thePlaneDir eps:1e-4 =
(
thePointVector = thePoint - thePlanePos
cross1 = cross thePointVector thePlaneDir
cross2 = cross thePlaneDir cross1
return (thePlanePos + cross2)
)
fn GetScanBounds lSource caster =
(
delete $tape*
delete $point*
dir = -lSource.transform.row3
pos = lSource.pos
r1 = [caster.min.x, caster.min.y, caster.min.z]
r2 = [caster.max.x, caster.min.y, caster.min.z]
r3 = [caster.min.x, caster.max.y, caster.min.z]
r4 = [caster.min.x, caster.min.y, caster.max.z]
r5 = [caster.max.x, caster.max.y, caster.min.z]
r6 = [caster.min.x, caster.max.y, caster.max.z]
r7 = [caster.max.x, caster.min.y, caster.max.z]
r8 = [caster.max.x, caster.max.y, caster.max.z]
lst = #(r1, r2, r3, r4, r5, r6, r7, r8)
x = #()
y = #()
z = #()
for currPoint in lst do
(
p = (ProjectPointOnPlane currPoint pos dir)
append x p.x
append y p.y
append z p.z
tape pos:p target:(targetObject pos:currPoint) wirecolor:red
)
currMin = [amin x, amin y, amin z]
currMax = [amax x, amax y, amax z]
point pos:currMin wirecolor:red
point pos:currMax wirecolor:black
return #(currMin, currMax)
)
fn CreateTracePoints lSource minBox maxBox stepx stepy stepz=
(
delete $dummy*
trans = lSource.transform
newTrans = rotatezmatrix (trans.rotationpart as eulerangles).z * trans
lightPos = trans.row4
pointList = #()
x1 = minBox.x
x2 = maxBox.x
distx = x2 - x1
deltax = distx/ stepx
y1 = minBox.y
y2 = maxBox.y
disty = y2 - y1
z1 = minBox.z
z2 = maxBox.z
distz = z2 - z1
deltaz = distz/ stepz
for x = 0 to distx by deltax do
(
for z = 0 to distz by deltaz do
(
p = [x , y1, z ]
pos = ProjectPointOnPlane p maxBox -newTrans.row3
pos = [x, pos.y, pos.z]
dummy pos:pos boxSize:[1,1,1]
append pointList pos
)
)
return pointList
)
fn CreateTestStuff =
(
theLight = DirectionalLight()
theLight.rotation = (quat 0.56506 0.101065 0.144166 0.806045)
theLight.position = [23,-63,24]
theObject = teapot()
bounds = GetScanBounds theLight theObject
pList = CreateTracePoints theLight bounds[1] bounds[2] 10 10 10
)
Thank you in advance,
Dome
What about:
(
fn getPointRayProjection p r =
r.pos + r.dir * dot r.dir (p - r.pos)
fn getPointPlaneProjection p pNorm =
p + dot (pNorm.pos - p) pNorm.dir * pNorm.dir
fn getProjectedBounds boundBox pNorm =
#(getPointPlaneProjection (boundBox[1] * pNorm.transform) pNorm,
getPointPlaneProjection (boundBox[2] * pNorm.transform) pNorm)
mapped fn createBoundingPts bounds = Point pos:bounds
fn createTracePoints tm startPos endPos xStepCount:10 yStepCount:10 =
(
local points = #()
local pos = startPos
local xEndPos = getPointRayProjection endPos (ray startPos tm.row1)
local yEndPos = getPointRayProjection endPos (ray startPos tm.row2)
local xStep = (xEndPos - startPos) / xStepCount
local yStep = (yEndPos - startPos) / yStepCount
for x = 0 to xStepCount do
(
for y = 0 to yStepCount do
(
Dummy pos:pos boxSize:[1,1,1]
append points pos
pos += yStep
)
pos += xStep - (yStepCount + 1) * yStep
)
points
)
local theLight = DirectionalLight rotation:(quat 0.56506 0.101065 0.144166 0.806045) pos:[23,-63,24]
local theObject = Teapot()
local projBoundingBox = (nodeGetBoundingBox theObject theLight.transform)
local bounds = getProjectedBounds projBoundingBox theLight
createBoundingPts bounds
local pList = createTracePoints theLight.transform bounds[1] bounds[2]
)
Wow , that looks a pretty interesting solution, thank you very much.
There is still a little if i rotate the light in fact a side of the plane should be parallel to the ground plane.
Kinda like the attached image.
Yeah, I was wondering, you didn’t specify it before. Here you go:
(
fn getPointRayProjection p r =
r.pos + r.dir * dot r.dir (p - r.pos)
fn getPointPlaneProjection p pNorm =
p + dot (pNorm.pos - p) pNorm.dir * pNorm.dir
fn getProjectedBounds boundBox tm pNorm =
#(getPointPlaneProjection (boundBox[1] * tm) pNorm,
getPointPlaneProjection (boundBox[2] * tm) pNorm)
mapped fn createBoundingPts bounds = Point pos:bounds
fn createTracePoints tm startPos endPos xStepCount:10 yStepCount:10 =
(
local points = #()
local pos = startPos
local xEndPos = getPointRayProjection endPos (ray startPos tm.row1)
local yEndPos = getPointRayProjection endPos (ray startPos tm.row2)
local xStep = (xEndPos - startPos) / xStepCount
local yStep = (yEndPos - startPos) / yStepCount
for x = 0 to xStepCount do
(
for y = 0 to yStepCount do
(
Dummy pos:pos boxSize:[1,1,1]
append points pos
pos += yStep
)
pos += xStep - (yStepCount + 1) * yStep
)
points
)
local theLight = DirectionalLight rotation:(quat 0.567879 -0.0837854 0.392897 0.718418) pos:[23,-63,24]
local theObject = Teapot()
local parallelTM = matrixFromNormal theLight.dir
local projBoundingBox = (nodeGetBoundingBox theObject parallelTM)
local bounds = getProjectedBounds projBoundingBox parallelTM theLight
createBoundingPts bounds
local pList = createTracePoints parallelTM bounds[1] bounds[2]
)
Ok added the rotation to your code, still having an incorrect bounding box with rotated light :
(
fn getPointRayProjection p r =
r.pos + r.dir * dot r.dir (p - r.pos)
fn getPointPlaneProjection p pNorm =
p + dot (pNorm.pos - p) pNorm.dir * pNorm.dir
fn getProjectedBounds boundBox pNorm =
#(getPointPlaneProjection (boundBox[1] * pNorm.transform) pNorm,
getPointPlaneProjection (boundBox[2] * pNorm.transform) pNorm)
mapped fn createBoundingPts bounds = Point pos:bounds
fn createTracePoints tm startPos endPos xStepCount:10 yStepCount:10 =
(
local points = #()
-- ROTATION
tm = rotatezmatrix (tm.rotationPart as eulerangles).y * tm
local pos = startPos
local xEndPos = getPointRayProjection endPos (ray startPos tm.row1)
local yEndPos = getPointRayProjection endPos (ray startPos tm.row2)
local xStep = (xEndPos - startPos) / xStepCount
local yStep = (yEndPos - startPos) / yStepCount
for x = 0 to xStepCount do
(
for y = 0 to yStepCount do
(
Dummy pos:pos boxSize:[1,1,1]
append points pos
pos += yStep
)
pos += xStep - (yStepCount + 1) * yStep
)
points
)
local theLight = DirectionalLight rotation:(quat 0.56506 0.101065 0.144166 0.806045) pos:[23,-63,24]
local theObject = Teapot()
local projBoundingBox = (nodeGetBoundingBox theObject theLight.transform)
local bounds = getProjectedBounds projBoundingBox theLight
createBoundingPts bounds
local pList = createTracePoints theLight.transform bounds[1] bounds[2]
)
Cool, I did not see your reply cause I was adding mine now it’s much better, thank you!
But try to move the light around, you will see that the 2 points sometime get narrow and the plane gets tilted for example here :
$Fdirect001.transform = (matrix3 [-0.911373,0.411582,0] [-0.13932,-0.308498,0.940967] [0.387285,0.857572,0.338498] [40.57,89.835,35.4594])