Thanks for the examples. I was mainly focussing on unfolding meshes, so I didn't saw them yet.
I would like to use the routine in a texpaint like painting program. Paintmesh is a Blitz3D example (I believe it was also written by birdie) where you can paint to the surface of an object.
In my program, I would like the users to load any .X or .3DS mesh available.
I noticed sometimes meshes have no texture coordinates. For instance the program LDraw exports its LEGO building blocks without texture coordinates.
I would like my program to generate texture coordinates in such a case, so the object could still be painted on.
Suppose a mesh is made out of paper. Then they could be unfolded to a flat surface. I would like to generate texture coordinates in that way, but my mathematical skills are a bit insufficient at this point.
I was thinking about single meshes. Unfolding an entire gamelevel would be cool, however my guess would be, complicated as well. Unfolding (or unwrapping?) single meshes would be quite a big step for me allready.
In the meanwhile, I tried to write a cubemapping routine.
I think it could also be a solution allready, however I am still interested in unfolding meshes. I believe this technique is called "unwrapping uwv" coordinates ? Some programs seem to be able to do this, but I would like to know how it's been done ?
Since birdies cubemapping example is not in the public domain, here is mine. One may use it in any form.
This code is yet unfinished. With more complicated meshes, it generates overlapping texture triangles. The idea is to translate the overlapping triangles to another part of the texture.
;---------------
;set up graphics
;---------------
Graphics3D 800, 600, 0, 3
SetBuffer BackBuffer()
;---------------------------
;load/create original object
;---------------------------
obj = CreateSphere()
UpdateNormals obj
;-------------
;set up camera
;-------------
camera = CreateCamera()
PositionEntity camera, 0, 0, -MeshSize(obj)
;--------------------
;create an empty mesh
;--------------------
mesh = CreateMesh()
;----------------------
;calculate cube mapping
;----------------------
For i = 1 To CountSurfaces(obj)
;create an empty surface
surf = CreateSurface(mesh)
;get an original surface
csurf = GetSurface(obj, i)
;reset min/max coords
minX# = 1000000
maxX# = -1000000
minY# = 1000000
maxY# = -1000000
minZ# = 1000000
maxZ# = -1000000
;determine min/max coords
For j = 0 To CountVertices(csurf) - 1
If VertexX(csurf, j) < minX Then minX = VertexX(csurf, j)
If VertexX(csurf, j) > maxX Then maxX = VertexX(csurf, j)
If VertexY(csurf, j) < minY Then minY = VertexY(csurf, j)
If VertexY(csurf, j) > maxY Then maxY = VertexY(csurf, j)
If VertexZ(csurf, j) < minZ Then minZ = VertexZ(csurf, j)
If VertexZ(csurf, j) > maxZ Then maxZ = VertexZ(csurf, j)
Next
;loop through all triangles of the selected surface
For j = 0 To CountTriangles(csurf) - 1
;get the 3 vertices from the selected triangle
v0 = TriangleVertex(csurf, j, 0)
v1 = TriangleVertex(csurf, j, 1)
v2 = TriangleVertex(csurf, j, 2)
;get the vertex normals
n0x# = VertexNX(csurf, v0)
n0y# = VertexNY(csurf, v0)
n0z# = VertexNZ(csurf, v0)
n1x# = VertexNX(csurf, v1)
n1y# = VertexNY(csurf, v1)
n1z# = VertexNZ(csurf, v1)
n2x# = VertexNX(csurf, v2)
n2y# = VertexNY(csurf, v2)
n2z# = VertexNZ(csurf, v2)
;calculate their average, to get the face normals
nx# = (n0x# + n1x# + n2x#) / 3
ny# = (n0y# + n1y# + n2y#) / 3
nz# = (n0z# + n1z# + n2z#) / 3
;calculate the dominant normal (front/back/left/right/top/bottom)
;determine direction or each normal
sx = (Sgn(nx) = 1)
sy = (Sgn(ny) = 1)
sz = (Sgn(nz) = 1)
;determine size of each normal
nx = Abs(nx)
ny = Abs(ny)
nz = Abs(nz)
;fs = face selected, the number determines if a face is front/back/left .. etc
fs = 1
If (nx >= ny) And (nx >= nz) Then fs = sx * 3 + 1
If (ny >= nx) And (ny >= ny) Then fs = sy * 3 + 2
If (nz >= ny) And (nz >= nx) Then fs = sz * 3 + 3
;calculate texture coords from vertex coords
;by scaling them in the range 0.0 - 1.0
tu0# = 1-((VertexX(csurf, v0) - minX#) / (maxX# - minX#))
tv0# = 1-((VertexY(csurf, v0) - minY#) / (maxY# - minY#))
tw0# = (VertexZ(csurf, v0) - minZ#) / (maxZ# - minZ#)
tu1# = 1-((VertexX(csurf, v1) - minX#) / (maxX# - minX#))
tv1# = 1-((VertexY(csurf, v1) - minY#) / (maxY# - minY#))
tw1# = (VertexZ(csurf, v1) - minZ#) / (maxZ# - minZ#)
tu2# = 1-((VertexX(csurf, v2) - minX#) / (maxX# - minX#))
tv2# = 1-((VertexY(csurf, v2) - minY#) / (maxY# - minY#))
tw2# = (VertexZ(csurf, v2) - minZ#) / (maxZ# - minZ#)
;create 3 new vertices
nv0 = AddVertex (surf, VertexX(csurf, v0), VertexY(csurf, v0), VertexZ(csurf, v0))
nv1 = AddVertex (surf, VertexX(csurf, v1), VertexY(csurf, v1), VertexZ(csurf, v1))
nv2 = AddVertex (surf, VertexX(csurf, v2), VertexY(csurf, v2), VertexZ(csurf, v2))
;apply the right texture coords to the face
Select fs
Case 1 ;left
VertexTexCoords surf, nv0, ((1-tw0#) / 3.0) + (0.0 / 3.0), (tv0# / 2.0) + (0.0)
VertexTexCoords surf, nv1, ((1-tw1#) / 3.0) + (0.0 / 3.0), (tv1# / 2.0) + (0.0)
VertexTexCoords surf, nv2, ((1-tw2#) / 3.0) + (0.0 / 3.0), (tv2# / 2.0) + (0.0)
Case 2 ;bottom
VertexTexCoords surf, nv0, ((1-tu0#) / 3.0) + (1.0 / 3.0), (tw0# / 2.0) + (0.5)
VertexTexCoords surf, nv1, ((1-tu1#) / 3.0) + (1.0 / 3.0), (tw1# / 2.0) + (0.5)
VertexTexCoords surf, nv2, ((1-tu2#) / 3.0) + (1.0 / 3.0), (tw2# / 2.0) + (0.5)
Case 3 ;top
VertexTexCoords surf, nv0, ((1-tu0#) / 3.0) + (2.0 / 3.0), (tv0# / 2.0) + (0.0)
VertexTexCoords surf, nv1, ((1-tu1#) / 3.0) + (2.0 / 3.0), (tv1# / 2.0) + (0.0)
VertexTexCoords surf, nv2, ((1-tu2#) / 3.0) + (2.0 / 3.0), (tv2# / 2.0) + (0.0)
Case 4 ;right
VertexTexCoords surf, nv0, (tw0# / 3.0) + (0.0 / 3.0), (tv0# / 2.0) + (0.5)
VertexTexCoords surf, nv1, (tw1# / 3.0) + (0.0 / 3.0), (tv1# / 2.0) + (0.5)
VertexTexCoords surf, nv2, (tw2# / 3.0) + (0.0 / 3.0), (tv2# / 2.0) + (0.5)
Case 5 ;top
VertexTexCoords surf, nv0, ((1-tu0#) / 3.0) + (1.0 / 3.0), ((1-tw0#) / 2.0) + (0.0)
VertexTexCoords surf, nv1, ((1-tu1#) / 3.0) + (1.0 / 3.0), ((1-tw1#) / 2.0) + (0.0)
VertexTexCoords surf, nv2, ((1-tu2#) / 3.0) + (1.0 / 3.0), ((1-tw2#) / 2.0) + (0.0)
Case 6 ;back
VertexTexCoords surf, nv0, (tu0# / 3.0) + (2.0 / 3.0), (tv0# / 2.0) + (0.5)
VertexTexCoords surf, nv1, (tu1# / 3.0) + (2.0 / 3.0), (tv1# / 2.0) + (0.5)
VertexTexCoords surf, nv2, (tu2# / 3.0) + (2.0 / 3.0), (tv2# / 2.0) + (0.5)
End Select
;make a triangle with the 3 created vertices
AddTriangle surf, nv0, nv1, nv2
;some debug output
Write fs + ","
tel = tel + 1
If tel > 20 Then tel = 0: Print
Next
Next
;--------------------------------------------------------------------------------------------------
; DEBUG II - show texcoords
;--------------------------------------------------------------------------------------------------
;debug pause
print
print "press any key"
Flip
FlushKeys()
WaitKey()
FlushKeys()
;hide original object
HideEntity obj
;----------------------------------
;draw texture + texcoords to screen
;----------------------------------
ClsColor 255, 255, 255
Cls
ClsColor 0, 0, 0
;img = LoadImage("c:\xfiles\kubus.bmp")
;DrawImage img, 0, 0
Color 0, 0, 0
For i = 1 To CountSurfaces(mesh)
surf = GetSurface(mesh, i)
For j = 0 To CountTriangles(surf) - 1
v0 = TriangleVertex(surf, j, 0)
v1 = TriangleVertex(surf, j, 1)
v2 = TriangleVertex(surf, j, 2)
tu0# = VertexU(surf, v0) * 512
tv0# = VertexV(surf, v0) * 512
tu1# = VertexU(surf, v1) * 512
tv1# = VertexV(surf, v1) * 512
tu2# = VertexU(surf, v2) * 512
tv2# = VertexV(surf, v2) * 512
Line tu0#, tv0#, tu1#, tv1#
Line tu1#, tv1#, tu2#, tv2#
Line tu2#, tv2#, tu0#, tv0#
Next
Next
Color 255, 255, 255
Text 0, 540, "Press any key"
Flip
WaitKey()
;----------------------------------------------------------------------------------------------------
; DEBUG II - show object
;----------------------------------------------------------------------------------------------------
;load texture
tex = Create6sidedTexture()
;texture new object
EntityTexture mesh, tex
;---------
;main loop
;---------
While Not KeyDown( 1 )
;turn new object
TurnEntity mesh, 0, 1, 0
RenderWorld
Flip
Wend
End
;----------------------------------------------------------------------------------------------------
; MeshSize()
;----------------------------------------------------------------------------------------------------
;returns either the depth, width or height of an object, accoording to which has the biggest value
Function MeshSize#( obj )
;check the 3 sizes of the given object
dd# = MeshDepth(obj)
hh# = MeshHeight(obj): If hh# > dd# Then dd# = hh#
hh# = MeshWidth(obj) : If hh# > dd# Then dd# = hh#
;limit the value
If dd# < 1.0 Then dd# = 1.0
Return dd
End Function
Function Create6sidedTexture()
oldbuffer = GraphicsBuffer()
tex = CreateTexture(256, 256)
SetBuffer TextureBuffer(tex)
font = LoadFont("Arial", 15)
SetFont font
Restore
For i = 0 To 2
For j = 0 To 1
Color Rand(127) + 127, Rand(127) + 127, Rand(127) + 127
Rect i * 85.333, j * 128, 85, 128
Read name$
Color 0, 0, 0
Text i * 85.333 + 42.833, j * 128 + 64, name$, True, True
Next
Next
SetBuffer oldbuffer
Return tex
End Function
Data "Left", "Right", "Top", "Bottom", "Front", "Back"