Today the journey continues with texture alignment and UV mapping. I left off with larger sculptured prims mapping texture to every other cell when using a grid. This may be related to how sculptured prims skip every other pixel to get vertices. It could also be that I might not supposed to be reading more than 33 vertices in a row/column to begin with, regardless of size.
I also want to address the odd behavior of controlling the camera since I changed the camera.up values to address the tilted view of the top and bottom camera angles. In addition, I need to figure out how to setup the camera angles properly to show the models actual front, back, left, right, top, and bottom sides.
Camera Angle
Let’s look at the reference cube since its the simplest element in the scene. Looking at it with various camera angles, I found one where it was at a 45 degree angle, a bit short, and I had to zoom out to see it. I had made some calculations so that the camera would fit the model within its view, but I didn’t expect the ratio to be anything other than 1:1.

Before we get to that, I set the camera up vector to the default 0, -1, 0 to get normal camera controls working to orbit the model. Everything looked almost normal except the top and bottom camera views, which led me down to changing the camera up vector in the first place. I still had to zoom out to see the shapes.

I tried increasing the distance, multiplying the largest height, width, and depth from 2 to 3 without any changes. Since the control vertices mesh now fits with the cube, I decided to get the bounds from the cube instead of the model. This resulted in all camera angles to show the cubes edges as vertical and horizontal without rolling the camera view.
Next is the ratio. The cube is taking up the full screen, stretching out to be wider than it is high. This has to do with how the orthographic camera was setup in order to focus in on the object. Changing the frustum length to use the canvas dimensions, the object couldn’t be seen unless you zoomed into the scene. I needed to take the max of the size x, y, or z and apply the canvas’s ratio.
const max = Math.max(size.x, size.y, size.z); const ratio = canvasWidth / canvasHeight; const frustumWidth = max * ratio; const frustumHeight = max; camera = new THREE.OrthographicCamera( frustumWidth / -2, frustumWidth / 2, frustumHeight / 2, frustumHeight / -2, 1, 1000 );

Progress.
Orbital Controls
As I looked at each scene, I noticed that the orbital controls behaved differently as I dragged my mouse left and right. Some scenes would rotate the model in the opposite direction on a vertical axis, while others appeared to roll the camera itself.
Research led me down the path to change the cameras rotate speed direction based on if the camera is looking up or down. You do this by applying the cameras quaternion to a vector of 0, 0, -1, look at a dot and determine if the camera is looking in the wrong direction. Got all of that? I sure didn’t. Here is the code after a bit of refactoring…
if(controls) controls.dispose(); // create controls with correct rotation behavior controls = new OrbitControls( camera, domElement ); const direction = new THREE.Vector3(0, 0, -1); // align direciton with camera rotation direction.applyQuaternion(camera.quaternion); // direction and cammera up vector pointing in opposite directions? const reverse = direction.dot(camera.getWorldDirection(up)) < 0; // correct rotation behavior controls.rotateSpeed *= (reverse ? -1 : 1);
Well, guess what? None of that was needed. I moved the controls into its own function to ensure a separation of concerns. I realized that the original OrbitControls had been set prior to setting the cameras position and where it was looking. As long as the orbit controls were created after the camera was positioned and rotated, the extra code to correct the rotation is unnecessary.
Camera Direction
Now let’s move onto the direction. Are we really looking at the front, back, left, right, top, and bottom of a cube? I need visual confirmation. Lets put some text on that cube.
I quickly learned that the order of faces in a cuboid is a standard in most 3d modeling applications. It goes in the order of right, left, top, bottom, front, back. I started with a simple image to display the text and found that every camera angle I clicked on matched the corresponding side. The right and left seemed reversed when I looked at the isometric view.


