Setting UV coordinates from scripts

Setting UV coordinates from scripts

Hi Martin,

I'm working on some models for a game, and I need to be able to set very specific UV coordinates for a selection of faces.

I'm making the models by starting from a cube and using the extrusion tools to build up a more complex shape. This is ideal, because it results in each quad-shaped face having UV coordinates of {{0, 0}, {0, 1}, {1, 1}, {1, 0}}. This allows me to have once copy of my texture mapped onto each face.

There are a couple of places where this doesn't work well. For one thing, if I delete some geometry and rebuild it with Fill Hole or Polygon, I end up with all the UV coordinates of the new face being set to {0, 0} (I believe). Also, if I subdivide or slice a face, each new face gets part of the original UV mapping (which is sometimes what I want, sometimes not). In either case, I'd like to be able to reset the mapping somehow.

Also, sometimes I want to be able to specify that there are two copies of the texture in the U direction, or I want to rotate the mapping by 90°. I might also want to extract a tile from a larger texture by giving fractional coordinates.

Of course, this is all the kind of thing that version 3.0's UV editor will address, but I'm trying to find a short term solution that will allow me to continue doing all the work in Cheetah3D (instead of transferring to Blender for this purpose).

My question is: is there any way I can write a JavaScript to get and set UV coordinates for selected polygons? Assuming it's possible, if you could give me some basic pointers to the nature of the API, that would be very much appreciated.

Thanks in advance!
 
Hi,
the features you need are already implemented. Just not documented. In the next week I will work on the Javascript docuementation while the Cheetah3D 2.6 beta is out. I hope I come far enough to document the functions you need.
Writing the script itself shouldn't take much more than 50 lines.

By,
Martin
 
Hi Neil,
I've written a lot of Javascript API docs during the last days. So you can expect all the necessary documentation for your script within the final v2.6 download.

By,
Martin
 
Well, I'm starting to look at how I can use this now, and I think I understand in general what's going on. However, just a couple of things are puzzling me and I can't see the answers in the documentation at the moment (please correct me if I'm missing something!).

Firstly, does it make any difference which folder I put my scripts into? Do different kinds of script get called in different ways? It seems like some of them are set up to be called as buildUI(tool) and others as main(doc) - is there a correct choice for each kind of script?

Secondly, one of the scripts, Parameter Info.js, uses print() to output information, but it just seems to disappear instead of coming out of the console.log or somewhere similar. Am I looking in the wrong place?

Thanks again for writing the documentation! These issues aside it clarifies things nicely.
 
Sorry, more questions and/or problems!

I have written a prototype version of my script, but I'm encountering a crash bug when I try to set the UV coordinates of a vertex. I can get the UV coordinates fine, but attempting to set them causes a crash.

This is the script (this is a simplified version which just demonstrates the crash):

Code:
//
// Coerce UVs.js
//

function buildUI(tool)
{
    tool.addParameterSeparator("Coerce UVs.js");
//  tool.addParameterInt("First Vertex Index", 0, 0, 3, false, false);
    tool.addParameterButton("Apply","OK","apply");
}

function apply(tool)
{
	var obj = tool.document().selectedObject().core();

	var totalErrors = 0;

	for(index = 0; index < obj.polygonCount(); ++index)
	{
		if(obj.polygonSelection(index))
		{
			if(obj.polygonSize(index) != 4)
				++totalErrors;
			else
				coerceUVs(tool, obj, index);
		}
	}

	if(totalErrors > 0)
		OS.messageBox("Coerce UVs", "" + totalErrors + " polygon" + (totalErrors == 1 ? " was" : "s were") +
			" ignored because they weren't quads.");
}

function coerceUVs(tool, obj, polygonIndex)
{
	obj.setUVCoord(polygonIndex, 1, new Vec2D(0.0, 0.0));
	obj.setUVCoord(polygonIndex, 2, new Vec2D(0.0, 1.0));
	obj.setUVCoord(polygonIndex, 3, new Vec2D(1.0, 1.0));
	obj.setUVCoord(polygonIndex, 0, new Vec2D(1.0, 0.0));
}

