Home Technical Talk

Autodesk 3ds Maxscript To GML Model Conversions

polycounter lvl 6
Offline / Send Message
MrQuetch polycounter lvl 6
Hello, everyone and anyone who is willing to help. I hope that this is the right section to post this topic, and if it isn't - I would be more than glad to have it be moved somewhere else just as suitable.

I am having an on going problem that I cannot seem to solve on my own - no matter how many times I have already tried. I have come up with many different ways and it still does not seem to work. I will admit that I am close - but there are still some minor problems. I am making a script in 3ds Max that will allow me to convert a model into GML code.

For example, the GML syntax of drawing a 3D primitive looks like this:
    // d3d_vertex_texture_colour(x,y,z, tex_x, tex_y, color, alpha);
    d3d_primitive_begin(pr_trianglelist);
    d3d_vertex_texture_colour(0,0,0,0,0,$FF0000,1);
    d3d_vertex_texture_colour(1024,0,0,0,0,$00FF00,1);
    d3d_vertex_texture_colour(0,768,0,0,0,$0000FF,1);
    d3d_primitive_end();

The Maxscript that I have already makes this exact code - the vertex positions, and colors work. I'm currently looking into the texture coordinates. However, the vertex colors are not showing what they're supposed to when I run my GML program. The models look fine in 3ds Max, but not GML. So, the right colors get put into the triangle, but the wrong indices are being used. I have already looked into the 3ds Max documentation for trying to get the right triangle indices along with proper vertex indices - but for the life of me... I cannot seem to get it to work.

The bulk of my attached file code is just the conversion of the RGB values to hex. GML is weird though, the colors are backwards - they go by BGR instead of RGB. That's already been fixed. The only part I cannot get working are the proper indices. My brain seems to fried at this point.

Any help at all is strongly appreciated.