Now I’m a bit confused. The left and right camera views are showing the correct texture stating “Left” and “Right”. If I swap the two textures, the camera angles are no longer correct, and the ordering of faces is non-standard.
After looking throughout the web, I found that I’m thinking from the wrong perspective. I know my right hand from my left hand. From a scene, geometry is about the coordinates. Right and Left are based on the x axis. It seems ambiguous. If I draw a cube on paper in an isometric view, its easier to say look at the right side – and from our perspective, we are the camera. We see the right side is to the right side of the paper. We are not viewing the cubes right side from the cubes perspective.
In this case, the mapping of textures are correct, and the camera angles are correct. Let’s give the cube some shading and make the textures pretty.

Geometry Position
With the camera angles now verified to be correct, it was now confirmed that my imported model was not in an upright position.






When I was originally designing the UFO in Rokuro, the view I saw was what I currently see in the top view. An upright UFO with a pointy top. However, maybe the generated sculptured prim image is different. The way to find out is to create a new object in second life, apply the sculptured texture, and look at the objects orientation in the world.
I logged in, created a cube, changed it to a sculpted prim, and applied my mesh. The results were interesting. It was upside down. Still – it circled the z axis.

I decided to take a look at the default texture mapping as well. Sure enough, it had its own issues. It had to be rotated 90° counterclockwise to appear correctly.
Now I have some confirmation regarding why the original UFO skin textures in my web page UFO models appear rotated 90 degrees.
Since the mapping rotation is fine, I need to determine what is going on with the orientation. When loaded, the UFO should appear upside down. Again, I am thinking that I am reading the models vertices in the wrong order, or that I’m mapping the colors individual RGB values to the wrong XYZ vectors.
I checked to see what the coordinate system was in both engines. Both Three.js and the Second Life viewer use a right-handed Cartesian coordinate system. The x-axis points to the right, the y-axis points up, and the z-axis points forward. This system is standard across 3D applications.
I reviewed where I mapped each pixel to a vertex. I changed the mapping of XYZ to GBR instead of RGB. The UFO appeared upside down on the front, left, right, and back angles. It almost worked when mapping XYZ to RBG as well, but the normals were inside out.
controlVertices.push({
color,
x: mapCv(g),
y: mapCv(b),
z: mapCv(r)
})
UV Texturing
The camera angles are correct. The camera controls are fixed. The model is loaded in the correct orientation. Lot’s of progress. Now I can get back to the “real” problem of texturing. As I reminder, I have been working on texturing the full day yesterday. I got far, but I still had problems. The main one being that on the UFO model, only a quarter of larger textures were being applied that I could see, and smaller textures looked choppy and blurry.


I started playing with the UV mapping. Maybe I was skipping something. I knew there was some logic multiplying a few things by two. Reviewing the code, I was just multiplying the geometries position count by two for the UV array that needed two elements for each position. That was a dead end. An attempt to reverse the UV values and order yielded to issues with mirrored textures. Attempting to change the segment counts resulted in the texture looking odd.


Since other models look fine, the UV mapping seems like it is correctly implemented. Maybe I should be skipping more pixels when reading larger sculpted prim images. Could it be that the extra pixel values are the same as the used pixel? If that were the case, those faces wouldn’t show up since they reside at the same points.
Downsampling Models
I started looking at how I read control vertices. I moved the logic to determine if a pixel was a control vertex into a separate function and started to hard code the logic to force 32 segments horizontally and vertically, and skip every odd, and every 3rd pixel out of four to reduce the number of vertices read. The low resolution texture displayed perfectly without skipping cells.