This results in the following crash log:

Code:
Exception:  EXC_BAD_ACCESS (0x0001)
Codes:      KERN_PROTECTION_FAILURE (0x0002) at 0x00000000

Thread 0 Crashed:
0   de.wengenmayer.MWM             	0x01166af8 JS_GetPrivate + 40
1   de.wengenmayer.MWM             	0x01123590 PolyCore_setUVCoord + 472
2   de.wengenmayer.MWM             	0x011d9bb0 js_Invoke + 3180
3   de.wengenmayer.MWM             	0x011e86a8 js_Interpret + 56172
4   de.wengenmayer.MWM             	0x011d9c44 js_Invoke + 3328
5   de.wengenmayer.MWM             	0x011da058 js_InternalInvoke + 364
6   de.wengenmayer.MWM             	0x0116c054 JS_CallFunctionName + 120
7   de.wengenmayer.MWM             	0x01112874 -[MWMBaseObject performAction:] + 220
8   de.wengenmayer.Cheetah3D       	0x0002ab40 -[mwPropViewButton updateMassage:] + 64 (mwPropViewButton.m:102)
9   com.apple.AppKit               	0x93725a20 -[NSApplication sendAction:to:from:] + 108
10  com.apple.AppKit               	0x93725954 -[NSControl sendAction:to:] + 96
11  com.apple.AppKit               	0x93725834 -[NSCell _sendActionFrom:] + 156
12  com.apple.AppKit               	0x9373f84c -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 1020
13  com.apple.AppKit               	0x9373f434 -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 564
14  com.apple.AppKit               	0x9373ee58 -[NSControl mouseDown:] + 536
15  com.apple.AppKit               	0x936e0660 -[NSWindow sendEvent:] + 4616
16  com.apple.AppKit               	0x936896f4 -[NSApplication sendEvent:] + 4172
17  com.apple.AppKit               	0x93680b30 -[NSApplication run] + 508
18  com.apple.AppKit               	0x93771618 NSApplicationMain + 452
19  de.wengenmayer.Cheetah3D       	0x00003400 main + 1080 (main.m:60)
20  de.wengenmayer.Cheetah3D       	0x00002824 _start + 340 (crt.c:272)
21  de.wengenmayer.Cheetah3D       	0x000026cc start + 60

Let me know if there's anything I can do to help you track this down (or if it's just me being stupid and there's actually a non-crashing way to do this!).
 
Hi Neil,
sorry for the problem. Your script worked great after I fixed the bug you mentioned. So thanks for the bug report.

By,
Martin

P.S. I've mailed you a version of Cheetah3D which fixes the bug.
 
The version you sent me does indeed work fine. :)

Here's the updated script, which allows you to set the UVs of the selected quads to be a complete copy of the texture oriented in any of four directions:

Code:
//
// Coerce UVs.js
//

function buildUI(tool)
{
    tool.addParameterSeparator("Coerce UVs.js");
    tool.addParameterInt("First Vertex Index", 0, 0, 3, false, false);
    tool.addParameterButton("Apply","OK","apply");
}

function apply(tool)
{
	var obj = tool.document().selectedObject().core();

	var totalErrors = 0;

	for(index = 0; index < obj.polygonCount(); ++index)
	{
		if(obj.polygonSelection(index))
		{
			if(obj.polygonSize(index) != 4)
				++totalErrors;
			else
				coerceUVs(tool, obj, index);
		}
	}

	tool.document().selectedObject().update();

	if(totalErrors > 0)
		OS.messageBox("Coerce UVs", "" + totalErrors + " polygon" + (totalErrors == 1 ? " was" : "s were") +
			" ignored because they weren't quads.");
}

