Notifications
Clear all

[Closed] Attach for lightmapping and detach afterwards

Hey all,

So I’m trying to develop an automated solution for attaching selected objects together, lightmapping that single object, and then breaking it back apart to the original objects after the process.

Lets assume the scene (for simplicitys sake) is comprised of multiple buildings that I would like to attach and then lightmap. Then my desired end state is that each individual building is a separate object (for engine culling reasons).

A first method would be to use grouping (seems the easiest method), as that’s basically what groups are great for. I can group all of my buildings, run the lightmap procedure, then ungroup and bam! I’m all done. The only issue is that the Render To Texture procedure doesn’t see a group as a single object (since it’s not really a single object) and then therefore will try to bake separate maps and do separate automatic unwraps on each object in the group! NOOO!!

A second method could involve Elements. I thought that when each building was attached together, then each building would become an ‘element’ then all we would need to do is add in a ‘break apart by element’ script (already written) at the end of the lightmapping process. It seems that elements are retained from their lowest level back in the history of their creation so in my example, each window and door frame was an element due to the fact that it was modeled that way and I don’t know of a way to consolidate elements to your own desire (am I wrong?)

A third method would be to store selection sets of each object before attachment and then once its combined, draw upon these selection sets and detach each group of polygons into a new object. It seems that this will also not work due to the fact that the selection sets seem to be eradicated when you attach items (only retains the sets on the one object that everything is attached to). This is probably due to the triangle order getting changed around as meshes keep getting attached and appended onto another mesh…

All of this song and dance is to accommodate the Render to Texture lightmap baking process in Max which requires you to combine objects if you want your autogenerated UV3 to span across them.

So now I’m here, with 3 dead ends. Ideas?

10 Replies
1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

I’m not sure that “attaching” to one object is the right solution in your case but …

why do you attach original objects? make their copies, attach them to temp object, and delete the temp object after lightmapping…

Go with the elements approach – but keep track of the number of polys before and after the attach… ie: Sphere01 is your base object and it has 40 polys. you then attach Sphere02 and now you have 70 polys total on sphere01 (both put together)… you know that polys 1-40 are Sphere01 and 41-70 are Sphere02… store that info in an array and you’re all set.

There is one more method to do this. Select all the objects and apply a unwrap uvw modifier with map channel 3 then use flatten mapping and convert all to poly. Later select all the objects and use render to texture to bake ur lightmap to separate maps per object. Finally open one texture map in gimp and drag and drop the rest map into the layers and save the single map out. Re-assign the final map to all the objects.

Use this script for creating automatic unwrap with channel 3 on all objects.


sel = geometry as array
select sel
addmodifier selection (Unwrap_UVW())

