#概要
sketchupでrubyやってみた。
make_fur使ってみた。
#写真
#サンプルコード
def glowup(preview = false)
@finstance = "yes"
@funits = "funits"
@camera = Sketchup.active_model.active_view.camera
@fdensity = 10.0
@flength = 10.0
@frootw = 10.0
@fvradius = 10.0
@maxnum = 10
@fforce = Geom::Vector3d.new(0.0, 0.0, 0.05)
@fdirection = Geom::Vector3d.new(0.0, 0.0, 0.05)
@ftype = "ftype"
@fj = 1.0 / 100
@flj = @fj / 100 * @flength
@fljitter = Geom::Vector3d.new(@fj * @flength, @fj * @flength, @fj * @flength)
@fwjitter = 1.0 * @frootw / 100
@fstrong = 1.0
@fsjitter = 1.0 * @fstrong / 100
@fdivs = 0
@fur_deflist = []
model = Sketchup.active_model
ss = model.selection
ents = model.entities
if ss.empty?
UI.messagebox("No selection.")
return nil
end
return if ss.find{ |selface|
selface.kind_of? Sketchup::Face
} == nil
starttime = Time.now.to_f
@camera = Sketchup.active_model.active_view.camera
@fdivs = @fdivs + 1 if @fvradius != 0
cnt = 0
sfaces = ss.find_all{ |selface|
selface.is_a?(Sketchup::Face)
}
spgs = sfaces.map{ |pg|
[pg.mesh(5), pg.material, pg.normal]
}
ocnt = 0
pmesh = Geom::PolygonMesh.new
pmeshes = []
pcmax = 600
pcnext = pcmax
pmat = Sketchup.active_model.materials.current
fur_inss_list = []
fur_inss = []
fur_def = Sketchup.active_model.definitions["fur_instance"]
if @finstance == "yes" or (fur_def == nil and @finstance == "fur_instance")
fur_def = model.definitions.add(model.definitions.unique_name(("fur_instance")))
make_fur(pmesh, pointXYZ(0, 0, 0), pointXYZ(0, 0, 0), pointXYZ(0, 0, 1), nil, pointXYZ(1, 0, 0), @fdivs, true)
if @ftype == "Box"
fur_def.entities.fill_from_mesh(pmesh, false, 0)
else
fur_def.entities.fill_from_mesh(pmesh, false, 12)
end
fur_def.insertion_point = pointXYZ(0, 0, 0)
fi_pcount = pmesh.count_polygons.to_i + 1.to_i
elsif @finstance == ("fur_crowd")
fi_pcount = 1
elsif @finstance != "no"
fur_def = Sketchup.active_model.definitions[@finstance]
@finstance = ("no") if fur_def == nil
fi_pcount = 1
end
pmesh = Geom::PolygonMesh.new if preview == false
prmax = 10000
@prepts = []
spgs.each{ |mesh, mat, nvec|
if mesh != nil
mesh.polygons.each{ |poly|
pt1 = mesh.point_at poly[0]
pt2 = mesh.point_at poly[1]
pt3 = mesh.point_at poly[2]
uv1 = mesh.uv_at(poly[0], 1)
uv2 = mesh.uv_at(poly[1], 1)
uv3 = mesh.uv_at(poly[2], 1)
nor1 = mesh.normal_at poly[0]
nor2 = mesh.normal_at poly[1]
nor3 = mesh.normal_at poly[2]
len12 = pt1.distance pt2
len13 = pt1.distance pt3
vec12 = pt1.vector_to pt2
vec13 = pt1.vector_to pt3
ang23 = vec12.angle_between vec13
area123 = len12.to_m * len13.to_m * Math.sin(ang23) * 0.5
cnt = area123.to_f * @fdensity.to_f
if cnt.to_f < 1.to_f
if cnt.to_f > rand.to_f
cnt = 1
else
cnt = 0
end
end
cnt = cnt.to_i
cnt = @maxnum if cnt > @maxnum
(1..cnt).each{ |i|
ra = rand
rb = 1.to_f - Math.sqrt(rand)
pt4 = Geom::Point3d.new
pt4 = point_add(vector_scale(pt2, ra.to_f), vector_scale(pt3, (1.to_f - ra.to_f)))
pt5 = Geom::Point3d.new
pt5 = point_add(vector_scale(pt1, rb.to_f), vector_scale(pt4, (1.to_f - rb.to_f)))
uv4 = Geom::Point3d.new
uv4.x = uv2.x * ra + uv3.x * (1 - ra)
uv4.y = uv2.y * ra + uv3.y * (1 - ra)
uv5 = Geom::Point3d.new
uv5.x = uv1.x * rb + uv4.x * (1 - rb)
uv5.y = uv1.y * rb + uv4.y * (1 - rb)
nor4 = Geom::Point3d.new
nor4 = point_add(vector_scale(nor2, ra.to_f), vector_scale(nor3, (1.to_f - ra.to_f)))
nor5 = Geom::Point3d.new
nor5 = point_add(vector_scale(nor1, rb.to_f), vector_scale(nor4, (1.to_f - rb.to_f)))
divs = @fdivs
if @finstance != ("no") and @finstance != "no"
if preview == false
fur_inss.push [pt5, nor5, mat]
ocnt += fi_pcount
pmat = mat
if (ocnt) >= pcnext
ocnt += fi_pcount
fur_inss_list.push fur_inss
fur_inss = []
while pcnext < (ocnt + pcmax / 2)
pcnext += pcmax
end
Sketchup.set_status_text "Calc #{ocnt} Polygons"
end
else
make_preview(@prepts, pt5, nor5, divs)
break if @prepts.size > prmax
end
else
if @fvradius == 0
if preview == false
make_fur pmesh, pt5, uv5, nor5, mat, pt1, divs
else
make_preview(@prepts, pt5, nor5, divs)
break if @prepts.size > prmax
end
else
cv1 = @camera.eye.vector_to @camera.target
cv2 = @camera.eye.vector_to pt5
if cv2.angle_between(cv1).to_f <= @camera.fov.degrees.to_f
pdist = @fvradius.to_f - pt5.distance(@camera.eye)
pdist = 0 if pdist < 0
divs = (@fdivs * Math.sqrt(pdist / @fvradius)).to_i
if divs != 0
if preview == false
make_fur(pmesh, pt5, uv5, nor5, mat, pt1, divs)
else
make_preview(@prepts, pt5, nor5, divs)
break if @prepts.size > prmax
end
end
end
end
pmat = mat
if preview == false
if (ocnt + pmesh.count_polygons) >= pcnext
ocnt += pmesh.count_polygons
pmeshes.push [pmesh, mat]
pmesh = Geom::PolygonMesh.new
while pcnext < (ocnt + pcmax / 2)
pcnext += pcmax
end
Sketchup.set_status_text "Calc #{ocnt} Polygons"
end
end
end
break if @prepts.size > prmax
}
break if @prepts.size > prmax
}
end
break if @prepts.size > prmax
}
return if preview == true
if Sketchup.version.to_f >= 7
model.start_operation "fur glow", true
else
model.start_operation "fur glow"
end
oocnt = 0
fgp = model.active_entities.add_group
fgents = fgp.entities
if @finstance != ("no") and @finstance != "no"
if fur_inss.size > 0
ocnt += fi_pcount
fur_inss_list.push fur_inss
Sketchup.set_status_text "Calc #{ocnt} Polygons"
end
fur_inss_list.each{ |fur_inss|
fur_inss.each{ |pt5, npt5, mat|
nor5 = pointXYZ(0, 0, 0).vector_to(npt5)
nor5.length = @flength.to_f
nor6 = vector_add(nor5, vector_scale(@fdirection, 0.5))
flv = vectorXYZ(@fljitter.x * (0.5 - rand), @fljitter.y * (0.5 - rand), @fljitter.z * (0.5 - rand))
nor7 = vector_add(nor6, flv)
nor7.length = nor5.length
nor6.length = nor5.length
if @fdirection.length == 0
scale_deg = 180.degrees
else
scale_deg = (90.degrees - nor5.angle_between(nor6)).abs
end
scale_deg = 180.degrees if scale_deg > 180.degrees
scale_deg = 180.degrees if scale_deg < 0
ra = ((1.0 - rand * 2.0) * scale_deg)
tr = Geom::Transformation.rotation(pointXYZ(0, 0, 0), vectorXYZ(0, 0, 1), ra)
if nor7.samedirection?(vectorXYZ(0, 0, 1))
elsif nor7.samedirection?(vectorXYZ(0, 0, -1))
tr = Geom::Transformation.rotation(pointXYZ(0, 0, 0), vectorXYZ(1, 0, 0), 180.degrees) * tr
else
zax = nor7
yax = nor7.cross(vectorXYZ(0, 0, 1))
xax = yax.cross(nor7)
tr = Geom::Transformation.axes(pointXYZ(0, 0, 0), xax, yax, zax) * tr
end
tsfactor = 1.to_f - @fj * (1.to_f - rand * 2.to_f)
tsfactor = 0.01 if tsfactor == 0
ts = Geom::Transformation.scaling(tsfactor, tsfactor, tsfactor)
tr = ts * tr
tr = Geom::Transformation.translation(pointXYZ(0, 0, 0).vector_to(pt5)) * tr
if @fur_deflist.length > 0
fins = fgents.add_instance @fur_deflist[(@fur_deflist.length * rand).to_i], tr
else
fins = fgents.add_instance fur_def, tr
end
fins.material = mat if mat != nil
Sketchup.set_status_text "Making #{oocnt} polygons / #{ocnt}"
oocnt += fi_pcount
}
}
else
if pmesh.count_polygons > 0
ocnt += pmesh.count_polygons
pmeshes.push [pmesh, pmat]
Sketchup.set_status_text "Calc #{ocnt} Polygons"
end
pmeshes.each{ |pmesh, mat|
if pmesh != nil
tgp = fgents.add_group
tgents = tgp.entities
if @ftype == "Box"
tgents.fill_from_mesh(pmesh, false, 0)
else
tgents.fill_from_mesh(pmesh, false, 12)
end
tgp.material = mat
oocnt += pmesh.count_polygons
Sketchup.set_status_text "Making #{oocnt} polygons / #{ocnt}"
end
}
end
model.commit_operation
wastetime = Time.now.to_f - starttime
Sketchup.set_status_text "#{('waste time is')} #{wastetime} #{('sec')}"
end
以上。