Notifications
Clear all

[Closed] Preserve Texturecoordinates ?

Hello all.

again i’m working on my exporter and i have the following problem.

I do a snapshot of the object and the read out the verts, faces ,and mapfaces.
I noticed some artefacts in the mapping. So after some investigation i found out
that this has to do with preserving texturecoordinates. When i export the model
to .3ds and then reimport it everything works fine. You can see it in the picture below.
The right sphere has been modified by the .3ds export and it renders perfect.
The left one is what i get when exporting the mesh. It would be very good if i could
find a way to preserve the texturecoordinates like the .3ds export does.
Also i noticed that the number of vertices is higher in the “preserved” version.
Somehow the verts on the pole are duplicated as far as i found out.

Now my question. Is there any function i can put the mesh before exporting to
preserve texturecoordinates. After long searching in the reference and the forum
i couldn’t find any answer.

Help would be greatly apprechiated.

take care

u3dreal

10 Replies

If I am not mistaken, this problem occurs because there are ‘geometrical’ vertices that have several map vertices and your exporter does not support that. So why not to write an exporter which suppport several map vertices for the same vertex ?

A second solution will be to modify your mesh to have one map vertex by ‘geometrical’ vertex. Like in the 3DS exporter but I don’t like this solution.

Hi arketip,

yes you are right thats the case and it seems the 3ds export does the following .
it duplicates the verts when there is more than on mapvert for the vert.
If this is correct.

So far the renderer only take the geom data as following.

vertex pos=xyz normal=xyz uv0=xy uv1=xy …

tri_set
[xyz]
[xyz]
[xyz]
tri_set

and so on…

So this means i can only specify one mapvertex per vertex per mapchannel…

But somehow it should be possible to duplicate the right verts and arrange the faces …
Well so far i don’t have a clue on how this could work.

EDIT: Can i use the meshOp.breakVerts Command ?

I found a script on scriptspot that could be helpful.
It’s called bbf and it’s written by bobo. Somehow he translates the uvw to max 3 uvw…
which is what i think is the right thing to do here as 3ds is the old max format where
you could only set one mapvertex per vertex…like in the renderer.

So if you read this bobo could you plz point out the section of your script where i can find the apropriate function ?? This would be great…

Ah OK for anybody interested in what i’m doing here here is a link.

Max2Indigo integrates indigo renderer into 3DMax.

You can find the latest version here. 0.495
http://www.flipcode.dxbug.com/board.php?topic=436&starting=20

Although alot of the new stuff like
support for multi/sub materials , multiple mappingchannels, support for maxprucedurals…
is not there yet as i have to fix the texturecoordinates…

Thanks for your help …

take care

u3dreal

I have created a structure which stores the mapping coordinates of your object.
The function .getDuplicatedMapverts returns the vertices associed with several mapvertices.

The breakDuplicatedMapverts function breaks these vertices.
It’s a bit unoptimized because one new vertex is created by face and that’s not always neccessary. It would be better to optimize this part of the code…

I hope this help

struct mappingCoordinatesStruct
	(
	getMapvertsOfVert,
	getVertsOfMapvert,
	fn init theObj theMapChannel =
		(
		getVertsOfMapvert = #()
		getMapvertsOfVert = #()
		if (meshop.getMapSupport theObj theMapChannel) do (
			local numMapVerts = meshOp.getNumMapVerts theObj theMapChannel
			local numGeomVerts = meshop.getNumVerts theObj
			if numMapVerts != 0 do (
				getVertsOfMapvert = for mv=1 to numMapVerts collect #{}
				getMapvertsOfVert = for mv=1 to numGeomVerts collect #{}
				local numMapFaces = meshOp.getNumMapFaces theObj theMapChannel
				for f = 1 to numMapFaces do (
			    	local mapFace3Point = meshOp.getMapFace theObj theMapChannel f
					local mapFaceArray = #(mapFace3Point.x as integer,mapFace3Point.y as integer,mapFace3Point.z as integer)
					local meshFace3Point = getFace theObj f
					local meshFaceArray = #(meshFace3Point.x as integer,meshFace3Point.y as integer,meshFace3Point.z as integer)
					for mv=1 to mapFaceArray.count do (
						getVertsOfMapvert[mapFaceArray[mv]][meshFaceArray[mv]]=true
						getMapvertsOfVert[meshFaceArray[mv]][mapFaceArray[mv]]=true
						)
					)
				)
			)
		),
	fn getDuplicatedMapverts theObj theMapChannel = (
		local duplicatedMapverts=#{}
		local numVerts = getMapvertsOfVert.count
		for vIdx=1 to numVerts do (
			if getMapvertsOfVert[vIdx].numberset>1 do duplicatedMapverts[vIdx]=true
			)
		duplicatedMapverts
		)
	)

