[Closed] Align To Quad part2
In previous thread Denis showed excellent example how to scatter flags over uneven terrain.
But why same approch not works on simple cube which is orient in non-axis direction?
This cube have already selected center faces on each side where flags need to be placed.
fn scatterNodes ground brush = if iskindof ground Editable_Mesh and isvalidnode brush do
(
faces = ground.selectedfaces as bitarray
done = #{}
for f in faces where not done[f] collect
(
polys = meshop.getpolysusingface ground f
ground.selectedverts = meshop.getvertsusingface ground polys
done += polys
center = (averageSelVertCenter ground)*ground.objecttransform
normal = averageSelVertNormal ground
copy brush pos:center dir:normal wirecolor:green
)
)
(
delete objects
brush =
(
top = box widthsegs:1 lengthsegs:1 heightsegs:1 width:6 length:0.1 height:4 pos:[3,0,7.5]
top.mat = standard diffuse:red
bot = Cylinder name:"flag" smooth:on heightsegs:1 capsegs:1 sides:24 height:12 radius:0.2 pos:[0,0,0] wirecolor:red
bot.mat = standard diffuse:yellow
attach (bot = converttomesh bot) top
bot
)
ground = Box length:50 width:50 height:50 lengthsegs:3 widthsegs:3 heightsegs:3 wirecolor:green \
pos:[-50,-50,0] dir:[0.665714,0.202268,0.718271] material:(standard diffuse:blue)
converttomesh ground ; ground.selectedfaces = #{9..10, 27..28, 45..46, 63..64, 81..82, 99..100}
/*ground = mesh name:"ground" length:100 width:100 lengthsegs:10 widthsegs:10 wirecolor:yellow pos:[-50,-50,0]
addmodifier ground (Noisemodifier fractal:on strength:[25,25,25] seed:(random 0 1000000)) -- add a little fun*/
scatterNodes ground brush
)
Same thing here
fn scatterNodes ground brush = if iskindof ground Editable_Mesh and isvalidnode brush do
(
faces = ground.selectedfaces as bitarray
done = #{}
for f in faces where not done[f] collect
(
polys = meshop.getpolysusingface ground f
ground.selectedverts = meshop.getvertsusingface ground polys
done += polys
center = (averageSelVertCenter ground)*ground.objecttransform
normal = averageSelVertNormal ground
tm =
(
face = (polys as array)[1]
vv = getface ground face
front = normalize ((getVert ground vv[2]) - (getVert ground vv[1]))
side = normalize (cross front normal)
_front = normalize (cross normal side)
matrix3 _front side normal center
)
b = copy brush wirecolor:green
b.transform = tm
b
)
)
(
delete objects
brush =
(
top = box widthsegs:1 lengthsegs:1 heightsegs:1 width:6 length:0.1 height:4 pos:[3,0,7.5]
top.mat = standard diffuse:red
bot = Cylinder name:"flag" smooth:on heightsegs:1 capsegs:1 sides:24 height:12 radius:0.2 pos:[0,0,0] wirecolor:red
bot.mat = standard diffuse:yellow
attach (bot = converttomesh bot) top
bot
)
ground = Box length:50 width:50 height:50 lengthsegs:3 widthsegs:3 heightsegs:3 wirecolor:green \
pos:[-50,-50,0] dir:[0.665714,0.202268,0.718271] material:(standard diffuse:blue)
converttomesh ground ; ground.selectedfaces = #{9..10, 27..28, 45..46, 63..64, 81..82, 99..100}
/*ground = mesh name:"ground" length:100 width:100 lengthsegs:10 widthsegs:10 wirecolor:yellow pos:[-50,-50,0]
addmodifier ground (Noisemodifier fractal:on strength:[25,25,25] seed:(random 0 1000000)) -- add a little fun*/
scatterNodes ground brush
)
ok … lets modify the scatterNodes function
fn scatterNodes ground brush = if iskindof ground Editable_Mesh and isvalidnode brush do
(
faces = ground.selectedfaces as bitarray
done = #{}
fn averageFaceNormal mesh faces =
(
normal = [0,0,0]
for f in faces do normal += getfacenormal mesh f
normalize (normal/faces.numberset)
)
for f in faces where not done[f] collect
(
polys = meshop.getpolysusingface ground f
ground.selectedverts = meshop.getvertsusingface ground polys
done += polys
center = (averageSelVertCenter ground)*ground.objecttransform
normal = averageFaceNormal ground polys
--averageSelVertNormal ground
copy brush pos:center dir:normal wirecolor:green
)
)
Ok. Now is direction and position of the flags corrected. Why this flag and on the other side is slightly rotated.
Also how to make this to works on TriMesh. Only problem here is averageSelVertCenter fn.
If we throw out this fn then we can use maybe something like this
fn averageFacePosNormal mesh faces =
(
local normal = [0,0,0], center = [0,0,0]
for f in faces do normal += getfacenormal mesh f
for f in faces do center += getface mesh f
datapair normal:(normalize (normal/2)) center:(center/2)
)
edit:
I tried this but is wrong
(
faces = ground.selectedfaces as bitarray
done = #{}
fn averageFacePosNormal mesh faces =
(
local n = [0,0,0], c = [0,0,0]
for f in faces do n += getfacenormal mesh f
for f in faces do c += getface mesh f
dataPair normal:(normalize (n/2)) center:((c/2)*mesh.objecttransform)
)
for f in faces where not done[f] collect
(
polys = meshop.getpolysusingface ground f
ground.selectedverts = meshop.getvertsusingface ground polys
done += polys
dp = averageFacePosNormal ground polys
copy brush pos:dp.center dir:dp.normal wirecolor:green
)
)
a flag rotated? but how do you specify what it has to be? we can use the ground coordinate system… or whatever… we are calculating a normal to surface, but for the side (of front) vector we need some extra axis
You mean like this
fn scatterNodes ground brush = if canConvertTo ground Editable_Mesh and isvalidnode brush do
(
ground = snapshotAsMesh ground
local faces = ground.selectedfaces as bitarray , done = #{}
fn averageFacePosNormal mesh faces =
(
local n = [0,0,0], c = [0,0,0], faceCenter = meshop.getFaceCenter
for f in faces do n += getfacenormal mesh f
for f in faces do c += faceCenter mesh f
dataPair normal:(normalize (n/2)) center:(c/2)
)
for f in faces where not done[f] collect
(
polys = meshop.getpolysusingface ground f ; done += polys
dp = averageFacePosNormal ground polys
face = (polys as array)[1]
vv = getface ground face
right = normalize ((getVert ground vv[2]) - (getVert ground vv[1]))
side = normalize (cross right dp.normal)
front = normalize (cross dp.normal side)
tm = matrix3 front side dp.normal dp.center
copy brush transform:tm wirecolor:green
) ; delete ground
)
(
delete objects
brush =
(
top = box widthsegs:1 lengthsegs:1 heightsegs:1 width:6 length:0.1 height:4 pos:[3,0,7.5]
top.mat = standard diffuse:red
bot = Cylinder name:"flag" smooth:on heightsegs:1 capsegs:1 sides:24 height:12 radius:0.2 pos:[0,0,0] wirecolor:red
bot.mat = standard diffuse:yellow
attach (bot = converttomesh bot) top
bot
)
ground = Box length:50 width:50 height:50 lengthsegs:3 widthsegs:3 heightsegs:3 wirecolor:green \
pos:[-50,-50,0] dir:[0.665714,0.202268,0.718271] material:(standard diffuse:blue)
converttopoly ground ; ground.EditablePoly.SetSelection #Face #{5, 14, 23, 32, 41, 50}
scatterNodes ground brush
)