Looking at the two images, I’m not seeing a difference in the placement of vertices. Each texture cell (ie H06 in the images) has 25 vertices along the edges and center. This is revealing that there may have been duplicate vertices and faces that were either overlapping other faces, or simply too thin to see. This means that larger images for sculpted prims have a lot more wasted space of unused pixels. I’d like to eventually see a graphical representation of what pixels are and are not used in sculpted prim images.
The hard coded logic breaks all of the models except those using 64×64 images. Now I need to determine which pixels to skip based on image size. I’ve got many varieties of image sizes.
| width | 16 | 32 | 64 | 128 | 256 |
|---|---|---|---|---|---|
| square | 64 | 128 | 256 | ||
| rectangle | 256 | 128 | 32 | 64 | |
| rectangle | 512 |
It seems like every other column, ad the last column is the base to work with. Once we start working with dimensions greater than 64 pixels, we tend to skip every 3 of 4 rows. I suspect with the larger 256 images it may also be every 5 of 8, and every 6 of 16 for 512. However, non-square shapes were supported at a later time in Second Life and may have different rules in how to pull the vertices out.
Doing a bit of research, I found that sculpted prims are limited to 1,000 vertices in the Sculpted Prims FAQ to keep the rendering weight similar to that of a torus prim available in the Second Life Viewer. My UFO is now using 1,056 vertices which is fairly close. I also found some sample Sculpt Map and Textures on the wiki as well.
What I ended up doing was creating a loop to downsample the segments if they would result in 1024 vertices or more (not including the hidden column for stitching). I would get the maximum of both the horizontal and vertical segments, divide by half, and increment the downsampling values. Once I knew how far each dimension was downsampled, I would exclude downsampled pixels. Here is some code that I created to ignore downsampled pixels.
for(let i = 1; i <= horizontalDownsample; i++) {
if(columnIndex % Math.pow(2, i+1) === i * 2) return false;
}
for(let i = 1; i <= verticalDownsample; i++) {
if(rowIndex % Math.pow(2, i+1) === i * 2) return false;
}
The results were that all models were intact and displayed textures correctly. One of the challenging textures was the overlook 4 model. It was a narrow 32×512 image. It had its vertical segments downsampled twice while preserving the original horizontal segments. I suspect this will come in handy at a later time when working with level of detail (LOD).

Revealing Vertices
As an added feature, I added the ability to toggle unused pixels to be blacked out in the sculpted prim unless it was used as a vertex in the model before I started reading the image data. It gives a better understanding of how much of the image is wasted – especially for larger images where downsampling occurs.



Overlook 4 Sculpt

Overlook 4 Vertices
Stitching
With all of the work getting textures to work, I still have another problem. Stitching from left to right. The lowest resolution texture shows a multi colored line where the two edges should meet. A higher resolution texture shows many lines.


Are we back to a UV vector issue? We have a “hidden” column that this could be a part of. Adding 1 to the horizontal segments for UV mapping just twisted the texture, and the line still remained. I tried adding 1 to the vertical segments as well, but it appeared to have the same effect.

After restoring the UV code I went into my function to determine if a control vertex can be read. Perhaps that last column could be causing trouble. I made it so that you couldn’t read the last column, and it gave me the same twisted texture.
Instead of reading the last pixel in the row, I tried reading the first pixel instead, to truly wrap around to the vertices at that specific location. The line remained and none of the models broke. Eliminating an additional column of pixels just increased the amount of unused space in the image.
Turning on vertices and zooming in, the line is the exact width of the last set of vertices. Another problem I found was that the first row of quads at the top of the model appear to be twisted. I think the two issues may be related somehow.


