Skip to content

Crash when equipping wing cap on x64 branch (mesh.Begin called with 0 triangles) #130

@Supercoder219

Description

@Supercoder219

When Mario equips the wing cap on the x64 branch, the game throws repeated errors:

[G64] lua/entities/g64_mario.lua:499: called mesh.Begin with a bad primitive type (2) or count (0)

This happens immediately when the wing cap is equipped.

Cause:
GenerateMesh() can attempt to build the wings mesh with zero triangles when the wing vertex list is empty during the equip frame.

Fix:
Add guards to prevent mesh.Begin() being called with 0 triangles and reset wingsIndices every frame.

Patch included below.

local fLerpVector = LerpVector
function ENT:GenerateMesh()
	local interpolation = GetConVar("g64_interpolation"):GetBool()

	if self.MarioId == nil or self.MarioId < 0 then return end
	if vertexBuffers[self.MarioId] == nil then return end

	local vertex = vertexBuffers[self.MarioId][self.bufferIndex + 1]
	local lastVertex = vertexBuffers[self.MarioId][1 - self.bufferIndex + 1]

	if vertex == nil or lastVertex == nil then return end
	if vertex[1] == nil or lastVertex[1] == nil then return end
	if #vertex[1] <= 0 or #lastVertex[1] <= 0 then return end

	local posTab = vertex[1]
	local lastPosTab = lastVertex[1]
	local normTab = vertex[2]
	local lastNormTab = lastVertex[2]
	local uTab = vertex[3]
	local vTab = vertex[4]
	local colTab = vertex[5]

	if posTab == nil or lastPosTab == nil or normTab == nil or lastNormTab == nil or uTab == nil or vTab == nil or colTab == nil then
		return
	end

	local vertCount = #posTab
	if vertCount <= 0 then return end

	local hasWingCap = self.hasWingCap == true
	local mainVertCount = vertCount

	-- Reset wing index list every frame so stale data does not carry over
	self.wingsIndices = {}

	-- Only split off wing vertices if the model actually has them
	if hasWingCap and vertCount > 2256 then
		mainVertCount = vertCount - 24
	end

	-- Need at least one full triangle
	if mainVertCount < 3 then return end

	local triCount = math.floor(mainVertCount / 3)
	if triCount <= 0 then return end

	if self.Mesh and self.Mesh:IsValid() then
		self.Mesh:Destroy()
		self.Mesh = nil
	end
	self.Mesh = Mesh()

	if self.WingsMesh and self.WingsMesh:IsValid() then
		self.WingsMesh:Destroy()
		self.WingsMesh = nil
	end
	self.WingsMesh = nil

	local t = (SysTime() - fixedTime) / G64_TICKRATE
	local myColorTable = self.colorTable or g64types.DefaultMarioColors
	local col
	local uvOffset = 2 / 704
	local wingIndex = 1

	-- Main body mesh
	mesh.Begin(self.Mesh, MATERIAL_TRIANGLES, triCount)
	for i = 1, vertCount do
		if posTab[i] == nil or lastPosTab[i] == nil or normTab[i] == nil or lastNormTab[i] == nil or uTab[i] == nil or vTab[i] == nil or colTab[i] == nil then
			mesh.End()
			self.Mesh:Destroy()
			self.Mesh = nil
			return
		end

		if hasWingCap and vertCount > 2256 and i > vertCount - 24 then
			self.wingsIndices[wingIndex] = i
			wingIndex = wingIndex + 1
		else
			col = myColorTable[colTab[i]] or {255, 255, 255}

			if interpolation then
				mesh.Position(fLerpVector(t, posTab[i], lastPosTab[i]))
				mesh.Normal(fLerpVector(t, normTab[i], lastNormTab[i]))
			else
				mesh.Position(posTab[i])
				mesh.Normal(normTab[i])
			end

			mesh.TexCoord(0, (uTab[i] + 0.002) * 0.9968, vTab[i])
			mesh.Color(col[1], col[2], col[3], 255)
			mesh.AdvanceVertex()
		end
	end
	mesh.End()

	-- Wings mesh
	local wingsIndices = self.wingsIndices
	local wingsVertCount = #wingsIndices
	local wingsTriCount = math.floor(wingsVertCount / 3)

	if hasWingCap and wingsVertCount >= 3 and wingsTriCount > 0 then
		self.WingsMesh = Mesh()
		uvOffset = 0.5 / 704

		mesh.Begin(self.WingsMesh, MATERIAL_TRIANGLES, wingsTriCount)
		for i = 1, wingsVertCount do
			local j = wingsIndices[i]

			if j == nil or posTab[j] == nil or lastPosTab[j] == nil or normTab[j] == nil or uTab[j] == nil or vTab[j] == nil or colTab[j] == nil then
				mesh.End()
				if self.WingsMesh and self.WingsMesh:IsValid() then
					self.WingsMesh:Destroy()
					self.WingsMesh = nil
				end
				return
			end

			col = myColorTable[colTab[j]] or {255, 255, 255}

			if interpolation then
				mesh.Position(fLerpVector(t, posTab[j], lastPosTab[j]))
				mesh.Normal(fLerpVector(t, normTab[j], lastNormTab[j]))
			else
				mesh.Position(posTab[j])
				mesh.Normal(normTab[j])
			end

			mesh.TexCoord(0, uTab[j] + uvOffset, vTab[j] + uvOffset)
			mesh.Color(col[1], col[2], col[3], 255)
			mesh.AdvanceVertex()
		end
		mesh.End()
	end
end

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions