# Books and more books

#1

Hey guys another fun and collaborative tool here. I figured why not!
I’ve recently come across some cool book shelve filling tools, but sadly there were all seemingly missing basic features/controls that I’d expect to see. Aside from that, some cost way to much \$\$\$ which we all know, not many of us have lying around waiting to get spent on a little mxs.

Any who lets get to it.
I’ve gone ahead and began to hard code a basic book layout tool.
The script creates a plane as a shelf, then distributes the books according to the settings.

For now I’m just hard-coding everything like I have in the past and then I’ll develop a UI once this gets far enough along. I’d love to take in everyones contributions and ideas to make this tool like many past ones, a solid tool that users can find useful.

Things Completed

• Books distribute randomly from the back of the shelf to the front base on desired settings
• Struct implementation to store the node and its dimensions.

Things To Do!

• Add a random rotation with a range control for Y
• Along with the random Y rotation, adjust books to fit snug against one another
• Allow for random number of books to be placed lying flat on the shelf, face down
• Add ‘N’ number of books until the shelf is full

The next thing to tackle is figuring out how to aligns books against one another whom have a varying Y rotation on them.

``````
delete objects
clearlistener()

shelf = plane length:20 width:60 pos:[0,0,10] wirecolor:[150,215,230]

struct bookData (node, thick, depth, height)
curBooks = #()

disableSceneRedraw()
for i = 1 to 20 do
(
mybook = box width:(random 0.5 3.0) height:(random 8.0 20.0) length:(random 8.0 15.0) pos:[(-3*i),0,0] wirecolor:[150,230,90]

bb = nodeLocalBoundingBox mybook
thick = abs (bb[1].x - bb[2].x)
depth = abs (bb[1].y - bb[2].y)
height = abs (bb[1].z - bb[2].z)
append curBooks (bookData node:myBook thick:thick depth:depth height:height)
)
enableSceneRedraw()

/*Start the calculating*/
bb = nodeLocalBoundingBox shelf
shelfWidth = abs (bb[1].x - bb[2].x)
shelfDepth = abs (bb[1].y - bb[2].y)

offset = 0.0

for b = 1 to curBooks.count do
(
book = curBooks[b]
shelfCorner = [bb[1].x,bb[2].y,shelf.pos.z] --back left corner of shelf

book.node.pos = shelfCorner + [(book.thick/2.0),-(book.depth/2.0),0] --place book in furthest back corner of shelf

--now adjust books position so there is no collision with previously placed books
book.node.pos.x += offset

--now adjust the books position depth wise based on the backFront
backFront =( random 0.0 1.0) -- 0.0:back 1.0:front
book.node.pos.y -= (backFront*(shelfDepth-book.depth))

offset += book.thick --continue to count offset from previous books
)

``````

#2

no, no, no… not again… why does this idea so excite young developers?

#3

Haha, it’s something I’ve personally never done.
I’d be more than glad to work on something that someone would find useful, that wouldn’t be a book script.

I’m open to any suggestions for new tools that would be unique and different from anything previously created.

#4

i can sell you an idea…
all stars in the space are most known by position. our forefathers defined constellations. but… today we can ‘pseudo randomly’ generate the new ones. and name them! is it not cool? pointless? probably. but much better than do ‘how to put books to shelves making them look that you’ve read them’

#5

So in short a galaxy of stars creator? with constellations?

#6

yes! be God!

#7

Here is something I’ve been wanting to do for awhile. It would allow for quickly throwing down hills for proxy placement in environments.

A mesh object that has a spinner for radius and then another spinner which would control the height.

As the height increases the loops between the center point and the outer ring would move in the fashion of an arch.
You’ll see in the background a read object which is incorrect. That method’s verts are moving linearly which is not what I’d want. You can look at the oilTank it’s similiar to what I’m talking about.

Update

You could have 3 spinners
2 for center height
3 for controller the interpolation from the outer ring to the center point.