The first cell from the texture prefixed with “A” is only using 20 vertexes instead of 25. Something is going on with the first column of vertices not being represented in the UV map properly.
I’ve been taking various approaches to UV mapping, and even reducing the number of faces at the poles. I haven’t been getting anywhere with much progress. I need a control sample to test what I’m doing. Something like a basic cube for starters. From there, I can progress to another cube that has distinct shapes in it so that I can discern the top, left, right, front, back, and bottom. Time to make a sculpted prim.
Let’s look at a few of the resident made tools on the Second Life Wiki.
- SculptPot Viewer – website appears to be malware
- AvPainter – in-world computer fails to get registration
- Rokuro Pro – Serial box still works. Software only works on windows…
- Cel_Sculptpreview – looks like we have some source code for mac…
- uses sculpty paint 2 in a browser. Promising!
- A Hacky Sculpt Previewer – broken link
- Sculptaire – source forge/windows.
- SIEE (Sculptie Importer Exporter and Editor) – offline wordpress site
- XNA Sculptpreview – broken link
- Texture Wizard – broken link
- LandSculptor – broken link
- LD Sculpty Protect – broken. Links to old xstreetsl website
- LD Sculpty Shrink – same
- Math Sculptor – broken link
- PloppSL – Broken link
- SculptCrafter – region no longer exists
- Sculpted Sim Terrain Mapper – broken link on sl exchange
- Sculpt Studio – found in marketplace. in-world tool for 4,999 L$ (15.62 US$)
- Sculpty Hider – Broken link
- sculpty.php – Broken link
- Sculpty Paint – Windows/Linux/MacOSX. Doesn’t work with my version of macOS Sonoma 14.2.1.
- SnurbO’Matic – Broken link. I have the alpha and beta models in my inventory, but it needs 1100 primitives. From what I recall, it makes a ton of spheres representing each vertex in the shape of a sphere, and you move them into position of the model you want. Then it gave you a link to download the file from a website.
- Sim Terrain Surveyor – broken link
- Tatara – Only have license for 6.0. Latest is 7.292. Looks like there is a mac version now. In-world shop only has windows for new users at 4,750 L$. Mac version not compatible with macOS Sonoma 14.2.1
- Tokoroten – extruder software for windows
- obj2sculpt – missing attachment. Looks like membership is required to look for it on DeviantArt
- raw2sculpt.html – a javascript version. don’t have any terrain files to play with.
- Sculpty Maker – broken link
SL Image UploadGridImageUpload – broken links to installer and source code repositories- Advanced Sculptie Exporter from Maya – has a mel script for Maya.
- redcap – software link broken. ruby source code available, but primarily for uploading images to second life. Nothing regarding sculpty generation.
- Prim Oven was an in-wold tool used to position 16 cubes or cylinders to position, rotate, and resize into a desired shape. It then created HTML code in chat that would result in a 16×256 sculpted prim image. It still works today. This is why the “16 Steps Floating” model has only 16 steps.
- A19 Sculpt Maker appears to be another in-world builder similar to snurbO’Matic in that you positioned spheres. It was unique in that you attached a few objects to your HUD to display the sculpted image and take a screen shot of it. It simulated a wireframe between the spheres using particles.
So far the few things I found that may be of most help is A19 Sculpt Maker, Snurbo’matic, Prim Oven, and Tatara. I’ve got a few constraints on prim usage on my parcel, so the software route is the way that I need to go. I’ll need to switch over to another computer to see if I can get anything up and running.
I installed a few apps on the windows computer. Tatara seems to be the best app by far for what I am looking for, but version 6 is plaged with memory address errors. Installing version 7 didn’t have any errors, but I would have to find a way to upgrade it, or purchase the full version as a new user for 4,750 L$ (roughly $15.50 in US currency). The website says “ROKURO Pro 3.0 Users can upgrade to TATARA 7.0.”. I’m going to see if my license key for Rokuro Pro 3.0 works… Nope. It looks like I’ll have to head back to their in-world shop and look for the serial box again to upgrade.

The store is located in the Phasic Foo region at coordinates 45, 28, 24. It has a bunch of Tatara 7 boxes with floating text above them for each plugin to purchase separately. On the side, I found the serial box for new users. Walking around every level of the store, nothing else could be found for existing users of Tatara 6 or Rokoru Pro 3 to upgrade. I don’t like buying stuff at full price when the documentation says there is a way for existing users to upgrade.


I made a few test sculpties, updated my little project, and the new models wouldn’t load. No errors. I suspect it’s because the file format is TGA. I found an online converter to change the file format to PNG. Once I loaded up a simple cube, I started to notice something about the last cell with the weird line. It’s actually a reverse of all the cells in the same row going from H3 to A3.

It’s late. Here is the daily recap with commentary.


