|
3D-программирование miniB3D, OpenGL |
18.09.2013, 18:53
|
#1
|
Социал-сычевист
Регистрация: 24.06.2011
Сообщений: 611
Написано 342 полезных сообщений (для 1,359 пользователей)
|
MD2 Loader под MiniB3D
Сап булка.
Очень уж я подружился с максом, и ещё сильнее с minib3d. И тут народ захотел увидеть в SpriteBoy (а плеер под него написан именно на максе) модельки хотя бы в MD2. Ну а кто я такой, чтобы им отказать?
Лоадер был написан, но при загрузке и построении меша происходит какая то неведомость с текстурными координатами. Для примера сравните:
Блицевский 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
|
(Offline)
|
|
18.09.2013, 19:21
|
#2
|
|
Ответ: MD2 Loader под MiniB3D
да бывает такое. Я тоже как то писал загрузчики md2/md3
Там нужно очень хитро передавать указатель. Пороюсь в мусорке, если найду - выложу полностью рабочий загрузчик.
|
|
|
18.09.2013, 19:33
|
#3
|
Социал-сычевист
Регистрация: 24.06.2011
Сообщений: 611
Написано 342 полезных сообщений (для 1,359 пользователей)
|
Ответ: MD2 Loader под MiniB3D
Если найдёшь - пожму руку
UPD: Хм, по-видимому с UV всё нормально, это они уже херово передаются в самого бздуна. Печаль века...
|
(Offline)
|
|
18.09.2013, 19:58
|
#4
|
|
Ответ: MD2 Loader под MiniB3D
загрузчик остался в жостком который я снял....
Короче тама наскок я помню делал так :
1 ) закидывал в массив
2 ) передавал адрес указателя
вроде так :
Local uv#[2]
glTexCoords2fv(VarPtr Float Ptr(uv[0]), VarPtr Float Ptr(uv[1]))
Или вроде так
glCoordsv(VarPtr Float Ptr(uv))
|
|
|
19.09.2013, 01:04
|
#5
|
Социал-сычевист
Регистрация: 24.06.2011
Сообщений: 611
Написано 342 полезных сообщений (для 1,359 пользователей)
|
Ответ: 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
|
(Offline)
|
|
Эти 2 пользователя(ей) сказали Спасибо Кирпи4 за это полезное сообщение:
|
|
Ваши права в разделе
|
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 04:32.
|