forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   3D-программирование (http://forum.boolean.name/forumdisplay.php?f=108)
-   -   MD2 Loader под MiniB3D (http://forum.boolean.name/showthread.php?t=18546)

Кирпи4 18.09.2013 18:53

MD2 Loader под MiniB3D
 
Сап булка.
Очень уж я подружился с максом, и ещё сильнее с minib3d. И тут народ захотел увидеть в SpriteBoy (а плеер под него написан именно на максе) модельки хотя бы в MD2. Ну а кто я такой, чтобы им отказать? :-D

Лоадер был написан, но при загрузке и построении меша происходит какая то неведомость с текстурными координатами. Для примера сравните:

Блицевский LoadMD2


Моё творение


Как видно, на бошке, на левой бицухе и по бокам ног есть ошибка UV. Я обрыскал весь код вдоль и поперёк, проверил UV, но всё видимо в порядке. Очень надеюсь на вашу помощь.

Код загрузчика (минибздун для работы обязателен)
Код:

Rem
        bbdoc:Undocumented type
End Rem

Function MD2Interp:Float(x1:Float, x2:Float, trans:Float)
        Return x1 + ((x2-x1)*trans)
End Function

Type TMD2Vert
        Field x:Float, y:Float, z:Float
End Type

Type TMD2Tri
        Field vert:Int[3]
        Field tex:Int[3]
End Type

Type TMD2TexCoord
        Field u:Double
        Field v:Double
End Type

       
Type TMD2Frame
        Field Name:String
        Field Scale:Float[3]
        Field Trans:Float[3]
        Field Surf:TSurface
        Field Vertices:TMD2Vert[]
End Type

Const _MAGIC:Int = 0
Const _VERSION:Int = 1
Const _SKIN_WIDTH:Int = 2
Const _SKIN_HEIGHT:Int = 3
Const _FRAME_SIZE:Int = 4
Const _COUNT_SKIN:Int = 5
Const _COUNT_VERTEX:Int = 6
Const _COUNT_TEXCOORD:Int = 7
Const _COUNT_TRIS:Int = 8
Const _COUNT_OGLCOM:Int = 9
Const _COUNT_FRAME:Int = 10
Const _OFF_SKIN:Int = 11
Const _OFF_TEXCOORD:Int = 12
Const _OFF_TRIS:Int = 13
Const _OFF_FRAME:Int = 14
Const _OFF_OGLCOM:Int = 15
Const _OFF_EOF:Int = 16

Const MD2_UseInterpolation:Int = 1


Type TMD2' Extends TEntity
        Global md2s:TList = CreateList()

        Field file:TStream
        Field mesh:TMesh
        Field surf:TSurface
        Field header:Int[17]
        Field frames:TMD2Frame[]
        Field tris:TMD2Tri[]
        Field coords:TMD2TexCoord[]
       
        Field anim_mode:Int
        Field anim_bounds:Int[2]
        Field anim_spd:Float
        Field anim_pos:Float
        Field anim_interp:Float
       
        Method UpdateFrame()
                ' Calculating interpolation
                Local interp:Float = Self.anim_pos - Floor(Self.anim_pos)
                Local fr1:Int = Floor(Self.anim_pos)
                If fr1 < Self.anim_bounds[0] fr1 = Self.anim_bounds[1]
                Local fr2:Int = fr1 + 1
                If fr2 > Self.anim_bounds[1] fr2 = Self.anim_bounds[0]
                If MD2_UseInterpolation
                        For Local i:Int = 0 To Self.surf.CountVertices() - 1
                                Local x:Float[2], y:Float[2], z:Float[2]
                                x[0] = Self.frames[fr1].Vertices[i].x
                                y[0] = Self.frames[fr1].Vertices[i].y
                                z[0] = Self.frames[fr1].Vertices[i].z
                                x[1] = Self.frames[fr2].Vertices[i].x
                                y[1] = Self.frames[fr2].Vertices[i].y
                                z[1] = Self.frames[fr2].Vertices[i].z
                                Self.surf.VertexCoords(i, MD2Interp(x[0], x[1], interp), MD2Interp(y[0], y[1], interp), MD2Interp(z[0], z[1], interp))
                        Next
                Else
                        For Local i:Int = 0 To Self.surf.CountVertices() - 1
                                Self.surf.VertexCoords(i, Self.frames[fr1].Vertices[i].x, Self.frames[fr1].Vertices[i].y, Self.frames[fr1].Vertices[i].z)
                        Next
                EndIf
        End Method
       
        Method StartAnim(st:Int, en:Int, spd:Float, md:Int, trans:Float)
                Self.anim_bounds[0] = st
                Self.anim_bounds[1] = en
                Self.anim_pos = Self.anim_bounds[0]
                Self.anim_spd = spd
                Self.anim_mode = md
                Self.anim_interp = trans
        End Method
       
        ' Funcs
        Function LoadMD2:TMD2(path:String, parent:TEntity = Null)
                Local f:TStream = ReadStream(path)
                If Not f Return Null
                Local m:TMD2 = New TMD2
               
                ' Header
                For Local i:Int = 0 To 16
                        m.header[i] = ReadInt(f)
                Next
               
                If m.header[_VERSION] <> 8
                        CloseStream f
                        Return Null
                EndIf
               
                ' Frames
               
                SeekStream(f, m.header[_OFF_FRAME])
                m.frames = New TMD2Frame[m.header[_COUNT_FRAME]]
                For Local I:Int = 0 To m.header[_COUNT_FRAME] - 1
                        Local Fr:TMD2Frame = New TMD2Frame
                        Fr.Scale[0] = ReadFloat(f)
                        Fr.Scale[1] = ReadFloat(f)
                        Fr.Scale[2] = ReadFloat(f)
                        Fr.Trans[0] = ReadFloat(f)
                        Fr.Trans[1] = ReadFloat(f)
                        Fr.Trans[2] = ReadFloat(f)
                        Fr.Name = ReadString(f, 16)
                        Fr.Vertices = New TMD2Vert[m.header[_COUNT_VERTEX] ]
                        For Local V:Int = 0 To m.header[_COUNT_VERTEX] - 1
                                Local Temp:TMD2Vert = New TMD2Vert
                                Temp.x = Float((ReadByte(f) * Fr.Scale[0]) + Fr.Trans[0])
                                Temp.y = Float((ReadByte(f) * Fr.Scale[1]) + Fr.Trans[1])
                                Temp.z = Float((ReadByte(f) * Fr.Scale[2]) + Fr.Trans[2])
                                ReadByte(f) ' Skip Normal Index
                                Fr.Vertices[V] = Temp
                        Next
                        m.frames[i] = Fr
                Next
               
                ' Triangles
               
                SeekStream(f, m.header[_OFF_TRIS])
                m.tris = New TMD2Tri[m.header[_COUNT_TRIS] ]
                For Local I:Int = 0 To m.header[_COUNT_TRIS] - 1
                        Local T:TMD2Tri = New TMD2Tri
                        T.vert[2] = ReadShort(f)
                        T.vert[1] = ReadShort(f)
                        T.vert[0] = ReadShort(f)
                        T.tex[2] = ReadShort(f)
                        T.tex[1] = ReadShort(f)
                        T.tex[0] = ReadShort(f)
                        'Print T.VIndex[0] + " : " + T.VINDEX[1] + " : " + T.Vindex[2]
                        m.tris[i] = T
                Next
               
                ' Tex Coords
               
                SeekStream(f, m.header[_OFF_TEXCOORD])
                m.coords = New TMD2TexCoord[m.header[_COUNT_TEXCOORD] ]
                For Local I:Int = 0 To m.header[_COUNT_TEXCOORD] - 1
                        Local T:TMD2TexCoord = New TMD2TexCoord
                        T.U = Float(ReadShort(f)) / Float(m.header[_SKIN_WIDTH])
                        T.V = Float(ReadShort(f)) / Float(m.header[_SKIN_HEIGHT])
                        m.coords[i] = T
                Next
               
                ' Building mesh
                m.mesh = CreateMesh(parent)
                m.mesh.EntityFX(3 + 8)
                Local surf:TSurface = m.mesh.CreateSurface()
                m.surf = surf
                For Local v:TMD2Vert = EachIn m.frames[0].Vertices
                        surf.AddVertex(v.x, v.y, v.z)
                Next
                For Local fr:TMD2Frame = EachIn m.frames
                       
                        Local sr:TSurface = CreateSurface(m.mesh)
                        For Local v:TMD2Vert = EachIn fr.Vertices
                                sr.AddVertex(v.x, v.y, v.z)
                        Next
                Next
               
                For Local t:TMD2Tri = EachIn m.tris
                        surf.AddTriangle(t.vert[0], t.vert[1], t.vert[2])
                        surf.VertexTexCoords(t.vert[0], m.coords[t.tex[0] ].u, m.coords[t.tex[0] ].v)
                        surf.VertexTexCoords(t.vert[1], m.coords[t.tex[1] ].u, m.coords[t.tex[1] ].v)
                        surf.VertexTexCoords(t.vert[2], m.coords[t.tex[2] ].u, m.coords[t.tex[2] ].v)
                       
                Next
               
               
                md2s.AddLast(m)
                Return m
        EndFunction
       
        Function UpdateMD2(spd:Float = 1)
                Local m:TMD2
                For m = EachIn TMD2.md2s
                        Local inview:Int = 0
                        For Local c:TCamera = EachIn TCamera.cam_list
                                If c.Hidden() = 0
                                        If c.EntityInView(m.mesh)
                                                inview = 1
                                                Exit
                                        End If
                                End If
                        Next
                        If m.anim_mode > 0 And m.anim_spd <> 0 And inview
                                m.UpdateFrame()
                                If m.anim_interp <> 0
                                       
                                Else
                                        m.anim_pos:+(spd * m.anim_spd)
                                        Select m.anim_mode
                                                Case 1
                                                        If m.anim_spd < 0
                                                                If m.anim_pos <= m.anim_bounds[0] m.anim_pos = m.anim_bounds[1]
                                                        Else
                                                                If m.anim_pos >= m.anim_bounds[1] m.anim_pos = m.anim_bounds[0]
                                                        End If
                                                Case 2
                                                        If m.anim_spd < 0
                                                                If m.anim_pos < m.anim_bounds[0] m.anim_mode = 0
                                                        Else
                                                                If m.anim_pos > m.anim_bounds[1] m.anim_mode = 0
                                                        End If
                                               
                                        End Select
                                EndIf
                        End If
                Next
        EndFunction
       
       
End Type


Черный крыс 18.09.2013 19:21

Ответ: MD2 Loader под MiniB3D
 
да бывает такое. Я тоже как то писал загрузчики md2/md3

Там нужно очень хитро передавать указатель. Пороюсь в мусорке, если найду - выложу полностью рабочий загрузчик.

Кирпи4 18.09.2013 19:33

Ответ: MD2 Loader под MiniB3D
 
Если найдёшь - пожму руку

UPD: Хм, по-видимому с UV всё нормально, это они уже херово передаются в самого бздуна. Печаль века...

Черный крыс 18.09.2013 19:58

Ответ: MD2 Loader под MiniB3D
 
загрузчик остался в жостком который я снял....

Короче тама наскок я помню делал так :

1 ) закидывал в массив
2 ) передавал адрес указателя