Replies

  • MrQuetch
    Offline / Send Message
    MrQuetch polycounter lvl 6
    Before I go, I would also like to say my model was originally a mesh with all vertices stitched. I have found the models look better when I select all of the triangles, and explode them with a value of 0. Then, I merge all of the triangles back together, but without stitching the vertices - then running my script. The color indices still don't work properly - but this is as close as I have gotten.
  • monster
    Offline / Send Message
    monster polycounter
    I don't know what GML is, is there a program you can view the files?

    Anyway, the main problem is that you are getting the vertex color incorrectly. The function expects a map vert index, but you are giving it a geometry index. The number of vertex colors doesn't always equal the number of geo verts. For example, a vertex is connected to 2 faces. On one side it's red, and the other side it's blue. So now we have 1 geo vert with 2 vert colors.

    Also, you can make the script a lot shorter using the bit.intAsHex command, instead of mapping every possible color.

    Finally, it looks like you were building a primitive per face, which I assume is incorrect. So I took the start and end out of the loop.

    I can't view GML files, so I on't know if this works.

    (
    	-- the selected object
    	theMesh = $.mesh
    	fStream = newScript()
    	
    	--Make sure vertex color is enabled
    	if meshop.getMapSupport theMesh 0 == false do meshop.setMapSupport theMesh 0 true
    
    	--Bookmark some functions
    	intAsHex = bit.intAsHex
    	getMapVert = meshop.getMapVert
    	getMapVertsUsingMapFace = meshop.getMapVertsUsingMapFace
    	numfaces = theMesh.numfaces
    	
    	format "d3d_primitive_begin(pr_trianglelist); \n" to:fStream
    
    	-- for-loop to get all of the faces from the mesh
    	for f = 1 to numfaces do
    	(
    		
    		--GET THE VERTEX COLORS
    		mapVerts = getMapVertsUsingMapFace theMesh 0 f 
    		
    		vColors = #()
    		
    		for m in mapVerts where mapVerts[m] do
    		(
    			vColor = (getMapVert theMesh 0 m) * 255.0
    			append vColors (intAsHex vColor.x)
    			append vColors (intAsHex vColor.y)
    			append vColors (intAsHex vColor.z)
    		)
    		
    		--MAKE SURE ALL HEX HAVE 2 CHARACTERS
    		for v = 1 to vColors.count do
    		(
    			if vColors[v].count == 1 do vColors[v] = "0" + vColors[v]
    		)
    		
    		--GET THE GEO VERTS
    		face = GetFace theMesh f
    		vert_1 = GetVert theMesh face.x
    		vert_2 = GetVert theMesh face.y
    		vert_3 = GetVert theMesh face.z
    		
    		format "d3d_vertex_colour(%% %% %% $%%%% 1); \n" (vert_1.x) "," (vert_1.y) "," (vert_1.z) "," vColors[3] vColors[2] vColors[1] "," to:fStream
    		format "d3d_vertex_colour(%% %% %% $%%%% 1); \n" (vert_2.x) "," (vert_2.y) "," (vert_2.z) "," vColors[6] vColors[5] vColors[4] "," to:fStream
    		format "d3d_vertex_colour(%% %% %% $%%%% 1); \n" (vert_3.x) "," (vert_3.y) "," (vert_3.z) "," vColors[9] vColors[8] vColors[7] "," to:fStream
    	)
    	
    	format "d3d_primitive_end(); \n" to:fStream
    )

  • MrQuetch
    Offline / Send Message
    MrQuetch polycounter lvl 6
    monster said:
    I don't know what GML is, is there a program you can view the files?

    Anyway, the main problem is that you are getting the vertex color incorrectly. The function expects a map vert index, but you are giving it a geometry index. The number of vertex colors doesn't always equal the number of geo verts. For example, a vertex is connected to 2 faces. On one side it's red, and the other side it's blue. So now we have 1 geo vert with 2 vert colors.

    Also, you can make the script a lot shorter using the bit.intAsHex command, instead of mapping every possible color.

    Finally, it looks like you were building a primitive per face, which I assume is incorrect. So I took the start and end out of the loop.

    I can't view GML files, so I on't know if this works.

    (
    	-- the selected object
    	theMesh = $.mesh
    	fStream = newScript()
    	
    	--Make sure vertex color is enabled
    	if meshop.getMapSupport theMesh 0 == false do meshop.setMapSupport theMesh 0 true
    
    	--Bookmark some functions
    	intAsHex = bit.intAsHex
    	getMapVert = meshop.getMapVert
    	getMapVertsUsingMapFace = meshop.getMapVertsUsingMapFace
    	numfaces = theMesh.numfaces
    	
    	format "d3d_primitive_begin(pr_trianglelist); \n" to:fStream
    
    	-- for-loop to get all of the faces from the mesh
    	for f = 1 to numfaces do
    	(
    		
    		--GET THE VERTEX COLORS
    		mapVerts = getMapVertsUsingMapFace theMesh 0 f 
    		
    		vColors = #()
    		
    		for m in mapVerts where mapVerts[m] do
    		(
    			vColor = (getMapVert theMesh 0 m) * 255.0
    			append vColors (intAsHex vColor.x)
    			append vColors (intAsHex vColor.y)
    			append vColors (intAsHex vColor.z)
    		)
    		
    		--MAKE SURE ALL HEX HAVE 2 CHARACTERS
    		for v = 1 to vColors.count do
    		(
    			if vColors[v].count == 1 do vColors[v] = "0" + vColors[v]
    		)
    		
    		--GET THE GEO VERTS
    		face = GetFace theMesh f
    		vert_1 = GetVert theMesh face.x
    		vert_2 = GetVert theMesh face.y
    		vert_3 = GetVert theMesh face.z
    		
    		format "d3d_vertex_colour(%% %% %% $%%%% 1); \n" (vert_1.x) "," (vert_1.y) "," (vert_1.z) "," vColors[3] vColors[2] vColors[1] "," to:fStream
    		format "d3d_vertex_colour(%% %% %% $%%%% 1); \n" (vert_2.x) "," (vert_2.y) "," (vert_2.z) "," vColors[6] vColors[5] vColors[4] "," to:fStream
    		format "d3d_vertex_colour(%% %% %% $%%%% 1); \n" (vert_3.x) "," (vert_3.y) "," (vert_3.z) "," vColors[9] vColors[8] vColors[7] "," to:fStream
    	)
    	
    	format "d3d_primitive_end(); \n" to:fStream
    )

    Hi there, monster.

    I apologize that I didn't get back to you earlier. I am very grateful that you were able to reply so quickly. To be honest, I was not expecting a full script. I cannot thank you enough! I really appreciate this! I just felt a big weight slide off my shoulders. You are definitely fluent in your Maxscripts. When I want to make my model converters for other game engines I will always be able to refer to this code as a reference. The colors are perfect, and they show just fine. Yes, I do have a viewer, and everything is as is.

    However, there is one problem, and if it can be fixed the script will be perfect. Right now I am actually "flooring" the vertex positions. The reason I do this is because sometimes I get a letter "e" in  the vertex position.

    Some examples:
    d3d_vertex_colour(-7.4386e-06, -16.0, -27.7128, $000063, 1); 
    d3d_vertex_colour(-16.0, 2.41593e-06, -27.7128, $000000, 1); 
    d3d_vertex_colour(-6.99382e-07, 16.0, -27.7128, $070500, 1); 

    GML does not like those letter "e"s, and my game will not run unless they're gone. Is there a way I can get just the first few values after the decimal, and no letter "e"?

    I'm really grateful for what you have already provided, and I hope I don't feel like a pain for asking for more.

    You're awesome, monster!
  • MrQuetch
    Offline / Send Message
    MrQuetch polycounter lvl 6
    Well, I managed to find a function somewhere, and it fixed the problem. Here is what I'm using. The first value is what you want to round, and the second value is how many places after the decimal. I'm using this as a part of the script where it writes down the vertex positions to the file stream. So, unless you have another way of doing it that's better - the work here is done.

    function roundFloat val dp =
        (
        a = val * (10^dp)
        b = a as integer
        a = b as float / (10^dp)
        return a
        )

    Now, I'm going to try and figure out the texture coordinates. With the data that is already in the script, it looks like it will be pretty easy to get the coordinates.
  • monster
    Offline / Send Message
    monster polycounter
    I was going to suggest to round the number as well. This function might be faster, because it's not casting between int and floats. But it'll be interesting to know if you test it.

    fn round_to val n = 
    (
        local mult = 10.0 ^ n
        (floor ((val * mult) + 0.5)) / mult
    )

  • MrQuetch
    Offline / Send Message
    MrQuetch polycounter lvl 6
    monster said:
    I was going to suggest to round the number as well. This function might be faster, because it's not casting between int and floats. But it'll be interesting to know if you test it.

    fn round_to val n = 
    (
        local mult = 10.0 ^ n
        (floor ((val * mult) + 0.5)) / mult
    )

    Hey again, monster.

    I've tested the function that you've provided, and it is faster. It doesn't feel like it will make much of a difference right now, but perhaps it will in the long run. As soon as I start exporting tons of models I'm sure I will notice the difference. Thanks for that function.

    For getting the proper texture coordinates, will I use the same function that gets the colors? It looks like it will work the same way. I'm sure the only difference is just a different map channel? Let me know if I'm wrong, I'm still unfamiliar with this. Thanks again for your help.
  • monster
    Offline / Send Message
    monster polycounter
    MrQuetch said:

    For getting the proper texture coordinates, will I use the same function that gets the colors? It looks like it will work the same way. I'm sure the only difference is just a different map channel? Let me know if I'm wrong, I'm still unfamiliar with this. Thanks again for your help.
    Yeah just change the mapping channel. 
  • MrQuetch
    Offline / Send Message
    MrQuetch polycounter lvl 6
    Ok, the mapping channel was it. I have texture coordinates now. I'm getting both mapping channels 0 and 1 for colors and textures. However, the vertex texture indexes appear to be wrong. I'm really close to solving this now. I just need a little "push". Can you let me know if this script looks right? Sorry to be of a bother - I appreciate your help yet, again.
  • monster
    Offline / Send Message
    monster polycounter
    You're getting the UV correctly. The only thing I can think is since the colors are BGR instead of RGB maybe the UVs are VU.

    Since I can't view GML files, and I'm not familiar with the format maybe ask on another forum where that file type is common.
  • MrQuetch
    Offline / Send Message
    MrQuetch polycounter lvl 6
    monster said:
    You're getting the UV correctly. The only thing I can think is since the colors are BGR instead of RGB maybe the UVs are VU.

    Since I can't view GML files, and I'm not familiar with the format maybe ask on another forum where that file type is common.
    Hey again, monster.

    Thanks for checking the script. Actually, I managed to get the vertex texture coordinate data properly. I was only listing 'x' and 'y' before, when I was forgetting that the 'z' in this case was the 3rd vertex of the triangle. Now, I check 'x','y', and 'z'. But, when I go to print the actual data, I only reference the 'x' and 'y'. That was a silly mistake on my part, but I'm glad it works. Looking at the entire script now, I have learned quite a bit and now it is even easier to understand. Thank you for teaching me about bookmarking functions and other useful Maxscript syntax; I didn't know about the 'bit.intAsHex' function, and if I had known before - would've done that in the first place.

    We can now mark this discussion as "Closed".
Sign In or Register to comment.