I am stuck on something I thought would be trivial. I am trying to take the UVW of a face and format it into a specific structure to be exported as what is called Brush (or World) Geometry in the Source Game Engine.
A little background: I already have code for exporting Models that map each vertices UVW, so I already know how to get that kind of UVW data; the problem is with these world brushes because I cannot figure out how to translate the data I know how to get into the correct code for the world brushes (which does not map each vertex).
As I understand it, the brush geometry gets its UVW for each face from two lines of code that look like this:
“uaxis” “[1 0 0 0] 0.25”
“vaxis” “[0 1 0 0] 0.25”
Here is the documentation on this subject in the Valve Wiki ( https://developer.valvesoftware.com/wiki/VMF_documentation#U.2FV_Axis ):
The u-axis and v-axis are the texture
specific axes. They hold their own designations as they are independent of the
true x-axis and y-axis, but it’s easier to think of them in terms of x and y.
The u-axis represents the x-axis and the v-axis represents the y-axis. These two
code lines work together to define how the texture is displayed upon a face.
“uaxis” “[1 0 0 0] 0.25”
“vaxis” “[0 1 0 0] 0.25”
u/v axis ([x y z dec] dec)
The x, y, and z are decimal values representing that axis. The following value is the translation and the last decimal is the total scaling. The values for the x y z set represent the amount of the texture to be shown in that axis. They modify how much of the texture is shown within the normal space the texture would occupy on the face. A value of one means one repetition in the normal space, a value of two would mean two repetitions in the normal space. The key is that this only applies to one axis of the texture and is applied relative to true x, y, and z axes. That means that it is possible to set the texture to appear along an axis the plane doesn’t exist in. With a flat plane in the x-axis and the y-axis definitions are only needed for those axes as any definition in the z-axis has no surface to appear on. The code sample shows how this would be generated by Hammer. The texture’s x-axis (the u-axis) is displayed in the real x-axis and the texture’s y-axis (v-axis) is displayed in the real y-axis. Which of the x, y, and z axes are showing the axes of the texture depends entirely upon the faces orientation. Negative values will flip textures and Hammer will generate errors about textures shown in a plane the surface does not occupy. The second to last value is the simple translation of the textures origin within that axis; this value is actually a decimal though Hammer will round it up when displaying Hammer will still save the correct
decimal value. The last decimal is the overall scaling of the entire axis including what is defined in the x y z group.
I have tried various formulas that follow this logic:
brushGeometry = ConvertToPoly (Box mapcoords:on) for faceIndex = 1 to brushGeometry.numfaces do ( face = polyop.getFaceVerts brushGeometry faceIndex in coordsys world ( vert1 = polyop.getVert brushGeometry face node:brushGeometry vert2 = polyop.getVert brushGeometry face node:brushGeometry vert3 = polyop.getVert brushGeometry face node:brushGeometry ) tvertFace = polyop.getMapFace brushGeometry 1 faceIndex tv1 = polyop.getMapVert brushGeometry 1 tvertFace tv2 = polyop.getMapVert brushGeometry 1 tvertFace tv3 = polyop.getMapVert brushGeometry 1 tvertFace format "################### " /* I've tried both using the Verts... */ vaxis = normalize (vert2-vert1) uaxis = normalize (vert2-vert3) format "Face % U axis using Verts: % " faceIndex vaxis format "Face % V axis using Verts: % " faceIndex uaxis /* And I've tried using the Texture Verts */ vaxis = normalize (tv2-tv1) uaxis = normalize (tv2-tv3) format "Face % U axis using Texture Verts: % " faceIndex vaxis format "Face % V axis using Texture Verts: % " faceIndex uaxis /* And I've tried various random combinations of which verts to subtract to create the axis. None have consistently created the correct axis when viewed in Hammer/Source */ )
I haven’t even yet tried to tackle the Translation and Scaling parameters in the output string for each axis as I can’t even get the U/V axises correct.
The problem has been getting more difficult because I am trying to make it so that whatever you see on a face in Max is how it exports into Source. And as I was struggling (unseccessfully) with the above problem, I also realized that I need to account for not only the actual UVW on the face, but any offsetting that is going on inside the texture–for example, if the Material on the Face has a Bitmap texture that is using the UVW Angles, Offset and Tiling.
Once I realized that I need to account for that, I started to think that the Angles, Offset and Tiling in the uaxis/vaxis are directly related to the texture’s coordinates (in the material editor) I started to think that my solution has to be something like this to output for the Source VMF format:
Get the X/Y Axis of the Face
Offset that by the UVW of the face
Offset that by the Materials Texture coordinates
Also get the Translation and tiling from the combined UVW/texture UVW
I may be wrong about that. But that is what I am thinking right now.
I am going to continue to experiment. But my personal problem is that although I have plenty or programming experience and can understand logic well… my math skills are weak. I have trouble thinking mathematically… and all of the matrix/vector aspect of this is extremely difficult and confusing for me. I’ve written to Valve for some help, but I’m not holding my breath in the meantime.
Any help would be greatly appreciated. I’ve mentioned my problem to several extremely smart MaxScript and SDK coders, and I am not actually the only one scratching my head–which is bad because I shouldn’t be doing anything to make my hair any thinner!