So users could make it linear or arch/curved.

#8

Here we go Denis.
I’ve got some basic stuff setup here for this so far.

How do I then implement an arch in the loops as they reach the top end point?

``````
----Created by John Martini & Grant Miller

plugin simpleObject Mound
name:"Mound"
category:"Joker_Martini"

-- -- -- -- --The Mound Mesh Creator Script-- -- -- -- --
(
parameters paramBlock rollout:paramRollout
(
segments type:#integer animatable:true ui:uiSegments default:8
subdivs type:#integer animatable:true	ui:uiSubDivs default:0
height type:#worldunits animatable:true ui:uiHeight default:0

(
)

(
)
)
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
rollout paramRollout "Parameters"
(
spinner	uiSegments "Segments:"	range:[3, 200, 0] type:#integer
spinner	uiSubDivs	"Loops:" range:[0, 200, 0] type:#integer
spinner uiHeight "Height:" range:[0, 100, 0] type:#worldunits
)
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

-- function for creating faces
-- OPTIONS: mesh, face index, vertices as point3, material id
fn createface msh fcndx vrts edgvis faceid =
(
local edg
setface msh fcndx [vrts.x, vrts.y, vrts.z]
if edgvis.x == 1 then edg = true else edg = false
setedgevis msh fcndx 1 edg
if edgvis.y == 1 then edg = true else edg = false
setedgevis msh fcndx 2 edg
if edgvis.z == 1 then edg = true else edg = false
setedgevis msh fcndx 3 edg
setfacesmoothgroup msh fcndx 0
setfacematid msh fcndx faceid

)
fn FlipObjNormal obj =
(
for f =1 to obj.numFaces do --for each face in the mesh
(
verts=getface obj f -- get its 3 vertices as a point3
local tmp=verts.x -- swap the first and third vertices
verts.x=verts.z -- which flips the normal
verts.z=tmp -- (right-hand rule), and
setface obj f verts -- store the new vertex order for the face
)
update obj -- update object so 3ds Max sees the changes
)
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
on buildmesh do
(
local varVertices = segments * (subdivs + 2)
local varFaces = (segments * (subdivs + 1)) * 2
local varVertCount = 1, varFaceCount = 1
tmesh = trimesh()
setmesh tmesh numverts:varVertices numfaces:varFaces
------- [draw vertices]

------ arch implementation
arch = 0
for crcl = 1 to radstep do
(
for theta = 0 to 359 by (360.0 / segments) do
(
setvert tmesh varVertCount [vertX, vertY, (arch)]; varVertCount += 1
)
)

------- [draw faces]
local curVert = 1, curFace, segCheck = 1
for curFace = 1 to varFaces by 2 do
(
if segCheck == segments then
(
segCheck = 0
conVert = curVert - (segments - 1)
createface tmesh curFace [curVert, curVert + segments, conVert + segments] [1, 1, 0] 1
createface tmesh (curFace + 1) [conVert + segments, conVert, curVert] [1, 1, 0] 1
)
else
(
createface tmesh curFace [curVert, curVert + segments, curVert + segments + 1] [1, 1, 0] 1
createface tmesh (curFace + 1) [curVert + segments + 1, curVert + 1, curVert] [1, 1, 0] 1
)

curVert += 1; segCheck += 1
)

------- [set mesh]
setmesh mesh tmesh

------- [weld center if inner radius = 0]
(
local i
local weldVerts = for i = 1 to segments collect i
meshop.weldvertset mesh weldVerts
)
------- Flips normals
(
FlipObjNormal mesh
flipped = true
)
------- Flips normals End Utility

)

-------------------------------------------------------------------------------
tool create
(
on mousepoint click do
(
case click of
(
1: nodeTM.translation = gridpoint
3: #stop
)
)

on mousemove click do
(
case click of
(
2:
(
)
3:
(
)
)
)
)
)
delete objects
completeredraw()

``````

