Jump to content

[SOLVED] Node Export - Object Names.


photo

Recommended Posts

Hi, we have the following problem while exporting node files from 3ds max and then opening them in the editor:

 

After opening the node file in the editor, all of the objects have lost the names they had in 3ds max, they are now all called ObjectMesh 1, 2,3,4, etc and so on.. this of course makes it very difficult to find a particular object in the scene when needed.

 

Is there access to the Maxscript source code so that we can modify the exporter to export correct mesh names from 3ds max? or is there an easier way?

 

Thanks In Advance.

Link to comment

Is there access to the Maxscript source code so that we can modify the exporter to export correct mesh names from 3ds max? or is there an easier way?

 

You have to modify installed UNIGINE 3DSmax export script UniginExport.ms export script located in <your 3DSMax root>\Scripts\Startup folder.

 

Maybe UNIGINE is willing to include it into SDK.

 

UnigineExport.ms lines 380-420

.....
-- single mesh export
if single then (

select nodes
exportFile (path + "/meshes/" + name + ".mesh") #noprompt selectedonly:true

format "\t<node type=\"ObjectMesh\" name=\"%\">\n" (name) to:file  // ADDED NAME ATTRIBUTE
format "\t\t<mesh>%</mesh>\n" (path_prefix + "meshes/" + name + ".mesh") to:file

for node in nodes do (
	export_surface "\t\t" node node.material mat_prefix file
	if findItem materials node.material == 0 then append materials node.material
)

format "\t\t<transform>1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1</transform>\n" to:file
format "\t</node>\n" to:file
)
-- multiple mesh export
else (

format "\t<node type=\"ObjectDummy\">\n" to:file

for node in nodes do (

	select node
	exportFile (path + "/meshes/" + node.name + ".mesh") #noprompt selectedonly:true

	format "\t\t<node type=\"ObjectMesh\" name=\"%\">\n" (node.name) to:file  // ADDED NAME ATTRIBUTE
	format "\t\t\t<mesh>%</mesh>\n" (path_prefix + "meshes/" + node.name + ".mesh") to:file
	export_surface "\t\t\t" node node.material mat_prefix file
	format "\t\t\t<transform>1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1</transform>\n" to:file
	format "\t\t</node>\n" to:file

	if findItem materials node.material == 0 then append materials node.material
)

format "\t\t<transform>1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1</transform>\n" to:file
format "\t</node>\n" to:file
)

Link to comment
  • 2 weeks later...

Thanks very much, this worked great. Our 3ds max scripter here also added the function to sort the list alphabetically.

Link to comment

Our 3ds max scripter here also added the function to sort the list alphabetically.

 

Than maybe you could post this code snippet, as this might be useful for others too.

Link to comment
  • 3 weeks later...

Than maybe you could post this code snippet, as this might be useful for others too.

 

Sorry it took so long, but here you go - this has made exporting large scenes much better to navigate for us here, sorry for posting the whole scriopt and not just the changes - but i am unsure what our scripter actually changed.

 

/* Copyright (C) 2005-2011, Unigine Corp. All rights reserved.
*
* File:    UnigineExport.ms
* Desc:    Unigine export plugin for 3D Studio Max
* Version: 1.13
* Author:  Alexander Zaprjagaev <frustum@unigine.com>
*
* This file is part of the Unigine engine (http://unigine.com/).
*
* Your use and or redistribution of this software in source and / or
* binary form, with or without modification, is subject to: (i) your
* ongoing acceptance of and compliance with the terms and conditions of
* the Unigine License Agreement; and (ii) your inclusion of this notice
* in any version of this software that you use or redistribute.
* A copy of the Unigine License Agreement is available by contacting
* Unigine Corp. at http://unigine.com/
*/



/******************************************************************************\
*
* other stuff
*
\******************************************************************************/

fn uppercase instring = 
( 
local upper, lower, outstring 
upper="ABCDEFGHIJKLMNOPQRSTUVWXYZ" 
lower="abcdefghijklmnopqrstuvwxyz"
outstring=copy instring

for i=1 to outstring.count do
(
	j=findString lower outstring[i]
	if (j != undefined) do outstring[i]=upper[j]
)
outstring 
) 