fn breakDuplicatedMapverts theObj theMapChannel = (
	local objMapStruct = mappingCoordinatesStruct()
	objMapStruct.init theObj theMapChannel
	local theVertsToProcess = objMapStruct.getDuplicatedMapverts theObj theMapChannel
	meshop.breakVerts theObj theVertsToProcess
	)

breakDuplicatedMapverts selection[1] 1

I don’t know how do the others renderer when there are several mapvertices by vertex.
Maybe they can use several mapvertices or they transform the objects before the render.

I don’t understand how Indigo retrieves the faces…

Hi arketip,

thank you very much your script works like silk !!

OK indigo works the following 

here is a simple example of a 200x200x200 cube

i already use the some code to split the mesh into elements by smoothiggroups
in order to preserve smoothing groups…i think you help me there as well…
That’s why we have 24 vertices.


    
    <mesh>
    
    		<name>Box02</name>
    	<embedded>
 			<vertex pos="-100.0 -100.0 0.0" normal="0.0 0.0 -1.0" uv0="1.0 0.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="100.0 -100.0 0.0" normal="0.0 0.0 -1.0" uv0="0.0 0.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="-100.0 100.0 0.0" normal="0.0 0.0 -1.0" uv0="1.0 1.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="100.0 100.0 0.0" normal="0.0 0.0 -1.0" uv0="0.0 1.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="-100.0 -100.0 200.0" normal="0.0 0.0 1.0" uv0="0.0 0.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="100.0 -100.0 200.0" normal="0.0 0.0 1.0" uv0="1.0 0.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="-100.0 100.0 200.0" normal="0.0 0.0 1.0" uv0="0.0 1.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="100.0 100.0 200.0" normal="0.0 0.0 1.0" uv0="1.0 1.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="-100.0 -100.0 0.0" normal="0.0 -1.0 0.0" uv0="0.0 0.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="100.0 -100.0 0.0" normal="0.0 -1.0 0.0" uv0="1.0 0.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="-100.0 100.0 0.0" normal="0.0 1.0 0.0" uv0="1.0 0.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="100.0 100.0 0.0" normal="1.0 0.0 0.0" uv0="1.0 0.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="-100.0 -100.0 200.0" normal="0.0 -1.0 0.0" uv0="0.0 1.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="100.0 -100.0 200.0" normal="0.0 -1.0 0.0" uv0="1.0 1.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="-100.0 100.0 200.0" normal="0.0 1.0 0.0" uv0="1.0 1.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="100.0 100.0 200.0" normal="1.0 0.0 0.0" uv0="1.0 1.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="-100.0 -100.0 0.0" normal="-1.0 0.0 0.0" uv0="1.0 0.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="100.0 -100.0 0.0" normal="1.0 0.0 0.0" uv0="0.0 0.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="-100.0 -100.0 200.0" normal="-1.0 0.0 0.0" uv0="1.0 1.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="100.0 -100.0 200.0" normal="1.0 0.0 0.0" uv0="0.0 1.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="100.0 100.0 0.0" normal="0.0 1.0 0.0" uv0="0.0 0.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="100.0 100.0 200.0" normal="0.0 1.0 0.0" uv0="0.0 1.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="-100.0 100.0 0.0" normal="-1.0 0.0 0.0" uv0="0.0 0.0" uv1="0 0" uv2="0 0"/>
 			<vertex pos="-100.0 100.0 200.0" normal="-1.0 0.0 0.0" uv0="0.0 1.0" uv1="0 0" uv2="0 0"/>
    		<triangle_set>
  			<material_name>02 - Default</material_name>
    			<tri>0 2 3</tri>
    			<tri>3 1 0</tri>
    			<tri>4 5 7</tri>
    			<tri>7 6 4</tri>
    			<tri>8 9 13</tri>
    			<tri>13 12 8</tri>
    			<tri>17 11 15</tri>
    			<tri>15 19 17</tri>
    			<tri>20 10 14</tri>
    			<tri>14 21 20</tri>
    			<tri>22 16 18</tri>
    			<tri>18 23 22</tri>
    		</triangle_set>
    	</embedded>
    	</mesh>
    