#9

cool, call it boob factory

#10

here is my version:

``````
/* denisT collection 2013 */

plugin simpleObject ConePlus name:"ConePlus"
classID:#(0x00001967, 0x1023099b)
category:"Standard Plus"
version:1
(
local coneobject
parameters plus rollout:plus
(
height type:#worldUnits default:0 ui:ui_height
bias type:#float default:0 ui:ui_bias
biasPower type:#float default:10 animatable:off ui:ui_biasPower
heightsegs type:#integer default:1 ui:ui_heightsegs
capsegs type:#integer default:1 ui:ui_capsegs
sides type:#integer default:16 ui:ui_sides
smooth type:#boolean default:on ui:ui_smooth
mapCoords type:#boolean default:on ui:ui_mapCoords
realWorldMapSize type:#boolean default:off ui:ui_realWorldMapSize
)
rollout plus "Parameters"
(
spinner ui_height "Height: " type:#worldUnits  range:[0,1e9,0] fieldwidth:52 align:#rigth offset:[8,2]
spinner ui_bias "Height Bias: " type:#float  range:[-1,1,0] scale:0.01 fieldwidth:52 align:#rigth offset:[8,-2]
spinner ui_biasPower "Bias Power: " range:[1,100,0] type:#float scale:0.1 fieldwidth:52 align:#right offset:[8,-2] tooltip:"Bias Power"
spinner ui_heightsegs "Height Segments: " type:#integer range:[1,256,0] fieldwidth:52 align:#rigth offset:[8,4]
spinner ui_capsegs "Cap Segments: " type:#integer range:[1,256,0] fieldwidth:52 align:#rigth offset:[8,0]
spinner ui_sides "Sides: " type:#integer range:[3,256,0] fieldwidth:52 align:#rigth offset:[8,0]
checkbox ui_smooth "Smooth" align:#left offset:[83,4]
checkbox ui_mapCoords "Generate Mapping Coords." align:#left offset:[-8,4]
checkbox ui_realWorldMapSize "Real-World map Size" align:#left offset:[-8,0]
)
on buildmesh do
(
fn fastValue f bias:0.0 power:1 =
(
if bias < 0 then 1 - (pow (1 - f) (1 - power*bias)) else (pow f (1 + power*bias))
)

if coneobject == undefined do coneobject = createinstance cone
coneobject.height = height
coneobject.heightsegs = heightsegs
coneobject.capsegs = capsegs
coneobject.sides = sides
coneobject.smooth = smooth
coneobject.mapCoords = mapCoords
coneobject.realWorldMapSize = realWorldMapSize
mesh = coneobject.mesh

for k=1.0 to heightsegs-1 do
(
s = (k*sides+2) + (capsegs-1)*sides
e = ((k+1)*sides+1) + (capsegs-1)*sides
verts = #{s..e}
z = height*(fastValue (k/heightsegs) bias:bias power:biasPower)
for v in verts do
(
p = getvert mesh v
setvert mesh v [p.x,p.y,z]
)
)
update mesh
)
tool create
(
on mousePoint click do case click of
(
1: nodeTM.translation = gridPoint
4: #stop
)
on mouseMove click do case click of
(
2: radius1 = amax (abs gridDist.x) (abs gridDist.y)
3: height = gridDist.z
4: radius2 = amax (abs gridDist.x) (abs gridDist.y)
)
)
)

``````

i can realize Slice as well but lazily to do it

#11

align:#rigth

#12

who cares… rigth is OK. right alignment is default for spinners anyway

#13

slice… ok, ok… here is it:

``````
/* denisT collection 2013 */

plugin simpleObject ConePlus name:"ConePlus"
classID:#(0x00001967, 0x1023099b)
category:"Standard Plus"
version:1
(
local coneobject
parameters params rollout:params
(
height type:#worldUnits default:0 ui:ui_height
bias type:#float default:0 ui:ui_bias
biasPower type:#float default:10 ui:ui_biasPower
heightsegs type:#integer default:1 ui:ui_heightsegs
capsegs type:#integer default:1 ui:ui_capsegs
sides type:#integer default:16 ui:ui_sides
smooth type:#boolean default:on ui:ui_smooth
sliceOn type:#boolean default:off ui:ui_sliceOn
sliceFrom type:#float default:0 ui:ui_sliceFrom
sliceTo type:#float default:0 ui:ui_sliceTo
mapCoords type:#boolean default:on ui:ui_mapCoords
realWorldMapSize type:#boolean default:off ui:ui_realWorldMapSize

on sliceOn get val do try
(
this.params.ui_sliceFrom.enabled = this.params.ui_sliceTo.enabled = val
)
catch (false)
)
rollout params "Parameters"
(
spinner ui_height "Height: " type:#worldUnits range:[0,1e9,0] fieldwidth:52 align:#right offset:[8,2]
spinner ui_bias "Height Bias: " type:#float range:[-1,1,0] scale:0.01 fieldwidth:52 align:#right offset:[8,-2]
spinner ui_biasPower "Bias Power: " range:[1,100,0] type:#float scale:0.1 fieldwidth:52 align:#right offset:[8,-2] tooltip:"Bias Power"
spinner ui_heightsegs "Height Segments: " type:#integer range:[1,256,0] fieldwidth:52 align:#right offset:[8,4]
spinner ui_capsegs "Cap Segments: " type:#integer range:[1,256,0] fieldwidth:52 align:#right offset:[8,0]
spinner ui_sides "Sides: " type:#integer range:[3,256,0] fieldwidth:52 align:#right offset:[8,0]
checkbox ui_smooth "Smooth" align:#left offset:[83,4]
checkbox ui_sliceOn "Slice On" align:#left offset:[83,2]
spinner ui_sliceFrom "Slice From: " type:#float enabled:sliceOn range:[-1e9,1e9,0] scale:0.1 fieldwidth:52 align:#right offset:[8,0]
spinner ui_sliceTo "Slice To: " type:#float enabled:sliceOn range:[-1e9,1e9,0] scale:0.1 fieldwidth:52 align:#right offset:[8,-2]
checkbox ui_mapCoords "Generate Mapping Coords." align:#left offset:[-8,4]
checkbox ui_realWorldMapSize "Real-World map Size" align:#left offset:[-8,0]
)
on buildmesh do
(
fn fastValue f bias:0.0 power:1 =
(
if bias < 0 then 1 - (pow (1 - f) (1 - power*bias)) else (pow f (1 + power*bias))
)

if coneobject == undefined do coneobject = createinstance cone
coneobject.height = height
coneobject.heightsegs = heightsegs
coneobject.capsegs = capsegs
coneobject.sides = sides
coneobject.smooth = smooth
coneobject.sliceOn = sliceOn
coneobject.sliceFrom = sliceFrom
coneobject.sliceTo = sliceTo
coneobject.mapCoords = mapCoords
coneobject.realWorldMapSize = realWorldMapSize
mesh = coneobject.mesh

for k=1.0 to heightsegs-1 do
(
ss = if sliceOn then (sides+2) else sides
s = (k*ss+2) + (capsegs-1)*ss
e = ((k+1)*ss+1) + (capsegs-1)*ss
verts = #{s..e}
z = height*(fastValue (k/heightsegs) bias:bias power:biasPower)
for v in verts do
(
p = getvert mesh v
setvert mesh v [p.x,p.y,z]
)
)
update mesh
)
tool create
(
on mousePoint click do case click of
(
1: nodeTM.translation = gridPoint
4: #stop
)
on mouseMove click do case click of
(
2: radius1 = amax (abs gridDist.x) (abs gridDist.y)
3: height = gridDist.z
4: radius2 = amax (abs gridDist.x) (abs gridDist.y)
)
)
)

``````

#14

That is pretty slick.
I’ll have to play around with it and see what I can learn from it in how you are making an arch.

#15

Adjust the span and the height then run

``````
delete objects
clearlistener()
span = 200.0
height = 30.0
h = 1.0/2.0*(span)
a = -(height) / ((span - h)^2) -- equation to get a

for i = 0.0 to span by 5.0 do
(
x = i --distance out from center
arch = (a*((x - h)^2)) + height

b= box height:2.0 width:2.0 length:2.0 wirecolor:[1*i,120,120] pos:[i/(2),0,arch]

)

``````

#16

``````
/* denisT collection 2013 */

plugin simpleObject ConePlus name:"ConePlus"
classID:#(0x00001967, 0x1023099b)
category:"Standard Plus"
version:1
(
local coneobject
parameters params rollout:params
(

height type:#worldUnits default:0 ui:ui_height
heightBias type:#float default:0 ui:ui_heightBias
heightBiasPower type:#float default:10 ui:ui_heightBiasPower

heightsegs type:#integer default:1 ui:ui_heightsegs
capsegs type:#integer default:1 ui:ui_capsegs
sides type:#integer default:16 ui:ui_sides
smooth type:#boolean default:on ui:ui_smooth
sliceOn type:#boolean default:off ui:ui_sliceOn
sliceFrom type:#float default:0 ui:ui_sliceFrom
sliceTo type:#float default:0 ui:ui_sliceTo
mapCoords type:#boolean default:on ui:ui_mapCoords
realWorldMapSize type:#boolean default:off ui:ui_realWorldMapSize

on sliceOn get val do try
(
this.params.ui_sliceFrom.enabled = this.params.ui_sliceTo.enabled = val
)
catch (false)
)
rollout params "Parameters"
(
spinner ui_height "Height: " type:#worldUnits range:[0,1e9,0] fieldwidth:52 align:#right offset:[8,6]
spinner ui_heightBias "Height Bias: " type:#float range:[-1,1,0] scale:0.01 fieldwidth:52 align:#right offset:[8,-2]
spinner ui_heightBiasPower "Height Power: " range:[1,100,0] type:#float scale:0.1 fieldwidth:52 align:#right offset:[8,-2]
spinner ui_heightsegs "Height Segments: " type:#integer range:[1,256,0] fieldwidth:52 align:#right offset:[8,6]
spinner ui_capsegs "Cap Segments: " type:#integer range:[1,256,0] fieldwidth:52 align:#right offset:[8,-2]
spinner ui_sides "Sides: " type:#integer range:[3,256,0] fieldwidth:52 align:#right offset:[8,-2]
checkbox ui_smooth "Smooth" align:#left offset:[83,6]
checkbox ui_sliceOn "Slice On" align:#left offset:[83,2]
spinner ui_sliceFrom "Slice From: " type:#float enabled:sliceOn range:[-1e9,1e9,0] scale:0.1 fieldwidth:52 align:#right offset:[8,0]
spinner ui_sliceTo "Slice To: " type:#float enabled:sliceOn range:[-1e9,1e9,0] scale:0.1 fieldwidth:52 align:#right offset:[8,-2]
checkbox ui_mapCoords "Generate Mapping Coords." align:#left offset:[-8,4]
checkbox ui_realWorldMapSize "Real-World map Size" align:#left offset:[-8,0]
)
fn domesh =
(
fn fastValue f heightBias:0.0 power:1 =
(
if heightBias < 0 then 1 - (pow (1 - f) (1 - power*heightBias)) else (pow f (1 + power*heightBias))
)

if coneobject == undefined do coneobject = createinstance cone
coneobject.height = height
coneobject.heightsegs = heightsegs
coneobject.capsegs = capsegs
coneobject.sides = sides
coneobject.smooth = smooth
coneobject.sliceOn = sliceOn
coneobject.sliceFrom = sliceFrom
coneobject.sliceTo = sliceTo
coneobject.mapCoords = mapCoords
coneobject.realWorldMapSize = realWorldMapSize
mesh = coneobject.mesh

for k=1.0 to heightsegs-1 do
(
f = k/heightsegs
ss = if sliceOn then (sides+2) else sides
s = (k*ss+2) + (capsegs-1)*ss
e = ((k+1)*ss+1) + (capsegs-1)*ss
verts = #{s..e}
h = height*(fastValue f heightBias:heightBias power:heightBiasPower)

for v in verts do
(
d = getvert mesh v
p = (normalize [d.x,d.y,0])*r
setvert mesh v [p.x,p.y,h]
)
)
update mesh
mesh
)
on buildmesh do domesh()

tool create
(
on mousePoint click do case click of
(
1: nodeTM.translation = gridPoint
4: #stop
)
on mouseMove click do case click of
(
2: radius1 = amax (abs gridDist.x) (abs gridDist.y)
3: height = gridDist.z
4: radius2 = amax (abs gridDist.x) (abs gridDist.y)
)
)
on update do domesh()
)