/******************************************************************************\
*
* Settings
*
\******************************************************************************/

/*
*/
fn set_settings name value = (
setINISetting (getDir #plugcfg + "\\UnigineExport.ini") "Unigine" name (value as string)
)

fn get_settings name default = (
local value = getINISetting (getDir #plugcfg + "\\UnigineExport.ini") "Unigine" name
if value == "" then return default
return value
)

/******************************************************************************\
*
* Meshes
*
\******************************************************************************/

/*
*/
fn export_mesh type = (

-- select file
local name = undefined
if type == ".mesh" then name = getSaveFileName caption:"Select Mesh file" filename:(get_settings "export_mesh" "") types:"Unigine static mesh (*.mesh)|*.mesh" historyCategory:"Unigine"
if type == ".smesh" then name = getSaveFileName caption:"Select MeshSkinned file" filename:(get_settings "export_smesh" "") types:"Unigine skinned mesh (*.smesh)|*.smesh" historyCategory:"Unigine"
if type == ".sanim" then name = getSaveFileName caption:"Select MeshSkinned animation file" filename:(get_settings "export_sanim" "") types:"Unigine animation frames (*.sanim)|*.sanim" historyCategory:"Unigine"
if name == undefined then return false
if type == ".mesh" then set_settings "export_mesh" name
if type == ".smesh" then set_settings "export_smesh" name
if type == ".sanim" then set_settings "export_sanim" name

-- check extension
if getFilenameType name != type then name += type

-- select nodes
local nodes = #()
if selection.count != 0 then (
	for node in selection do (
		if node.isHidden == true then continue
		append nodes node
	)
) else (
	for node in rootnode.children do (
		if node.isHidden == true then continue
		append nodes node
	)
)

-- save selection
local old_selection = selection as array

-- export nodes
select nodes
exportFile name selectedonly:true

-- restore selection
select old_selection
)

/*
*/
fn export_multi_mesh = (

-- select target directory
local dir = getSavePath caption:"Select target directory" initialDir:(get_settings "export_multi_mesh" "") historyCategory:"Unigine"
if dir == undefined then return false
set_settings "export_multi_mesh" dir

-- select nodes
local nodes = #()
if selection.count != 0 then (
	for node in selection do (
		if node.isHidden == true then continue
		append nodes node
	)
) else (
	for node in rootnode.children do (
		if node.isHidden == true then continue
		append nodes node
	)
)

-- save selection
local old_selection = selection as array

-- export nodes
for node in nodes do (
	select node
	local name = dir + "/" + node.name + ".mesh"
	exportFile name #noprompt selectedonly:true
)

-- restore selection
select old_selection
)

/*
*/
fn import_mesh type = (

-- select file
local name = undefined
if type == ".mesh" then name = getOpenFileName caption:"Select Mesh file" filename:(get_settings "import_mesh" "") types:"Mesh (*.mesh)|*.mesh" historyCategory:"Unigine"
if type == ".smesh" then name = getOpenFileName caption:"Select MeshSkinned file" filename:(get_settings "import_smesh" "") types:"MeshSkinned (*.smesh)|*.smesh" historyCategory:"Unigine"
if type == ".sanim" then name = getOpenFileName caption:"Select MeshSkinned animation file" filename:(get_settings "import_sanim" "") types:"MeshSkinned animation (*.sanim)|*.sanim" historyCategory:"Unigine"
if name == undefined then return false
if type == ".mesh" then set_settings "import_mesh" name
if type == ".smesh" then set_settings "import_smesh" name
if type == ".sanim" then set_settings "import_sanim" name

-- import file
importFile name
)

/******************************************************************************\
*
* Spline export
*
\******************************************************************************/

/*
*/
fn export_spline = (

-- check selection
if selection.count == 0 then (
	MessageBox "Selection is null" title:"Export error"
	return false
)

-- export splines
for node in selection do (

	local name = getSaveFileName caption:"Select spline file" filename:(node.name + ".spline") types:"Spline (*.spline)" historyCategory:"Unigine"
	if name == undefined then return false

	exportFile name selectedonly:true
)
)

/*
*/
fn export_camera = (

-- check selection
if selection.count == 0 then (
	MessageBox "Selection is null" title:"Export error"
	return false
)

-- export cameras
for node in selection do (

	if classof node != FreeCamera and classof node != TargetCamera then continue

	local name = getSaveFileName caption:"Select camera file" filename:(node.name + ".txt") types:"Txt (*.txt)" historyCategory:"Unigine"
	if name == undefined then return false

	local file = openFile name mode:"wb"
	if file == undefined then (
		MessageBox "Can't create file" title:"Export error"
		return false
	)

	local current = currenttime
	local start = animationrange.start
	local end = animationrange.end

	local type = node.fovType
	node.fovType = 2

	format "%\n" (((end - start) as integer) / TicksPerFrame) to:file
	for time = start to end do (
		slidertime = time
		local xyz = node.transform.position
		local rot = node.transform.rotation
		format "% % % " xyz.x xyz.y xyz.z to:file
		format "% % % % " rot.x rot.y rot.z rot.w to:file
		format "%\n" node.curFOV to:file
	)

	node.fovType = type

	slidertime = current
	close file
)
)

/******************************************************************************\
*
* Node export
*
\******************************************************************************/

/*
*/
rollout node_window "Unigine node exporter" width:320 height:180 (

checkbox single_cb "Single mesh" pos:[10,10] checked:true
checkbox selected_cb "Selection only" pos:[10,32] checked:false
checkbox base_cb "Base material" pos:[10,54] checked:false
editText base_et "" pos:[100,54] width:200 readonly:true text:"mesh_base"
checkbox mat_prefix_cb "Material prefix" pos:[10,76] checked:false
editText mat_prefix_et "" pos:[100,76] width:200 readonly:true text:""
checkbox path_prefix_cb "Path prefix" pos:[10,98] checked:false
editText path_prefix_et "" pos:[100,98] width:200 readonly:true text:""
button ok_b "Ok" pos:[130,140] width:80 height:24
button cancel_b "Cancel" pos:[220,140] width:80 height:24

-- export material map
fn export_map map type path prefix file = (

	-- check map
	if map == undefined then return false
	if classof map != Bitmaptexture then return false

	-- find texture
	local old_name = mapPaths.getFullFilePath map.filename
	if old_name == "" then return false

	local new_name = path + "textures\\" + getFilenameFile old_name + ".dds"

	-- fix paths
	for i = 1 to old_name.count do (
		if old_name[i] == "\\" then old_name[i] = "/"
	)
	for i = 1 to new_name.count do (
		if new_name[i] == "\\" then new_name[i] = "/"
	)

	-- texture name		
	format "\t\t<texture name=\"%\">%</texture>\n" type (prefix + "textures/" + getFilenameFile old_name + ".dds") to:file

	-- compress texture
	local ret = undefined
	local command = "imagedds_x86.exe"
	if type == "diffuse" then ret = DOSCommand (command + " -m -c -o \"" + new_name + "\" \"" + old_name + "\"")
	if type == "normal" then ret = DOSCommand (command + " -m -n -a2 -o \"" + new_name + "\" \"" + old_name + "\"")
	if type == "specular" then ret = DOSCommand (command + " -m -c -o \"" + new_name + "\" \"" + old_name + "\"")

	if ret != undefined then (
		-- check execution
		if ret != 0 then (
			MessageBox ("Can't run \"" + command + "\" program") title:"Export error"
		)
		-- check texture
		else (
			local file = openFile new_name mode:"rb"
			if file == undefined then MessageBox ("Can't save \"" + new_name + "\" file") title:"Export error"
			else close file
		)
	)
)

-- export material
fn export_material mat path path_prefix file = (

	-- two sided
	if mat.twoSided then (
		format "\t\t<options two_sided=\"1\"/>\n" to:file
	)
	-- alpha
	if mat.opacitymapenable then (
		format "\t\t<options alpha_test=\"1\"/>\n" to:file
	)

	-- anisotropy
	if mat.shaderType == 0 then (
		format "\t\t<state name=\"light_omni\">2</state>\n" to:file
		format "\t\t<state name=\"light_cube\">2</state>\n" to:file
		format "\t\t<state name=\"light_proj\">2</state>\n" to:file
		format "\t\t<state name=\"light_world\">2</state>\n" to:file
	)

	if mat.diffusemapenable then export_map mat.diffusemap "diffuse" path path_prefix file
	if mat.bumpmapenable then export_map mat.bumpmap "normal" path path_prefix file
	if mat.specularmapenable then export_map mat.specularmap "specular" path path_prefix file

--	kill specular
	format "\t\t<parameter name=\"specular_scale\">0</parameter>\n" to:file
	format "\t\t<parameter name=\"specular_power\">1</parameter>\n" to:file

)

-- export surface
fn export_surface prefix node mat mat_prefix file = (

	-- single surface
	if classof mat == StandardMaterial then (
		format "%<surface name=\"%\" material=\"%\"/>\n" (prefix) (node.name) (mat_prefix + mat.name) to:file
	)

	-- multiple surfaces
	else if classof mat == MultiMaterial then (
		for i = 1 to mat.numsubs do (
			local m = mat[i]
			if m != undefined and classof m == StandardMaterial then (
				format "%<surface name=\"%\" material=\"%\"/>\n" (prefix) (node.name + "_" + m.name) (mat_prefix + mat.name + "_" + m.name) to:file
			)
		)
	)
)

-- export node
fn export_node node = (

	local single = single_cb.checked

	local selected = selected_cb.checked

	local base = base_cb.checked
	if base then base = base_et.text
	else base = "mesh_base"

	local mat_prefix = mat_prefix_cb.checked
	if mat_prefix then mat_prefix = mat_prefix_et.text
	else mat_prefix = ""

	local path_prefix = path_prefix_cb.checked
	if path_prefix then path_prefix = path_prefix_et.text
	else path_prefix = ""

	for i = 1 to path_prefix.count do (
		if path_prefix[i] == "\\" then path_prefix[i] = "/"
	)
	if path_prefix.count > 0 and path_prefix[path_prefix.count] != "/" then append path_prefix "/"

	local nodes = #()
	local materials = #()

	if selected then (
		for node in selection do (
			if node.material == undefined then continue
			if node.isHidden == true then continue
			append nodes node
		)
	) else (
		for node in rootnode.children do (
			if node.material == undefined then continue
			if node.isHidden == true then continue
			append nodes node
		)
	)

	-- sort nodes
	names_array = for ii in nodes collect (uppercase ii.name)
	sort names_array
	sorted_nodes = #()
	for ii = 1 to names_array.count do
	(
		append sorted_nodes (getnodebyname names_array[ii])
	)	
	nodes = sorted_nodes

	local path = getFilenamePath node
	local name = getFilenameFile node

	-- node file
	local file = openFile (path + "/" + name + ".node") mode:"wb"
	if file == undefined then return false

	format "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" to:file
	format "<nodes version=\"1.0\">\n" to:file

	-- material library
	format "\t<materials>\n" to:file
	format "\t\t<library>%</library>\n" (path_prefix + name + ".mat") to:file
	format "\t</materials>\n" to:file

	-- export nodes
	makeDir (path + "/meshes")

	local old_selection = selection as array

	-- single mesh export
	if single then (

		select nodes
		exportFile (path + "/meshes/" + name + ".mesh") #noprompt selectedonly:true
		node_name = name as string
		format "\t<node type=\"ObjectMesh\" name=\"%\">\n"  node_name to:file
		format "\t\t<mesh>%</mesh>\n" (path_prefix + "meshes/" + name + ".mesh") to:file

		for node in nodes do (
			export_surface "\t\t" node node.material mat_prefix file
			if findItem materials node.material == 0 then append materials node.material
		)

		format "\t\t<transform>1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1</transform>\n" to:file
		format "\t</node>\n" to:file
	)

	-- multiple mesh export
	else (

		format "\t<node type=\"ObjectDummy\">\n" to:file

		for node in nodes do (

			select node
			exportFile (path + "/meshes/" + node.name + ".mesh") #noprompt selectedonly:true
			node_name = node.name as string
			format "\t<node type=\"ObjectMesh\" name=\"%\">\n"  node_name to:file
			format "\t\t\t<mesh>%</mesh>\n" (path_prefix + "meshes/" + node.name + ".mesh") to:file
			export_surface "\t\t\t" node node.material mat_prefix file
			format "\t\t\t<transform>1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1</transform>\n" to:file
			format "\t\t</node>\n" to:file

			if findItem materials node.material == 0 then append materials node.material
		)

		format "\t\t<transform>1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1</transform>\n" to:file
		format "\t</node>\n" to:file
	)

	select old_selection

	format "</nodes>\n" to:file
	close file

	-- material file
	local file = openFile (path + name + ".mat") mode:"wb"
	if file == undefined then return false

	format "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" to:file
	format "<materials version=\"1.0\">\n" to:file

	-- export materials
	makeDir (path + "/textures")

	-- base material
	if base != "mesh_base" then (
		format "\t<material name=\"%\" parent=\"mesh_base\"/>\n" base to:file
	)

	-- inherit materials
	for mat in materials do (
		if classof mat == StandardMaterial then (
			format "\t<material name=\"%\" parent=\"%\">\n" (mat_prefix + mat.name) base to:file
			export_material mat path path_prefix file
			format "\t</material>\n" to:file
		)
		else if classof mat == MultiMaterial then (
			for i = 1 to mat.numsubs do (
				local m = mat[i]
				if m != undefined and classof m == StandardMaterial then (
					format "\t<material name=\"%\" parent=\"%\">\n" (mat_prefix + mat.name + "_" + m.name) base to:file
					export_material m path path_prefix file
					format "\t</material>\n" to:file
				)
				else (
					format "\t<material name=\"%\" parent=\"%\"/>\n" (mat_prefix + mat.name + "_" + m.name) base to:file
				)
			)
		)
		else (
			format "\t<material name=\"%\" parent=\"%\"/>\n" (mat_prefix + mat.name) base to:file
		)
	)

	format "</materials>\n" to:file
	close file

	return true
)

-- settings
fn load_settings = (
	single_cb.checked = ((get_settings "export_node_single_cb" "true") == "true")
	selected_cb.checked = ((get_settings "export_node_selection_cb" "false") == "true")
	base_cb.checked = ((get_settings "export_node_base_cb" "false") == "true")
	base_et.text = (get_settings "export_node_base_et" "mesh_base")
	base_et.readonly = not base_cb.checked
	mat_prefix_cb.checked = ((get_settings "export_node_mat_prefix_cb" "false") == "true")
	mat_prefix_et.text = (get_settings "export_node_mat_prefix_et" "")
	mat_prefix_et.readonly = not mat_prefix_cb.checked
	path_prefix_cb.checked = ((get_settings "export_node_path_prefix_cb" "false") == "true")
	path_prefix_et.text = (get_settings "export_node_path_prefix_et" "")
	path_prefix_et.readonly = not path_prefix_cb.checked
)

fn save_settings = (
	set_settings "export_node_single_cb" (single_cb.checked as string)
	set_settings "export_node_selection_cb" (selected_cb.checked as string)
	set_settings "export_node_base_cb" (base_cb.checked as string)
	set_settings "export_node_base_et" base_et.text
	set_settings "export_node_mat_prefix_cb" (mat_prefix_cb.checked as string)
	set_settings "export_node_mat_prefix_et" mat_prefix_et.text
	set_settings "export_node_path_prefix_cb" (path_prefix_cb.checked as string)
	set_settings "export_node_path_prefix_et" path_prefix_et.text
)

-- events
on node_window open do (
	load_settings()
)

on mat_prefix_cb changed state do (
	mat_prefix_et.readonly = not state
)

on path_prefix_cb changed state do (
	path_prefix_et.readonly = not state
)

on base_cb changed state do (
	base_et.readonly = not state
)

on ok_b pressed do (
	local name = getSaveFileName caption:"Select node file" filename:(get_settings "export_node" "") types:"Node (*.node)" historyCategory:"Unigine"
	if name != undefined then (
		if export_node name == false then (
			MessageBox "Can't export node" title:"Export error"
		) else (
			set_settings "export_node" name
			save_settings()
		)
	)
	DestroyDialog node_window
)

on cancel_b pressed do (
	DestroyDialog node_window
)
)

/******************************************************************************\
*
* Menu
*
\******************************************************************************/

/*
*/
rollout about_window "About Unigine" width:220 height:80 (

label about_l "Unigine exporter for 3ds Max v1.10" pos:[16,16]
button close_b "Close" pos:[120,40] width:80 height:24

on close_b pressed do (
	DestroyDialog about_window
)
)

/*
*/
macroScript export_mesh_action buttontext:"Mesh export" category:"Unigine" tooltip:"Export node to mesh" (
export_mesh ".mesh"
)

macroScript export_smesh_action buttontext:"MeshSkinned export" category:"Unigine" tooltip:"Export node to mesh skinned" (
export_mesh ".smesh"
)

macroScript export_sanim_action buttontext:"MeshSkinned animation export" category:"Unigine" tooltip:"Export node to mesh skinned animation" (
export_mesh ".sanim"
)

macroScript export_multi_mesh_action buttontext:"Multi Mesh export" category:"Unigine" tooltip:"Export nodes to mesh files" (
export_multi_mesh()
)

macroScript import_mesh_action buttontext:"Mesh import" category:"Unigine" tooltip:"Import node from mesh" (
import_mesh ".mesh"
)

macroScript import_smesh_action buttontext:"MeshSkinned import" category:"Unigine" tooltip:"Import node from mesh skinned" (
import_mesh ".smesh"
)

macroScript import_sanim_action buttontext:"MeshSkinned animation import" category:"Unigine" tooltip:"Import node from mesh skinned animation" (
import_mesh ".sanim"
)

macroScript export_spline_action buttontext:"Spline export" category:"Unigine" tooltip:"Export spline" (
export_spline()
)

macroScript export_camera_action buttontext:"Camera export" category:"Unigine" tooltip:"Export camera" (
export_camera()
)

macroScript export_node_action buttontext:"Node export" category:"Unigine" tooltip:"Export node" (
createDialog node_window
)

macroScript close_action buttontext:"Close" category:"Unigine" tooltip:"Export close" (
local menu = menuMan.findMenu "Unigine"
if menu != undefined then (
	menuMan.unRegisterMenu menu
	menuMan.updateMenuBar()
)
)

macroScript about_action buttontext:"About" category:"Unigine" tooltip:"About Unigine" (
createDialog about_window
)

/*
*/
fn init = (

local menu = menuMan.findMenu "Unigine"

if menu != undefined then (
	menuMan.unRegisterMenu menu
	menuMan.updateMenuBar()
)

local main = menuMan.getMainMenuBar()
local menu = menuMan.createMenu "Unigine"

menu.addItem (menuMan.createActionItem "export_mesh_action" "Unigine") -1
menu.addItem (menuMan.createActionItem "export_smesh_action" "Unigine") -1
menu.addItem (menuMan.createActionItem "export_sanim_action" "Unigine") -1
menu.addItem (menuMan.createActionItem "export_multi_mesh_action" "Unigine") -1

menu.addItem (menuMan.createSeparatorItem()) -1

menu.addItem (menuMan.createActionItem "import_mesh_action" "Unigine") -1
menu.addItem (menuMan.createActionItem "import_smesh_action" "Unigine") -1
menu.addItem (menuMan.createActionItem "import_sanim_action" "Unigine") -1

menu.addItem (menuMan.createSeparatorItem()) -1

menu.addItem (menuMan.createActionItem "export_spline_action" "Unigine") -1

menu.addItem (menuMan.createSeparatorItem()) -1

menu.addItem (menuMan.createActionItem "export_camera_action" "Unigine") -1

menu.addItem (menuMan.createSeparatorItem()) -1

menu.addItem (menuMan.createActionItem "export_node_action" "Unigine") -1

menu.addItem (menuMan.createSeparatorItem()) -1

menu.addItem (menuMan.createActionItem "close_action" "Unigine") -1

menu.addItem (menuMan.createSeparatorItem()) -1

menu.addItem (menuMan.createActionItem "about_action" "Unigine") -1

local item = menuMan.createSubMenuItem "Unigine" menu
local index = main.numItems() - 1

main.addItem item index
menuMan.updateMenuBar()
)

init()

Link to comment
  • 2 weeks later...
×
×
  • Create New...