for i in sel do
( i.modifiers[#unwrap_uvw].setMapChannel 3
 i.modifiers[#unwrap_uvw].unwrap6.selectFacesByNode #{1..(i.NumFaces)} i)

sel[1].modifiers[#unwrap_uvw].flattenMap 45 #([1,0,0], [-1,0,0], [0,1,0], [0,-1,0], [0,0,1],[0,0,-1]) 0.02 true 0 true true

converttopoly $

Akram,

Thanks for your solution. I don’t quite understand how the saving of the rendered lightmap and the combination of each could be scripted so I’m tempted to abandon the solution, as we need the flexibility of being able to make quick iterations on our level, and rebake without a bunch of effort combining textures. I’m currently working on solitude’s solution but I’m a slow MaxScripter so far so it’ll take me a moment to figure everything out. Thx guys so far!

Alright, so I have a prototype (non-gui version) of the combine and attach script. Obviously I would do some wonderful lightmapping inbetween the combine and detaching but this is for demonstration purposes.

Anyway, the script works but when it detaches it moves the objects a certain offset from where the original objects were. How can I fix this?

(To test, just create 3 cubes in an empty scene, select all 3, and then run the script. It’ll combine the cubes, then detach them all using the method listed above of storing the faces in an array as objects are attached)


SourceOBJ = $
sourceobjcount = sourceOBJ.count 

if SourceOBJ[1] == undefined then messagebox "Select everything you want to attach!" 
for ii = 1 to (sourceobjcount) do with redraw off (
	convertTo SourceOBJ[ii] (Editable_Mesh)
)
polycount = #()

for iii = 1 to (sourceobjcount) do with redraw off (
	polycount[iii] = SourceOBJ[1].numfaces
	print ("Polycount of mesh: " + polycount[iii] as string)
	if (iii < (sourceobjcount)) then (
		Attach SourceOBJ[1] SourceOBJ[2];
	)
)

-- ==================================================================
-- NOW WE JUST DETACH ALL THE OBJECTS WE JUST COMBINED
-- ==================================================================

print("time for detachment")
totalfaces = meshop.getNumFaces SourceOBJ[1]
for i = 1 to totalfaces do (
	append polycount i
)
for i = 1 to (sourceobjcount) do (
	if (i == 1) then (
		newmesh = meshop.detachFaces SourceOBJ[1] #{1..(polycount[1])} asMesh:true delete:false name:(SourceOBJ[1].name as String + "SPLIT")
	) else (
		newmesh = meshop.detachFaces SourceOBJ[1] #{(polycount[i-1]+1)..(polycount[i])} asMesh:true delete:false name:(SourceOBJ[1].name as String + "SPLIT")
	)
	update SourceOBJ[1]
	emesh = Editable_mesh()
	emesh.mesh = newMesh
	update emesh
)

Please excuse my sloppiness (and any suggestions / slaps in the face are more than welcome). How can I get the detached objects to exist in the same spot?

I think you need to set the pivot of the attached mesh to 0,0,0 before you detach… when you create the new mesh it’s created at 0,0,0, so it’s offsetting it based on the pivot or something. Editable poly is probably easier, but either way… you’re pretty close!

Went ahead and did it:

SourceOBJ = selection as array
 sourceobjcount = sourceOBJ.count 
 polycount = #()
 
 if SourceOBJ[1] == undefined then 
 	(
 		messagebox "Select everything you want to attach!" 
 	)
 	else
 	(
 		---Let's do the first object separately
 		temparray = #()
 		converttopoly SourceOBJ[1]
 		append temparray SourceOBJ[1].name
 		append temparray (getnumfaces SourceOBJ[1])
 		append polycount temparray
 		
 		--now lets attach all the other objects to the first one
 		for iii = 2 to (sourceobjcount) do with redraw off (
 			converttopoly SourceOBJ[iii]
 			temparray = #()
 			append temparray SourceOBJ[iii].name
 			append temparray (getnumfaces SourceOBJ[iii])
 			append polycount temparray
 			print ("Polycount of " + SourceOBJ[iii].name + ": " + ((getnumfaces SourceOBJ[iii]) as string))
 			Polyop.Attach SourceOBJ[1] SourceOBJ[iii];
 			)
 		
 		-- ==================================================  ================
 		-- NOW WE JUST DETACH ALL THE OBJECTS WE JUST COMBINED
 		-- ==================================================  ================
 
 		 print("time for detachment")
 		for i = sourceobjcount to 2 by -1 do (
 			totalfaces = getnumfaces SourceObj[1]
 			startface = (totalfaces - polycount[i][2]) + 1 
 			thebitarray = #{}
 			for i = startface to totalfaces do (append thebitarray i)
 			polyop.detachfaces SourceOBJ[1] thebitarray asnode:true name:polycount[i][1]
 			newobj = getnodebyname polycount[i][1]
 			centerpivot newobj
 		)
 	)

Let me clear some doubts, you are trying to attach object to create a single lightmap for ur scene and u are using automatic unwrap in render to texture dialog, Right.

The only issue is that the Render To Texture procedure doesn’t see a group as a single object (since it’s not really a single object) and then therefore will try to bake separate maps and do separate automatic unwraps on each object in the group! NOOO!!

To over come this just run the script with your scene open(Huge file might crash Max). This script selects all and creates a single unwrap for lightmapping(this is the same thing u get after attaching the object and automatic unwrap with RTT). After running the script, use render to texture(RTT) and select ‘use existing channel’ 3, don’t select automatic unwrap. Now render the lightmap. The only issue with this is to combine all the textures in photoshop or gimp. I found gimp easier i.e. open one map in gimp and drag and drop the rest maps on the layers it is then done(don’t forget to use alpha while RTT).

If u need any clarification i will try to upload pics or video of the process.

Akram, I was attempting to do the whole procedure in an automated fashion and the finalized attach and detach method is working perfectly for me, without the need to launch the external photo editor. Your method is also very valid, unless you need to make slight changes to the object placements and re-bake multiple times a day, and then the photoshop/gimp part starts getting tedius and in need of automation.

Thanks for your help though, and everyone else too.

Hmm, using most of what Solitude provided, I’m having an issue where my UV3 uvs are destroyed when i break apart the mesh. How do you deal with the preservation of UVs when splitting?

Here’s my splitting function:
(remember that polycount is a global variable written to after attaching)


FN DetachAttachedObjects_fn = (
	SourceOBJ = selection as array

	if SourceOBJ[1] == undefined then (
		messagebox "Select the one object you want to detach!" 
	) else (
		try(
			for i = sourceobjcount to 2 by -1 do (
				print "begin detachment"
				totalfaces = getnumfaces SourceObj[1]
				startface = (totalfaces - polycount[i][2]) + 1 
				thebitarray = #{}
				for i = startface to totalfaces do (append thebitarray i)
				polyop.detachfaces SourceOBJ[1] thebitarray asnode:true name:polycount[i][1]
				newobj = getnodebyname polycount[i][1]
				centerpivot newobj
				print "end detachment"
			)
		) catch(messagebox "It looks like you tried to detach a level that was not previously attached.
Attach FIRST before spliting back apart.")	
	)
)

This one is my bad. If I collapse the auto-unwrap on channel 3 to my editable poly, THEN split, it will carry over without any intervention on my part. If i leave the unwrap modifier on and split, it f’es up everything royally.

Sweet, all working.