``````

#17

If radius2 = 0.0 it should weld all the center verts. Rather than having them all sit ontop of one another.

#18

i don’t think so. it should behave the same way as cone
there is a new version (i fixed topology issue when slice was on)

``````
/* denisT collection 2013 */

plugin simpleObject ConePlus name:"ConePlus"
classID:#(0x00001967, 0x1023099b)
category:"Standard Plus"
version:1
(
local coneobject
parameters params rollout:params
(

height type:#worldUnits default:0 ui:ui_height
heightBias type:#float default:0 ui:ui_heightBias
heightBiasPower type:#float default:10 ui:ui_heightBiasPower

heightsegs type:#integer default:1 ui:ui_heightsegs
sides type:#integer default:16 ui:ui_sides

capsOn type:#boolean default:on ui:ui_capsOn
capsegs type:#integer default:1 ui:ui_capsegs

smooth type:#boolean default:on ui:ui_smooth
sliceOn type:#boolean default:off ui:ui_sliceOn
sliceFrom type:#float default:0 ui:ui_sliceFrom
sliceTo type:#float default:0 ui:ui_sliceTo
mapCoords type:#boolean default:on ui:ui_mapCoords
realWorldMapSize type:#boolean default:off ui:ui_realWorldMapSize

on capsOn get val do
(
try(this.params.ui_capsegs.enabled = val) catch (false)
val
)
on sliceOn get val do
(
try(this.params.ui_sliceFrom.enabled = this.params.ui_sliceTo.enabled = val) catch (false)
val
)
)
rollout params "Parameters"
(
spinner ui_height "Height: " type:#worldUnits range:[0,1e9,0] fieldwidth:52 align:#right offset:[8,6]
spinner ui_heightBias "Height Bias: " type:#float range:[-1,1,0] scale:0.01 fieldwidth:52 align:#right offset:[8,-2]
spinner ui_heightBiasPower "Height Power: " range:[1,100,0] type:#float scale:0.1 fieldwidth:52 align:#right offset:[8,-2]
spinner ui_heightsegs "Height Segments: " type:#integer range:[1,256,0] fieldwidth:52 align:#right offset:[8,6]
spinner ui_sides "Sides: " type:#integer range:[3,256,0] fieldwidth:52 align:#right offset:[8,-2]

checkbox ui_capsOn "Caps On" align:#left offset:[83,4]
spinner ui_capsegs "Cap Segments: " type:#integer enabled:capsOn range:[1,256,0] fieldwidth:52 align:#right offset:[8,0]

checkbox ui_smooth "Smooth" align:#left offset:[83,6]
checkbox ui_sliceOn "Slice On" align:#left offset:[83,2]
spinner ui_sliceFrom "Slice From: " type:#float enabled:sliceOn range:[-1e9,1e9,0] scale:0.1 fieldwidth:52 align:#right offset:[8,0]
spinner ui_sliceTo "Slice To: " type:#float enabled:sliceOn range:[-1e9,1e9,0] scale:0.1 fieldwidth:52 align:#right offset:[8,-2]
checkbox ui_mapCoords "Generate Mapping Coords." align:#left offset:[-8,4]
checkbox ui_realWorldMapSize "Real-World map Size" align:#left offset:[-8,0]
)
fn domesh =
(
fn fastValue f heightBias:0.0 power:1 =
(
if heightBias < 0 then 1 - (pow (1 - f) (1 - power*heightBias)) else (pow f (1 + power*heightBias))
)

if coneobject == undefined do coneobject = createinstance cone
coneobject.height = height
coneobject.heightsegs = heightsegs
coneobject.capsegs = capsegs
coneobject.sides = sides
coneobject.smooth = smooth
coneobject.sliceOn = sliceOn
coneobject.sliceFrom = sliceFrom
coneobject.sliceTo = sliceTo
coneobject.mapCoords = mapCoords
coneobject.realWorldMapSize = realWorldMapSize
mesh = coneobject.mesh

for v=1 to mesh.numverts do
(
d = getvert mesh v
if d.z > 0 and d.z < height do
(
f = d.z/height
h = height*(fastValue f heightBias:heightBias power:heightBiasPower)
if (r = length [d.x,d.y,0]) > 0 do
(
)
p = (normalize [d.x,d.y,0])*r
setvert mesh v [p.x,p.y,h]
)
)
if not capsOn do
(
faces = #{}
for f=1 to mesh.numfaces do faces[f] = (getfacematid mesh f != 3)
meshop.deletefaces mesh faces
)

update mesh
mesh
)
on buildmesh do domesh()

tool create
(
on mousePoint click do case click of
(
1: nodeTM.translation = gridPoint
4: #stop
)
on mouseMove click do case click of
(
2: radius1 = amax (abs gridDist.x) (abs gridDist.y)
3: height = gridDist.z
4: radius2 = amax (abs gridDist.x) (abs gridDist.y)
)
)
on update do domesh()
)