вроде так :

PHP код:

Local uv#[2]

glTexCoords2fv(VarPtr Float Ptr(uv[0]), VarPtr Float Ptr(uv[1])) 

Или вроде так

PHP код:

glCoordsv(VarPtr Float Ptr(uv)) 


Кирпи4 19.09.2013 01:04

Ответ: MD2 Loader под MiniB3D
 
Дьябло, ты извращенец =D

А если по теме: автэ оч сильно помог, практически указал на ошибку. Всё дело оказалось в том, что формат по несколько раз использует одни и те же вершины, задавая им разные UV. Так как в своё время ни VBO, ни каких то других фенечек не было, всё рисовалось через glBegin-glEnd. Собственно, вертексы в их существенном понимании отсутствовали и нигде не хранились, задаваясь каждый раз по новой. Поэтому пришлось немного подкостылить, заимев на каждый MD2-вертекс TList, который содержит реальные айди вершин-двойников этого вертекса.

Анимации ещё надо сильно допиливать.

Код:

Rem
        MD2 Loader
End Rem

Function MD2Interp:Float(x1:Float, x2:Float, trans:Float)
        Return x1 + ((x2-x1)*trans)
End Function

Type TMD2Vert
        Field x:Float, y:Float, z:Float
End Type

Type TMD2BlitzVert
        Field tris:TList
