Books and more books

Become a member of the CGSociety

Connect, Share, and Learn with our Large Growing CG Art Community. It's Free!

THREAD CLOSED
 
Thread Tools Search this Thread Display Modes
  02 February 2013
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
 
  02 February 2013
no, no, no... not again... why does this idea so excite young developers?
 
  02 February 2013
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.
 
  02 February 2013
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'
 
  02 February 2013
So in short a galaxy of stars creator? with constellations?
__________________
____________ ___ __ _
John A. Martini
JokerMartini@hotmail.com
www.JokerMartini.com
 
  02 February 2013
Originally Posted by JokerMartini: So in short a galaxy of stars creator? with constellations?

yes! be God!
 
  02 February 2013
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.
 
  02 February 2013
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
 
  02 February 2013
cool, call it boob factory
 
  02 February 2013
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
 
  02 February 2013
Quote: align:#rigth


__________________
Maxscript Made Easy...
http://davewortley.wordpress.com/
 
  02 February 2013
Originally Posted by DaveWortley:

who cares... rigth is OK. right alignment is default for spinners anyway
 
  02 February 2013
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)
		)
	)
)
 
  02 February 2013
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
 
  02 February 2013
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
 
Thread Closed share thread



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 vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 11:48 PM.


Powered by vBulletin
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.