First you state the vetices, the normals and the uvs for each channel and 

then you define faces with these vertices and the material.
So you can only state one mapvertex per vertex per mapchannel.

This causes the problem we were talking about. I'm not sure if i will implement this 
directly into the exporter cause this problem only takes place with spherical and shrikwrap
mapping i think. 

With your kind permission i will add your script as a maxcript utility ( or elsewhere if you have a better idea ) of course stating your name and e-mail if you like.
So ppl can use the uvw preservation when necessary.
To implement this i will have to check what kind of mapping is used
( and so far i haven’t figured out how this works )
or if the object is a sphere ( haven’t figured this out as well ) and so on.
So because this is only necessary in special cases an extra utility will be sufficiant. Implementing will only slow down the exporter.
Or maybe you have a better idea.

You can mail me at -------------if you

EDIT :send you an e-mail

want me to state your full name and mail. 

Thank you very much again. 


u3dreal ;)
2 Replies
(@arketip)
Joined: 11 months ago

Posts: 0

I think you don’t need to transform the objects in 3DSmax.
You can export a different geometry to Indogo (directly).

For example: if you have 1 vertex with 2 different mapvertices, you can use 2 different number of vertices for Indogo. So you don’t have never a problem.

Not at all it is just an common example where there are several mapvertices for one vertex.
I’m not sure but a face mapping could be the source of an identical problem.
And potentially every unwrap operation can create this situation.

I think that no. The only fast means to know the situation It is to compare the number of vertices to the number of mapvertices. If the number is the same it is extremely probable that the object comprises only one mapvertex by vertex.
So your exporter will be fast but in the case where the number would be different it could adopt a specific treatment ( breakDuplicatedMapverts )
Ask to 3dsmax the number of mapvertices is really fast.
Just remember that the object can have several mapchannels…

(@u3dreal)
Joined: 11 months ago

Posts: 0

Thank you arketip for all the efford you put in to help me out…

Hm not quite sure if i get you right here if i just export another vert the faces will have to be renamed and that’s really a bit too hard for me now for now. If you mean the suggestion you stated below then i get it…ask for numverts and numMapverts and compare. that shouldn’t be too hard.

Ok you are right this wasn't really a professional solution.

Ok I’ll try that soon…but for to bed…

Yes already thought of that but i have no clue on how to handle this.
If i have two mapverts in the first channel and lets say three in the second channel then
what will i do ? Will i get three verts after breaking the duplicate verts ...what will happen 
with the third one of the second channel in the first channel. 

Will i just write x=0 and y=0 to the first channel ? What will happen when i ask for the
Mapvert of this one in the first channel where it does not exist ?
And will those be in the exact same place ?

Hm really have to think about that a little.

thanks for your help again.

u3dreal ;)

P.S.: The work on your site looks really really good. I like your comic style alot.

Yes you are right. In this case the best solution is to unify your object (the copy) before to export it.
Break all vertices which have duplicated mapvertices and that for all map channel.

I have created a function called getDuplicatedMapvertsAllChannels.
It returns the vertices to break in a bitarray (it could be empty).
When getDuplicatedMapvertsAllChannels is called, the test is performed for all used map channels.
If the number of vertices is equal to the number of mapvertices nothing happens.
If the numbers are not equal, and only in this case, the function look in the map structure to find the duplicated mapVertices.