``````

#19

could always make it an option.

#20

You’ll see I commented out some code I had implemented to resemble what you had there, but it kept throwing errors when it was un-commented.

Anywho it works great. Fun to mess with.

``````
plugin simpleObject ConePlus name:"ConePlus"
classID:#(0x00001967, 0x1023099b)
category:"Standard Plus"
version:1
(
local coneobject
parameters params rollout:params
(

noiseFrequency type:#float default:1 animatable:off ui:ui_noiseFrequency
noisePhase type:#float default:0 animatable:off ui:ui_noisePhase
noiseScale type:#float default:1 animatable:off ui:ui_noiseScale

height type:#worldUnits default:0 ui:ui_height
heightBias type:#float default:0 ui:ui_heightBias
heightBiasPower type:#float default:10 ui:ui_heightBiasPower

heightsegs type:#integer default:1 ui:ui_heightsegs
capsegs type:#integer default:1 ui:ui_capsegs
sides type:#integer default:16 ui:ui_sides
smooth type:#boolean default:on ui:ui_smooth

sliceOn type:#boolean default:off ui:ui_sliceOn
sliceFrom type:#float default:0 ui:ui_sliceFrom
sliceTo type:#float default:0 ui:ui_sliceTo
mapCoords type:#boolean default:on ui:ui_mapCoords
realWorldMapSize type:#boolean default:off ui:ui_realWorldMapSize

on sliceOn get val do try
(
this.params.ui_sliceFrom.enabled = this.params.ui_sliceTo.enabled = val
)
catch (false)
)
rollout params "Parameters"
(
spinner ui_noiseScale "Noise Scale: " range:[-1e9,1e9,0] type:#float scale:0.01 fieldwidth:54 align:#right offset:[8,6] tooltip:"Noise Scale"
spinner ui_noiseFrequency "Noise Frequency: " range:[0,1e9,0] type:#float scale:0.01 fieldwidth:54 align:#right offset:[8,-2] tooltip:"Noise Frequency"
spinner ui_noisePhase "Noise Phase: " range:[-1e9,1e9,0] type:#float scale:0.1 fieldwidth:54 align:#right offset:[8,-2] tooltip:"Noise Phase"
spinner ui_height "Height: " type:#worldUnits range:[0,1e9,0] fieldwidth:52 align:#right offset:[8,6]
spinner ui_heightBias "Height Bias: " type:#float range:[-1,1,0] scale:0.01 fieldwidth:52 align:#right offset:[8,-2]
spinner ui_heightBiasPower "Height Power: " range:[1,100,0] type:#float scale:0.1 fieldwidth:52 align:#right offset:[8,-2]
spinner ui_heightsegs "Height Segments: " type:#integer range:[1,256,0] fieldwidth:52 align:#right offset:[8,6]
spinner ui_capsegs "Cap Segments: " type:#integer range:[1,256,0] fieldwidth:52 align:#right offset:[8,-2]
spinner ui_sides "Sides: " type:#integer range:[3,256,0] fieldwidth:52 align:#right offset:[8,-2]
checkbox ui_smooth "Smooth" align:#left offset:[83,6]
checkbox ui_sliceOn "Slice On" align:#left offset:[83,2]
spinner ui_sliceFrom "Slice From: " type:#float enabled:sliceOn range:[-1e9,1e9,0] scale:0.1 fieldwidth:52 align:#right offset:[8,0]
spinner ui_sliceTo "Slice To: " type:#float enabled:sliceOn range:[-1e9,1e9,0] scale:0.1 fieldwidth:52 align:#right offset:[8,-2]
checkbox ui_mapCoords "Generate Mapping Coords." align:#left offset:[-8,4]
checkbox ui_realWorldMapSize "Real-World map Size" align:#left offset:[-8,0]
)
fn domesh =
(
fn fastValue f heightBias:0.0 power:1 =
(
if heightBias < 0 then 1 - (pow (1 - f) (1 - power*heightBias)) else (pow f (1 + power*heightBias))
)

if coneobject == undefined do coneobject = createinstance cone
-- 		coneobject.noiseFrequency = noiseFrequency
-- 		coneobject.noisePhase = noisePhase
-- 		coneobject.noiseScale = noiseScale
coneobject.height = height
coneobject.heightsegs = heightsegs
coneobject.capsegs = capsegs
coneobject.sides = sides
coneobject.smooth = smooth
coneobject.sliceOn = sliceOn
coneobject.sliceFrom = sliceFrom
coneobject.sliceTo = sliceTo
coneobject.mapCoords = mapCoords
coneobject.realWorldMapSize = realWorldMapSize
mesh = coneobject.mesh

for k=1.0 to heightsegs-1 do
(
f = k/heightsegs
ss = if sliceOn then (sides+2) else sides
s = (k*ss+2) + (capsegs-1)*ss
e = ((k+1)*ss+1) + (capsegs-1)*ss
verts = #{s..e}
noise = ((noise3 ([f*noiseFrequency,0,noisePhase]))*10*noiseScale)
h = height*(fastValue f heightBias:heightBias power:heightBiasPower)

print noise

for v in verts do
(
d = getvert mesh v
p = (normalize [d.x,d.y,0])*r
setvert mesh v [p.x,p.y,h]
)
)
update mesh
mesh
)
on buildmesh do domesh()

tool create
(
on mousePoint click do case click of
(
1: nodeTM.translation = gridPoint
4: #stop
)
on mouseMove click do case click of
(
2: radius1 = amax (abs gridDist.x) (abs gridDist.y)
3: height = gridDist.z
4: radius2 = amax (abs gridDist.x) (abs gridDist.y)
)
)
on update do domesh()
)

``````