function coerceUVs(tool, obj, polygonIndex)
{
	firstVertexIndex = tool.getParameter("First Vertex Index");

	for(vertexIndex = 0; vertexIndex < obj.polygonSize(polygonIndex); ++vertexIndex)
	{
		switch((vertexIndex + firstVertexIndex) % 4)
		{
			case 0:
				obj.setUVCoord(polygonIndex, vertexIndex, new Vec2D(0.0, 0.0));
				break;
			case 1:
				obj.setUVCoord(polygonIndex, vertexIndex, new Vec2D(1.0, 0.0));
				break;
			case 2:
				obj.setUVCoord(polygonIndex, vertexIndex, new Vec2D(1.0, 1.0));
				break;
			case 3:
				obj.setUVCoord(polygonIndex, vertexIndex, new Vec2D(0.0, 1.0));
				break;
		}
	}
}

I'm going to refine this a bit further to allow for the extraction of tiles from a texture.

Incidentally, one other crash bug I encountered was caused by attempting to call .update() on a PolyCore (I meant to call it on the parent object). I also had a hang occur while experimenting with the script, but I haven't been able to track down the cause of that yet. I'll let you know if any other bugs show up.

Thanks a lot for your help!
 
In case it's of use to anyone, here's the completed script. It now has these features:
  • Can set all selected quads to a single copy of the entire texture.
  • Can set all selected quads to have a tile extracted from a tilemap texture.
  • Can rotate the UVs of all selected polygons (not just quads) in either direction.
  • Can set all vertices of all selected polygons to have a particular UV value, which is sometimes useful for making polygons a flat colour.
  • Has a margin setting to eliminate bleed between neighbouring tiles.
Read the script itself for instructions.

I'd be happy to hear any feedback or answer any questions about the script. Thinking about it, I might need to add the ability to reverse the order of the UVs for selected polygons. There are probably more things I could play with here. :)

Thanks again, Martin. This will solve a lot of problems with my game development projects.

I have one more request with regard to scripting... would it be possible to make scripts more easily accessible? Ideally, I'd like to be able to map them to keys in the preferences dialog or put them into the top toolbar as icons.
 

Attachments

  • polygon_uv_editor_587.zip
    2.3 KB · Views: 465
Hi Neil,
that is a very usefull script. I especially like the rotate UV function.

But you script requires Cheetah3D v2.6.1 so all other users should better wait til v2.6.1 is released. v2.6.1 will also fix a bug in the tool history which doesn't work in v2.6 .

The tool history ("Tool history backward" and "forward" hotkeys) can be used to jump between the last tools you used. In your case probably your UV script and the select tool.

By,
Martin

P.S. What type of models do you make for your game. I would be nice to have a game screenshot in the gallery forum. :wink:
 
Martin said:
The tool history ("Tool history backward" and "forward" hotkeys) can be used to jump between the last tools you used. In your case probably your UV script and the select tool.
Good point, that's probably the answer. For some reason, history backward doesn't seem to do anything and I have to press history forward several times before my script comes back, but it'll do for now. :) [EDIT: that's probably the bug you were talking about in the previous post!]

P.S. What type of models do you make for your game. I would be nice to have a game screenshot in the gallery forum.
This is a space shooter with rather stylised graphics, so the various spaceships are quite blocky and have deliberately simple textures. I still need to use my script to fix the UV mapping and textures on my models, but once they're looking nicer, I'll make sure I post an image!
 
I just realised that I had a couple of bugs in there. For one thing, the shortcut to assign the whole texture to every quad didn't work at all (I renamed a variable in some but not all places). Also, if it was doing a process which only worked on quads and it hit a non-quad, it would bail out instead of skipping it and going to the next quad. These are fixed now.
 

Attachments

  • polygon_uv_editor_123.zip
    2.3 KB · Views: 586
Hi NCarter,

Thanks for your contribution to the C3D community. I’m just starting to understand the basics of C3D and look forward to the time when I can use your script. Thanks again for your efforts.
 
help

i would like very much to use this script to assign one image texture to each polygon, but i cannot make it work.
can someone tell me please
- does this work in version 5.1 ?
- in wich script folder does it belong (i tried tool) ?
- what numbers have to be put in what boxes :redface: ?
(i have no idea what index, margin or uv-value mean)
thanks in advance

- archie
 
Back
Top