Показать сообщение отдельно
Старый 18.09.2013, 18:53   #1
Кирпи4
Социал-сычевист
 
Аватар для Кирпи4
 
Регистрация: 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)
 
Ответить с цитированием