Home Technical Talk

helpneeded.. maxscript question (uv)

polycounter
Offline / Send Message
rollin polycounter
hi

i eventually started to lern maxscript .. a model file import/export script for a very old microprose fligtsimulator

sooo .. i mainly have trouble to understand the way maxscript calls "things"
in this case a vertex

what i want to do:

x = 10
y = 0
z = 35

u = 0.4
v = 0.4
w = 0

thisIndex = polyOp.createVert myEditPolyObject [x ,y , z ]


and now i want to give this newly created vertex the texture coordinates [u, v, w]

i iknow i can move the textur points with eg. <void>moveX <float>p

but how do i aplly this movement to the vertex thisIndex ?

it would help me a lot if i understand the idear behind that method
thx

Replies

  • MoP
    Offline / Send Message
    MoP polycounter lvl 18
    Well, AFAIK, you have to use the Unwrap UVW methods to set UVW data.

    So I think the correct procedure for this would be to first create all the verts using the method you showed (polyOp.createVert) and obviously you will have to hook up the faces once you have created the vertices.
    Then once all the verts and faces exist, you can use the Unwrap UVW methods to get each geometric vertex index, find the corresponding UV index, and set it to the required value.

    Something which might be more difficult is dealing with seams, since you may have one geometric vertex which has 2 (or more!) UV indices. It depends how you're constructing the model, I mean you could just create one geometric vertex for every single UV and then only weld the geometric verts in the very final stage after the UVs are constructed.

    Either way it sounds like a "fun" exercise, I am pretty sure that Max's method of accessing/comparing UV and geometric vertex data is quite annoying to use.

    I don't have much experience constructing UVs from scratch though - I wrote a maxscript LWO file importer and it correctly imported all the meshes, but I stopped before I got to the UV reconstruction part :)

    edit: you might get some better / more useful replies to this over on www.tech-artists.org
  • renderhjs
    Offline / Send Message
    renderhjs sublime tool
    some things to keep in mind:
    The only level that UV and poly or mesh data share are "faces" whoose ID's are equal. So you could say that face #1 is equal to texture face #1 and all other faces.
    What is different though and very important to understand:
    Texture Vertex coordinates are way different from mesh Vertex coordinates - because as you might now any set of UV-faces can have a compelte different composition known as shell as a composition in the poly model itself.
    So again: face id's are equal but vertex coordinates (and also amount) vary and are different.


    Maybe give of a brief overview of what you really want to archive in the big loop - not how to solve this smal step. Because maybe there is a better way to do it.
  • rollin
    Offline / Send Message
    rollin polycounter
    hey thx so far.. i have to try and look into it more deeply tomorrow

    what i have is

    an array with the vertex data
    one block looks like this
    [x, y, z]

    an array with the face data
    one block looks like this
    (the length of it depending on the amount of vertices the poly shares)
    [vertexID1, u1, v1, vertexID2, u2, v2, ...]

    what i do atm is

    • look at the first face-data block
    • create a vertice for every vertexID in this block
    • create a face out of it (n-gon poly)
    • next i want (would be nice if possible) to set the uv coordinates of this face uv-points
    • go to the next face-data block and start again
    • and than i would (maybe) run a merge-vertice over the complete mesh, maybe even something more complex to merge just the vertice i want to be merged.. but thats not so important atm

    ( to create first all vertice and then create the polys does not realy work, bc it can be that i have 2 polys which share the same vertice and max would bring the "illegal face" error and its easier to accomplish the other way around)
    EDIT: one thought.. if i have to access the vertices for a lot of things AFTER i´v created the whole mesh it might be better to try this approach again.. bc i don´t see a way to keep the right vertex id´s otherwise
    any idear how i can prevent the problem of max not creating faces "over" existing faces? something relatively easy to develop?
  • renderhjs
    Offline / Send Message
    renderhjs sublime tool
    ok although you dont need this I will post it anyway because I prepared it anyway so:
    here is a code snippet that will read out your texture vertex points if you have a UVWunweap modifiert attached:
    obj = selection[ 1 ];
    if (classof (modPanel.getCurrentObject()) == Unwrap_UVW) then (
    	local uv = selection[1].modifiers[ #unwrap_uvw ];--the UV modifier
    	
    	local verts = #{1..(uv.NumberVertices())};
    	
    	for i in verts do (
    		local pt = uv.getVertexPosition 1 i;
    		print("vert. "+i as string+" pos.:" +pt.x as string+" / "+pt.y as string);
    	)
    )
    




    here is what you might propably want instead:
    http://renderhjs.net/bbs/polycount/colorcatch/xml_tools_18.ms

    its a smal script collection I wrote for this game project:
    maxscript_editor_01.gif
    http://boards.polycount.net/showthread.php?p=806838

    in particular these code lines might be interesting for you- the script constructs a mesh out of a binary stream and assigns the UV faces directly into the Mesh object- which is a bit tricky at some parts (the order was important or so):
    here is the load function that generates the Mesh:
    on btn_load pressed do
    	(
    		try(
    			url = txt.text;
    			--function to load custom file type
    			vert_array = #();
    			face_array = #();
    			texv_array = #();
    			texf_array = #();
    			
    			f = fopen url "rb";--read binary
    			if (f != undefined) then(
    				num_verts = readShort f;
    				num_faces = readShort f;
    				num_tverts = readShort f;
    				num_tsize = readShort f;
    			
    				vert_array.count = num_verts;
    				face_array.count = num_faces;
    				texv_array.count = num_tverts;--texture vertices
    				texf_array.count = num_faces;
    			
    				
    				for i = 1 to num_verts do
    				(
    					x = readShort f;
    					y = readShort f;
    					z = readShort f;
    					vert_array[i] = point3 x y z;--add 3point to array
    					print ("xyz: "+vert_array[i].x as string+", "+vert_array[i].y as string);
    				)
    				for i = 1 to num_faces do
    				(
    					x = readShort f as Integer +1;
    					y = readShort f as Integer +1;
    					z = readShort f as Integer +1;
    					face_array[i] = point3 x y z;
    				)
    				for i = 1 to num_tverts do
    				(
    					x = (readShort f as Float)/ num_tsize;
    					y = ((readShort f as Float) - num_tsize)/ num_tsize *-1 ;
    					z = 0 ;
    					texv_array[i] = point3 x y z;
    				)
    				for i = 1 to num_faces do
    				(
    					x = readShort f as Integer +1;
    					y = readShort f as Integer +1;
    					z = readShort f as Integer +1;
    					texf_array[i] = point3 x y z;
    				)
    				fclose f;
    				
    				--create Mesh
    				new_mesh = mesh vertices:vert_array faces:face_array;
    				new_mesh.name ="loadedObject";
    				
    				setNumTVerts new_mesh num_tverts;
    				for i = 1 to num_tverts do(
    					setTVert new_mesh i texv_array[i];--set texture vertice ID- to 3point array
    				)
    				
    				buildTVFaces new_mesh;--enable texture faces arrays
    				for i = 1 to num_faces do(
    					setTVFace new_mesh i texf_array[i];
    				)
    				--convert to poly
    				max select none;
    				select new_mesh;
    				macros.run "Modifier Stack" "Convert_to_Poly";
    				if ( (classof selection[1]) == Editable_Poly)then(
    					selection[1].alledges = on;
    					selection[1].renderable = false;
    				)
    				max select none;
    				
    				lbl_output.text = "ok:t"+num_faces as String+" fcs, "+num_verts as String+" vrts, "+num_tverts as String+" texVrts";
    				writeBinary.timerMessage.ticks = 0;
    				writeBinary.timerMessage.active = true;
    			)else(
    				lbl_output.text = "error loading";
    				writeBinary.timerMessage.ticks = 0;
    				writeBinary.timerMessage.active = true;
    			)			
    			fclose f;
    		)catch(
    			lbl_output.text = "error loading";
    			writeBinary.timerMessage.ticks = 0;
    			writeBinary.timerMessage.active = true;
    		);
    	)
    

    so these lines:
    setNumTVerts new_mesh num_tverts;
    				for i = 1 to num_tverts do(
    					setTVert new_mesh i texv_array[i];--set texture vertice ID- to 3point array
    				)
    				
    				buildTVFaces new_mesh;--enable texture faces arrays
    				for i = 1 to num_faces do(
    					setTVFace new_mesh i texf_array[i];
    				)
    
    are the one to look out for

    hope that helps somewhat
  • rollin
    Offline / Send Message
    rollin polycounter
    ohhhhhhhh maaaaaaan...

    found out that i dont need to create my mesh as edit poly.. and to make it even better: it seems a lot more complicate then doing it as edit mesh...

    thx hendrik .. this is enough new information to keep going for the next hours.. :)
  • rollin
    Offline / Send Message
    rollin polycounter
    ok the importer works quite well.. had to do some heavy fighting with many arrays but it does work

    with the esporter still to go i have some generel maxscript question

    what i know what is possible is something like this line to create dynamic vars

    execute("b" + i as string + " = 10");

    but is there a way to do it more like the flash-actionscript way ?

    eval("b" + i) = 10;
  • renderhjs
    Offline / Send Message
    renderhjs sublime tool
    on a sidenote, eval is not used since AS2 anymore it's written like this now
    this["b"+i]=10;
    

    but about maxscript- I haven't evaluated dymanic stuff yet, there is format which is pretty powerfull and it would be then written as:
    format "b%=10" i;
    
    whereas each % sign gets replaced by the followed parameters (any number you want). But so far I only traced with it, maybe read up the format related entries in the maxscript help
  • rollin
    Offline / Send Message
    rollin polycounter
    yes.. the format is quite cool but does only write into stringstreams..
    it doesn´t seem i can catch it within a maxscript line

    thx so far

    but lets ask the question a bit different


    what i want to do:

    create dynamically <n> objects with _for 1 to <n>_ and give them the vars myobject_<n>

    so i can later access them again dynamical with a _for_
  • renderhjs
    Offline / Send Message
    renderhjs sublime tool
    why do you need them with that names?- imo. you could simply use an array for that like this:
    myobject = #();
    
    for i = 1 to 24 do (
    	local b = myobject[i] = box height:50 width:10;--shortcut to the box, to the array content
    	b.pos = (10,10,20);
    )
    
    --later on to read them out or modifiy them....
    for i = 1 to myobject.count do (
    	local b = myobject[i];--shortcut to the array variable
    	b.name = "box "+i as string;
    	format "box % position % n" b.name b.pos
    )
    

    this i what I do all the time in other scripting languages - creating shortcuts to array contents. Not only makes it easier to work with arrays but it also speeds up the code execution since the maxscript does not need to create a 'lookup' each time since the variable 'b' is already cached.

    is that perhaps what you have in mind?
  • rollin
    Offline / Send Message
    rollin polycounter
    arrrg.. man you´re so right... thx man..


    buut script for import and export is in the last phase of testing and optimising
    this was an ugly crash course of maxscript -.-

    i´ll post it as soon as i think it´s worth of v.1.0 ;)

    i´m curious if there´s still someone modding EAW..

    lowpoly wwII plane ownage!!!!!

    wohoo :poly142:
  • rollin
    Offline / Send Message
    rollin polycounter
    ok.. one question again concerning texturVerts


    i´m wondering how i can link the following information:


    face nr #F has 3 vertices [v1, v2, v3]

    texture face nr #TF has 3 textur vertices [tv1, tv2, tv3]

    as you have mentioned #F == #TF

    buuut .. which tv represents which v (or the other way around)?
    i know the id´s don´t match.. but somehow i have to be able to tell which tv is based on which v (even if there could be more tv based on one v)
  • MoP
    Offline / Send Message
    MoP polycounter lvl 18
    The only way I know of doing this is by selecting the texture vertex and calling <unwrap_uvw>.getSelectedGeomVerts() to return the corresponding geometric vertex.

    I thought there must be a better way than this, but I haven't found one yet :/
  • renderhjs
    Offline / Send Message
    renderhjs sublime tool
    maybe this schnipsel can help :D
    channel = 1;
    local num_faces = polyop.getNumFaces $;
    for f = 1 to num_faces do(
    	uvF = polyOp.getMapFace $ channel f;
    	
    	uvVert1 = polyOp.getMapVert $ channel uvF[1];
    	uvVert2 = polyOp.getMapVert $ channel uvF[2];
    	uvVert3 = polyOp.getMapVert $ channel uvF[3];
    	--manipulate each uvVert, like uvVert1.x = 0.5; 
    	--or like this: uvVert2.x+= 0.5; 
    	
    	--store them back
    	polyOp.setMapVert $ channel uvF[1] uvVert1;
    	polyOp.setMapVert $ channel uvF[2] uvVert2;
    	polyOp.setMapVert $ channel uvF[3] uvVert3;
    )
    
    you just need the right support command to get through the hierarchy of the 3dsmax world
  • MoP
    Offline / Send Message
    MoP polycounter lvl 18
    Ah, nice ... I was thinking backwards since I've only ever tried accessing from Unwrap UVW, totally forgot you could go the other way and access texture verts from polyOp.
  • rollin
    Offline / Send Message
    rollin polycounter
    hmm.. i´m working with an Editable_mesh.. and i can´t convert it to an Editable_Poly bc of the very mad way the eaw-fileformat is build up

    so am i right if i say i cant use polyOp if i´m working with an Editable_Mesh

    annnnd if soo.. what´s the trick there


    it seems i can only access with eg.

    meshop.getMapFace <Mesh mesh> <Integer mapChannel> <Integer index>

    to get a point3 [tvert1, tvert2, tvert3]

    and

    getFace <mesh> <face_index_integer>

    to get a point3 [vert1, vert2, vert3]

    buuuuuuuuuuut the question is.. is tvert1 always corresponding to vert1? even if the uv´s are mirrored?

    .. i don´t know.. but i´ll try
  • rollin
    Offline / Send Message
    rollin polycounter
    ok it seems to work.. however i have to test it under various conditions to be sure

    so i still have to figure out how to get the vertex-clockvise-order for edit_mesh_polys right and the import/export script is somehow doing what its designed for :)
Sign In or Register to comment.