The function breakDuplicatedMapverts breaks the verts only when the bitarray is not empty.
So you can call breakDuplicatedMapverts for all objects without slow down the exporter

Don’t forget that is not an ideal solution to use “meshop.breakVerts” because the smoothing groups can be affected. In the majority of the cases, there are too many created points.

Yes, I think that’s a good solution to set UV coordinates to (0,0) if the mapvertex don’t exist.

Thanks. Happy to hear it.
You are my first fan

struct mappingCoordinatesStruct
	(
	getMapvertsOfVert,
	getVertsOfMapvert,
	fn getActiveMapChannels theObj = (
		local activeMapChannels=#{}
		local numMapChannels = meshop.getNumMaps theObj
		for theMapChannel=1 to numMapChannels do ( if (meshop.getMapSupport theObj theMapChannel) do activeMapChannels[theMapChannel]=true )
		activeMapChannels
		),
	fn initMapStruct theObj theMapChannel =
		(
		getVertsOfMapvert = #()
		getMapvertsOfVert = #()
		if (meshop.getMapSupport theObj theMapChannel) do (
			local numMapVerts = meshop.getNumMapVerts theObj theMapChannel
			local numGeomVerts = meshop.getNumVerts theObj
			if numMapVerts != 0 do (
				getVertsOfMapvert = for mv=1 to numMapVerts collect #{}
				getMapvertsOfVert = for mv=1 to numGeomVerts collect #{}
				local numMapFaces = meshop.getNumMapFaces theObj theMapChannel
				for f = 1 to numMapFaces do (
			    	local mapFace3Point = meshop.getMapFace theObj theMapChannel f
					local mapFaceArray = #(mapFace3Point.x as integer,mapFace3Point.y as integer,mapFace3Point.z as integer)
					local meshFace3Point = getFace theObj f
					local meshFaceArray = #(meshFace3Point.x as integer,meshFace3Point.y as integer,meshFace3Point.z as integer)
					for mv=1 to mapFaceArray.count do (
						getVertsOfMapvert[mapFaceArray[mv]][meshFaceArray[mv]]=true
						getMapvertsOfVert[meshFaceArray[mv]][mapFaceArray[mv]]=true
						)
					)
				)
			)
		),
	fn getDuplicatedMapverts theObj theMapChannel = (
		local duplicatedMapverts=#{}
		local numVerts = getMapvertsOfVert.count
		for vIdx=1 to numVerts do (
			if getMapvertsOfVert[vIdx].numberset>1 do duplicatedMapverts[vIdx]=true
			)
		duplicatedMapverts
		)
	)

fn getDuplicatedMapvertsAllChannels theObj = (
	local theVertsToProcess = #{}
	local numGeomVerts = meshop.getNumVerts theObj
	local objMapStruct = mappingCoordinatesStruct()
	local theChannels=objMapStruct.getActiveMapChannels theObj
	local deepScan = false
	for theMapChannel in theChannels where ((meshop.getNumMapVerts theObj theMapChannel)!=numGeomVerts) do deepScan=true
	if deepScan do (
		for theMapChannel in theChannels do (
			objMapStruct.initMapStruct theObj theMapChannel
			local currentVertsToProcess = objMapStruct.getDuplicatedMapverts theObj theMapChannel
			theVertsToProcess+=currentVertsToProcess
			)
		)
	theVertsToProcess
	)

fn breakDuplicatedMapverts theObj = (
	local theVertsToProcess = getDuplicatedMapvertsAllChannels theObj
	if theVertsToProcess.numberset!=0 do meshop.breakVerts theObj theVertsToProcess
	)

breakDuplicatedMapverts selection[1]

Well what more can i say… Thank you very very much…!

It just works.........

If there would be the possibility to give points in this forum i would give you
1000000 point for being so kind. Thanks ...again..

Take care 

u3dreal ;)

I am glad to have been able to help you.

I am interrested to use Indigo now.
I have seen some pictures and that looks really good !

have a good day