End Type

Type TMD2Tri
        Field vert:Int[3]
        Field tex:Int[3]
End Type

Type TMD2TexCoord
        Field u:Double
        Field v:Double
End Type

       
Type TMD2Frame
        Field Name:String
        Field Scale:Float[3]
        Field Trans:Float[3]
        Field Vertices:TMD2Vert[]
End Type

Const _MAGIC:Int = 0
Const _VERSION:Int = 1
Const _SKIN_WIDTH:Int = 2
Const _SKIN_HEIGHT:Int = 3
Const _FRAME_SIZE:Int = 4
Const _COUNT_SKIN:Int = 5
Const _COUNT_VERTEX:Int = 6
Const _COUNT_TEXCOORD:Int = 7
Const _COUNT_TRIS:Int = 8
Const _COUNT_OGLCOM:Int = 9
Const _COUNT_FRAME:Int = 10
Const _OFF_SKIN:Int = 11
Const _OFF_TEXCOORD:Int = 12
Const _OFF_TRIS:Int = 13
Const _OFF_FRAME:Int = 14
Const _OFF_OGLCOM:Int = 15
Const _OFF_EOF:Int = 16

Const MD2_UseInterpolation:Int = 1


Type TMD2' Extends TEntity
        Global md2s:TList = CreateList()

        Field file:TStream
        Field mesh:TMesh
        Field surf:TSurface
        Field header:Int[17]
        Field frames:TMD2Frame[]
        Field tris:TMD2Tri[]
        Field coords:TMD2TexCoord[]
        Field verts:TMD2BlitzVert[]
        Field skins:String[]
       
        Field anim_mode:Int
        Field anim_bounds:Int[2]
        Field anim_spd:Float
        Field anim_pos:Float
        Field anim_interp:Float
       
        Method UpdateFrame()
                ' Calculating interpolation
                Local interp:Float = Self.anim_pos - Floor(Self.anim_pos)
                Local fr1:Int = Floor(Self.anim_pos)
                If fr1 < Self.anim_bounds[0] fr1 = Self.anim_bounds[1]
                Local fr2:Int = fr1 + 1
                If fr2 > Self.anim_bounds[1] fr2 = Self.anim_bounds[0]
                If MD2_UseInterpolation
                        For Local i:Int = 0 To Self.header[_COUNT_VERTEX] - 1
                                Local x:Float[2], y:Float[2], z:Float[2]
                                x[0] = Self.frames[fr1].Vertices[i].x
                                y[0] = Self.frames[fr1].Vertices[i].y
                                z[0] = Self.frames[fr1].Vertices[i].z
                                x[1] = Self.frames[fr2].Vertices[i].x
                                y[1] = Self.frames[fr2].Vertices[i].y
                                z[1] = Self.frames[fr2].Vertices[i].z
                                Self.repositionVert(i, MD2Interp(x[0], x[1], interp), MD2Interp(y[0], y[1], interp), MD2Interp(z[0], z[1], interp))
                        Next
                Else
                        For Local i:Int = 0 To Self.header[_COUNT_VERTEX] - 1
                                Self.repositionVert(i, Self.frames[fr1].Vertices[i].x, Self.frames[fr1].Vertices[i].y, Self.frames[fr1].Vertices[i].z)
                        Next
                EndIf
        End Method
       
        Method StartAnim(st:Int, en:Int, spd:Float, md:Int, trans:Float)
                Self.anim_bounds[0] = st
                Self.anim_bounds[1] = en
                Self.anim_pos = Self.anim_bounds[0]
                Self.anim_spd = spd
                Self.anim_mode = md
                Self.anim_interp = trans
                If Self.anim_bounds[1] > Self.header[_COUNT_FRAME] - 1 Self.anim_bounds[1] = Self.header[_COUNT_FRAME] - 1
        End Method
       
        '========== Funcs =============
        'Quake2 MD2
       
        Function LoadMD2:TMD2(path:String, parent:TEntity = Null)
                Local f:TStream = ReadStream(path)
                If Not f Return Null
                Local m:TMD2 = New TMD2
               
                ' Header
                For Local i:Int = 0 To 16
                        m.header[i] = ReadInt(f)
                Next
               
                If m.header[_VERSION] <> 8
                        CloseStream f
                        Return Null
                EndIf
               
                ' Frames
               
                SeekStream(f, m.header[_OFF_FRAME])
                m.frames = New TMD2Frame[m.header[_COUNT_FRAME] ]
                m.verts = New TMD2BlitzVert[m.header[_COUNT_VERTEX] ]
                For Local I:Int = 0 To m.header[_COUNT_FRAME] - 1
                        Local Fr:TMD2Frame = New TMD2Frame
                        Fr.Scale[0] = ReadFloat(f)
                        Fr.Scale[1] = ReadFloat(f)
                        Fr.Scale[2] = ReadFloat(f)
                        Fr.Trans[0] = ReadFloat(f)
                        Fr.Trans[1] = ReadFloat(f)
                        Fr.Trans[2] = ReadFloat(f)
                        Fr.Name = ReadString(f, 16)
                        Fr.Vertices = New TMD2Vert[m.header[_COUNT_VERTEX] ]
                        For Local V:Int = 0 To m.header[_COUNT_VERTEX] - 1
                                m.verts[v] = New TMD2BlitzVert
                                m.verts[v].tris = CreateList()
                                Local Temp:TMD2Vert = New TMD2Vert
                                Temp.z = Float((ReadByte(f) * Fr.Scale[0]) + Fr.Trans[0])
                                Temp.x = Float((ReadByte(f) * Fr.Scale[1]) + Fr.Trans[1])
                                Temp.y = Float((ReadByte(f) * Fr.Scale[2]) + Fr.Trans[2])
                                ReadByte(f) ' Skip Normal Index
                                Fr.Vertices[V] = Temp
                        Next
                        m.frames[i] = Fr
                Next
               
                ' Triangles
               
                SeekStream(f, m.header[_OFF_TRIS])
                m.tris = New TMD2Tri[m.header[_COUNT_TRIS] ]
                For Local I:Int = 0 To m.header[_COUNT_TRIS] - 1
                        Local T:TMD2Tri = New TMD2Tri
                        T.vert[0] = ReadShort(f)
                        T.vert[1] = ReadShort(f)
                        T.vert[2] = ReadShort(f)
                        T.tex[0] = ReadShort(f)
                        T.tex[1] = ReadShort(f)
                        T.tex[2] = ReadShort(f)
                        m.tris[i] = T
                Next
               
                ' Tex Coords
               
                SeekStream(f, m.header[_OFF_TEXCOORD])
                m.coords = New TMD2TexCoord[m.header[_COUNT_TEXCOORD] ]
                For Local I:Int = 0 To m.header[_COUNT_TEXCOORD] - 1
                        Local T:TMD2TexCoord = New TMD2TexCoord
                        T.U = Float(ReadShort(f)) / Float(m.header[_SKIN_WIDTH])
                        T.V = Float(ReadShort(f)) / Float(m.header[_SKIN_HEIGHT])
                        m.coords[i] = T
                Next
               
                ' Skins
               
                SeekStream(f, m.header[_OFF_SKIN])
                m.skins = New String[m.header[_COUNT_SKIN] ]
                For Local I:Int = 0 To m.header[_COUNT_SKIN] - 1
                        m.skins[i] = Trim(ReadString(f, 64))
                Next
               
                ' Building mesh
                m.mesh = CreateMesh(parent)
                m.mesh.EntityFX(3 + 8)
                Local surf:TSurface = m.mesh.CreateSurface()
                m.surf = surf
                For Local t:TMD2Tri = EachIn m.tris
                        Local vrt:Int[3]
                        vrt[0] = m.addInternalVert(surf, t.vert[0], m.coords[t.tex[0] ].u, m.coords[t.tex[0] ].v)
                        vrt[1] = m.addInternalVert(surf, t.vert[1], m.coords[t.tex[1] ].u, m.coords[t.tex[1] ].v)
                        vrt[2] = m.addInternalVert(surf, t.vert[2], m.coords[t.tex[2] ].u, m.coords[t.tex[2] ].v)
                        surf.AddTriangle(vrt[2], vrt[1], vrt[0])
                Next
               
                md2s.AddLast(m)
                Return m
        EndFunction
       
        Method addInternalVert:Int(surf:TSurface, vid:Int, u:Float, v:Float)
                Local vrt:Int = surf.AddVertex(Self.frames[0].Vertices[vid].x, Self.frames[0].Vertices[vid].y, Self.frames[0].Vertices[vid].z, u, v)
                Self.verts[vid].tris.AddLast(String(vrt))
                Return vrt
        EndMethod
       
        Method repositionVert(vid:Int, x:Float, y:Float, z:Float)
                For Local i:String = EachIn Self.verts[vid].tris
                        Local st:Int = Int(i)
                        Self.surf.VertexCoords(st, x, y, z)
                Next
        End Method
       
        Function UpdateMD2(spd:Float = 1)
                Local m:TMD2
                For m = EachIn TMD2.md2s
                        Local inview:Int = 0
                        For Local c:TCamera = EachIn TCamera.cam_list
                                If c.Hidden() = 0
                                        If c.EntityInView(m.mesh)
                                                inview = 1
                                                Exit
                                        End If
                                End If
                        Next
                        If m.anim_mode > 0 And m.anim_spd <> 0
                                If inview m.UpdateFrame()
                                If m.anim_interp <> 0
                                       
                                Else
                                        m.anim_pos:+(spd * m.anim_spd)
                                        Select m.anim_mode
                                                Case 1
                                                        If m.anim_spd < 0
                                                                If m.anim_pos <= m.anim_bounds[0] m.anim_pos = m.anim_bounds[1]
                                                        Else
                                                                If m.anim_pos >= m.anim_bounds[1] m.anim_pos = m.anim_bounds[0]
                                                        End If
                                                Case 2
                                                        If m.anim_spd < 0
                                                                If m.anim_pos < m.anim_bounds[0] m.anim_mode = 0
                                                        Else
                                                                If m.anim_pos > m.anim_bounds[1] m.anim_mode = 0
                                                        End If
                                               
                                        End Select
                                EndIf
                        End If
                Next
        EndFunction
       
       
End Type



Часовой пояс GMT +4, время: 22:58.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot