Store cooked models as structs instead of list of tuples - now the important loops are all white (C code) but it leaks memory

This commit is contained in:
David Vierra 2015-01-04 12:46:40 -10:00
parent 864990429d
commit 801307e069
3 changed files with 120 additions and 35 deletions

View File

@ -0,0 +1,20 @@
cdef struct ModelQuad:
float[24] xyzuvc
char[4] cullface # isCulled, dx, dy, dz
cdef struct ModelQuadList:
int count
ModelQuad *quads
cdef class BlockModels:
cdef object resourceLoader
cdef object blocktypes
cdef object modelBlockJsons
cdef object modelStateJsons
cdef object modelQuads
cdef object _textureNames
cdef public object firstTextures
cdef object cookedModels
cdef ModelQuadList cookedModelsByID[4096][16]
cdef object cooked

View File

@ -16,10 +16,21 @@ from array import array
from mceditlib import faces
from mceditlib.geometry import Vector, FloatBox
from libc.stdlib cimport malloc, free
from libc.string cimport memset
log = logging.getLogger(__name__)
cdef struct ModelQuad:
float[24] xyzuvc
char[4] cullface # isCulled, dx, dy, dz
cdef struct ModelQuadList:
int count
ModelQuad *quads
cdef class BlockModels(object):
class BlockModels(object):
def _getBlockModel(self, modelName):
model = self.modelBlockJsons.get(modelName)
if model is None:
@ -53,7 +64,8 @@ class BlockModels(object):
self._textureNames = set()
self.firstTextures = {} # first texture found for each block - used for icons (xxx)
self.cookedModels = {} # nameAndState -> list[(xyzuvc, cullface)]
self.cookedModelsByID = numpy.zeros((256*16, 16), dtype=list) # (id, meta) -> list[(xyzuvc, cullface)]
#self.cookedModelsByID = numpy.zeros((256*16, 16), dtype=list) # (id, meta) -> list[(xyzuvc, cullface)]
memset(self.cookedModelsByID, 0, sizeof(self.cookedModelsByID))
self.cooked = False
for i, block in enumerate(blocktypes):
@ -266,17 +278,44 @@ class BlockModels(object):
xyzuvc.view('uint8')[:, 20:] = faceShades[face]
else:
xyzuvc.view('uint8')[:, 20:] = 0xff
xyzuvc.shape = 1, 4, 6 # add the first dimension to stack along in modelmesh.pyx
xyzuvc.shape = 24 # flatten to store in ModelQuad.xyzuvc
cookedQuads.append((xyzuvc, cullface))
cookedModels[nameAndState] = cookedQuads
ID, meta = self.blocktypes.IDsByState[nameAndState]
self.cookedModelsByID[ID, meta] = cookedQuads
self.storeQuads(cookedQuads, ID, meta)
self.cookedModels = cookedModels
self.cooked = True
def storeQuads(self, list cookedQuads, unsigned short ID, unsigned char meta):
cdef ModelQuadList modelQuads
modelQuads.count = len(cookedQuads)
cdef void * quads = malloc(modelQuads.count * sizeof(ModelQuad))
modelQuads.quads = <ModelQuad *>quads
cdef float[:] xyzuvc, quadxyzuvc
cdef int i
for i in range(modelQuads.count):
xyzuvc, cullface = cookedQuads[i]
quadxyzuvc = modelQuads.quads[i].xyzuvc
quadxyzuvc[:] = xyzuvc[:]
if cullface:
modelQuads.quads[i].cullface[0] = 1
dx, dy, dz = cullface.vector
modelQuads.quads[i].cullface[1] = dx
modelQuads.quads[i].cullface[2] = dy
modelQuads.quads[i].cullface[3] = dz
else:
modelQuads.quads[i].cullface[0] = 0
modelQuads.quads[i].cullface[1] = 0
modelQuads.quads[i].cullface[2] = 0
modelQuads.quads[i].cullface[3] = 0
self.cookedModelsByID[ID][meta] = modelQuads
def rotateVertices(self, rotation, variantXrot, variantYrot, variantZrot, xyzuvc):
if rotation is not None:
origin = rotation["origin"]

View File

@ -10,6 +10,10 @@ cimport numpy
from mcedit2.rendering import renderstates
from mcedit2.rendering.vertexarraybuffer import VertexArrayBuffer
from mcedit2.rendering cimport blockmodels
from libc.stdlib cimport malloc, realloc, free
from libc.string cimport memcpy
log = logging.getLogger(__name__)
@ -32,12 +36,9 @@ class BlockModelMesh(object):
cdef numpy.ndarray[numpy.uint8_t, ndim=3] data
cdef numpy.ndarray[numpy.uint8_t, ndim=1] renderType
cdef numpy.ndarray[numpy.uint8_t, ndim=1] opaqueCube
cdef blockmodels.BlockModels blockModels
chunk = self.sectionUpdate.chunkUpdate.chunk
cdef short cy = self.sectionUpdate.cy
section = chunk.getSection(cy)
if section is None:
return
atlas = self.sectionUpdate.chunkUpdate.updateTask.textureAtlas
blockModels = atlas.blockModels
@ -45,28 +46,33 @@ class BlockModelMesh(object):
blocktypes = self.sectionUpdate.blocktypes
areaBlocks = self.sectionUpdate.areaBlocks
data = section.Data
data = self.sectionUpdate.Data
renderType = self.sectionUpdate.renderType
opaqueCube = blocktypes.opaqueCube
faceQuadVerts = []
#faceQuadVerts = []
cdef unsigned short y, z, x, ID, meta
cdef short dx, dy, dz,
cdef unsigned short nx, ny, nz, nID
cdef numpy.ndarray verts
cdef list quads
cdef tuple quad
cdef blockmodels.ModelQuadList quads
cdef blockmodels.ModelQuad quad
cdef numpy.ndarray[numpy.uint16_t, ndim=1] coords = numpy.zeros(3, dtype=numpy.uint16)
cdef numpy.ndarray[list, ndim=2] cookedModelsByID = blockModels.cookedModelsByID
cdef unsigned short rx, ry, rz
cdef unsigned int buffer_ptr = 0
cdef unsigned int buffer_size = 256
cdef float * vertexBuffer = <float *>malloc(buffer_size * sizeof(float) * 24)
cdef float * xyzuvc
cdef numpy.ndarray vabuffer
if vertexBuffer == NULL:
return
for y in range(1, 17):
coords[1] = y - 1 + (cy << 4)
ry = y - 1 + (cy << 4)
for z in range(1, 17):
coords[2] = z - 1
rz = z - 1
for x in range(1, 17):
coords[0] = x - 1
rx = x - 1
ID = areaBlocks[y, z, x]
if ID == 0:
continue
@ -74,27 +80,47 @@ class BlockModelMesh(object):
if renderType[ID] != 3: # only model blocks for now
continue
quads = cookedModelsByID[ID, meta]
if quads is None:
quads = blockModels.cookedModelsByID[ID][meta]
if quads.count == 0:
continue
for xyzuvc, cullface in quads:
if cullface is not None:
dx, dy, dz = cullface.vector
nx = x + dx
ny = y + dy
nz = z + dz
for i in range(quads.count):
quad = quads.quads[i]
if quad.cullface[0]:
nx = x + quad.cullface[1]
ny = y + quad.cullface[2]
nz = z + quad.cullface[3]
nID = areaBlocks[ny, nz, nx]
if opaqueCube[nID]:
continue
verts = numpy.array(xyzuvc)
verts[..., :3] += coords
faceQuadVerts.append(verts)
# log.info("Block %s:\nVertices: %s", (x-1, y-1, z-1), verts)
xyzuvc = vertexBuffer + buffer_ptr * 24
memcpy(xyzuvc, quad.xyzuvc, sizeof(float) * 24)
# raise SystemExit
if len(faceQuadVerts):
vertexArray = VertexArrayBuffer(len(faceQuadVerts), lights=False)
vertexArray.buffer[..., :6] = numpy.vstack(faceQuadVerts)
#(<object>verts).shape = 1, 4, 6
#verts[..., :3] += coords
xyzuvc[0] += rx
xyzuvc[1] += ry
xyzuvc[2] += rz
xyzuvc[6] += rx
xyzuvc[7] += ry
xyzuvc[8] += rz
xyzuvc[12] += rx
xyzuvc[13] += ry
xyzuvc[14] += rz
xyzuvc[18] += rx
xyzuvc[19] += ry
xyzuvc[20] += rz
buffer_ptr += 1
if buffer_ptr >= buffer_size:
buffer_size *= 2
vertexBuffer = <float *>realloc(vertexBuffer, buffer_size * sizeof(float) * 24)
#buffer.resize((buffer_size, 24))
#faceQuadVerts.append(verts)
if buffer_ptr: # now buffer size
vertexArray = VertexArrayBuffer(buffer_ptr, lights=False)
vabuffer = vertexArray.buffer
memcpy(vabuffer.data, vertexBuffer, buffer_ptr * sizeof(float) * 24)
self.vertexArrays = [vertexArray]
free(vertexBuffer)