# Books and more books

 02 February 2013 JokerMartini Expert   portfolio John Martini CG Supervisor, 3D, Maxscript, VFX Ingenuity Engine Los Angeles, USA Books and more books 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. Now for the task lists 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 ) `````` __________________ ____________ ___ __ _ John A. Martini JokerMartini@hotmail.com www.JokerMartini.com share quote
 02 February 2013 denisT MAX Doctor   portfolio Denis Trofimov CA, USA no, no, no... not again... why does this idea so excite young developers? share quote
 02 February 2013 JokerMartini Expert   portfolio John Martini CG Supervisor, 3D, Maxscript, VFX Ingenuity Engine Los Angeles, USA 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. __________________ ____________ ___ __ _ John A. Martini JokerMartini@hotmail.com www.JokerMartini.com Last edited by JokerMartini : 02 February 2013 at 01:27 AM. share quote
 02 February 2013 denisT MAX Doctor   portfolio Denis Trofimov CA, USA Originally Posted by JokerMartini: I'm open to any suggestions for new tools that would be unique and different from anything previously created. 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' share quote
 02 February 2013 JokerMartini Expert   portfolio John Martini CG Supervisor, 3D, Maxscript, VFX Ingenuity Engine Los Angeles, USA So in short a galaxy of stars creator? with constellations? __________________ ____________ ___ __ _ John A. Martini JokerMartini@hotmail.com www.JokerMartini.com share quote
 02 February 2013 denisT MAX Doctor   portfolio Denis Trofimov CA, USA Originally Posted by JokerMartini: So in short a galaxy of stars creator? with constellations? yes! be God! share quote
 02 February 2013 JokerMartini Expert   portfolio John Martini CG Supervisor, 3D, Maxscript, VFX Ingenuity Engine Los Angeles, USA 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 1 for radius 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. __________________ ____________ ___ __ _ John A. Martini JokerMartini@hotmail.com www.JokerMartini.com Last edited by JokerMartini : 02 February 2013 at 02:00 AM. share quote
 02 February 2013 JokerMartini Expert   portfolio John Martini CG Supervisor, 3D, Maxscript, VFX Ingenuity Engine Los Angeles, USA So far. 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" classID:#(0x5b0fad29, 0x62323fc1) -- -- -- -- --The Mound Mesh Creator Script-- -- -- -- -- ( parameters paramBlock rollout:paramRollout ( radius1 type:#worldunits animatable:true ui:uiRadius1 default:0 radius2 type:#worldunits animatable:true ui:uiRadius2 default:0 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 on radius1 set val do ( if radius1 < 0 then radius1 = 0 ) on radius2 set val do ( if radius2 < 0 then radius2 = 0 ) ) -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- rollout paramRollout "Parameters" ( spinner uiRadius1 "Radius 1:" range:[-1e+6, 1e+6, 0] spinner uiRadius2 "Radius 2:" range:[-1e+6, 1e+6, 20] 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] local vertX, vertY, radius, theta, radadd, radstep, crcl radadd = ((radius2 - radius1) as float) / (subdivs + 1) radstep = (subdivs + 2) radius = radius1 ------ arch implementation arch = 0 for crcl = 1 to radstep do ( for theta = 0 to 359 by (360.0 / segments) do ( vertX = cos(theta) * radius vertY = sin(theta) * radius setvert tmesh varVertCount [vertX, vertY, (arch)]; varVertCount += 1 ) radius += radadd arch += (height/(radstep-1)) print radstep print (height/radstep) ) ------- [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] if radius1 == 0 then ( local i local weldVerts = for i = 1 to segments collect i meshop.weldvertset mesh weldVerts ) ------- Flips normals if (radius1 > radius2) then ( 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: ( radius2 = (distance nodeTM.position gridpoint) if abs(griddist.y) > radius2 then radius2 = abs(griddist.y) if radius2 < 0 then radius2 = 0 ) 3: ( radius1 = (distance nodeTM.position gridpoint) if radius1 < 0 then radius1 = 0 ) ) ) ) ) delete objects select (mound radius1:20.0 height:10.0 subdivs:10) completeredraw()`````` __________________ ____________ ___ __ _ John A. Martini JokerMartini@hotmail.com www.JokerMartini.com share quote
 02 February 2013 Klunk Lord of the posts   portfolio Klunk United Kingdom cool, call it boob factory share quote
 02 February 2013 denisT MAX Doctor   portfolio Denis Trofimov CA, USA 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 ( radius1 type:#worldUnits default:0 ui:ui_radius1 radius2 type:#worldUnits default:0 ui:ui_radius2 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_radius1 "Radius 1: " type:#worldUnits range:[0,1e9,0] fieldwidth:52 align:#rigth offset:[8,0] spinner ui_radius2 "Radius 2: " type:#worldUnits range:[0,1e9,0] fieldwidth:52 align:#rigth offset:[8,-2] 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.radius1 = radius1 coneobject.radius2 = radius2 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 share quote
 02 February 2013 DaveWortley   portfolio David Wortley Technical Director Vancouver, Canada Quote: align:#rigth __________________ Maxscript Made Easy... http://davewortley.wordpress.com/ share quote
 02 February 2013 denisT MAX Doctor   portfolio Denis Trofimov CA, USA Originally Posted by DaveWortley: who cares... rigth is OK. right alignment is default for spinners anyway share quote
 02 February 2013 denisT MAX Doctor   portfolio Denis Trofimov CA, USA 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 ( radius1 type:#worldUnits default:0 ui:ui_radius1 radius2 type:#worldUnits default:0 ui:ui_radius2 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_radius1 "Radius 1: " type:#worldUnits range:[0,1e9,0] fieldwidth:52 align:#right offset:[8,0] spinner ui_radius2 "Radius 2: " type:#worldUnits range:[0,1e9,0] fieldwidth:52 align:#right offset:[8,-2] 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.radius1 = radius1 coneobject.radius2 = radius2 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) ) ) )`````` share quote
 02 February 2013 JokerMartini Expert   portfolio John Martini CG Supervisor, 3D, Maxscript, VFX Ingenuity Engine Los Angeles, USA 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. __________________ ____________ ___ __ _ John A. Martini JokerMartini@hotmail.com www.JokerMartini.com share quote
 02 February 2013 JokerMartini Expert   portfolio John Martini CG Supervisor, 3D, Maxscript, VFX Ingenuity Engine Los Angeles, USA arching position 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] )`````` __________________ ____________ ___ __ _ John A. Martini JokerMartini@hotmail.com www.JokerMartini.com share quote

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts vB code is On Smilies are On [IMG] code is On HTML code is Off CGSociety Society of Digital Artists www.cgsociety.org Powered by vBulletinCopyright ©2000 - 2006, Jelsoft Enterprises Ltd.