pumpkin_man: draw the entire multi-object model
This commit is contained in:
parent
02e191eec0
commit
2aa1cedef4
@ -35,6 +35,11 @@ struct reloc_indices {
|
||||
int flush;
|
||||
};
|
||||
|
||||
struct vb_object_offsets {
|
||||
int start;
|
||||
int material_index;
|
||||
};
|
||||
|
||||
static inline uint32_t rreg(void * rmmio, uint32_t offset)
|
||||
{
|
||||
uint32_t value = *((volatile uint32_t *)(((uintptr_t)rmmio) + offset));
|
||||
@ -212,6 +217,13 @@ int _3d_clear(int ix, const struct reloc_indices * reloc_indices)
|
||||
|
||||
T0V(VAP_INDEX_OFFSET, 0x00000000);
|
||||
|
||||
T0V(VAP_VF_MAX_VTX_INDX
|
||||
, VAP_VF_MAX_VTX_INDX__MAX_INDX(0)
|
||||
);
|
||||
T0V(VAP_VF_MIN_VTX_INDX
|
||||
, VAP_VF_MIN_VTX_INDX__MIN_INDX(0)
|
||||
);
|
||||
|
||||
T0V(VAP_OUT_VTX_FMT_0
|
||||
, VAP_OUT_VTX_FMT_0__VTX_POS_PRESENT(1));
|
||||
T0V(VAP_OUT_VTX_FMT_1
|
||||
@ -257,9 +269,108 @@ int _3d_clear(int ix, const struct reloc_indices * reloc_indices)
|
||||
return ix;
|
||||
}
|
||||
|
||||
int _3d_object(int ix, const struct reloc_indices * reloc_indices,
|
||||
float theta,
|
||||
int texture(int ix,
|
||||
const struct reloc_indices * reloc_indices,
|
||||
int texture_index)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// TX
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
T0V(TX_INVALTAGS, 0x00000000);
|
||||
|
||||
T0V(TX_ENABLE
|
||||
, TX_ENABLE__TEX_0_ENABLE__ENABLE);
|
||||
T0V(TX_FILTER0_0
|
||||
, TX_FILTER0__MAG_FILTER__LINEAR
|
||||
| TX_FILTER0__MIN_FILTER__LINEAR
|
||||
);
|
||||
T0V(TX_FILTER1_0
|
||||
, TX_FILTER1__LOD_BIAS(1)
|
||||
);
|
||||
T0V(TX_BORDER_COLOR_0, 0);
|
||||
T0V(TX_FORMAT0_0
|
||||
, TX_FORMAT0__TXWIDTH(1024 - 1)
|
||||
| TX_FORMAT0__TXHEIGHT(1024 - 1)
|
||||
);
|
||||
|
||||
T0V(TX_FORMAT1_0
|
||||
, TX_FORMAT1__TXFORMAT__TX_FMT_8_8_8_8
|
||||
| TX_FORMAT1__SEL_ALPHA(5)
|
||||
| TX_FORMAT1__SEL_RED(0)
|
||||
| TX_FORMAT1__SEL_GREEN(1)
|
||||
| TX_FORMAT1__SEL_BLUE(2)
|
||||
| TX_FORMAT1__TEX_COORD_TYPE__2D
|
||||
);
|
||||
T0V(TX_FORMAT2_0, 0);
|
||||
|
||||
T0V(TX_OFFSET_0
|
||||
//, TX_OFFSET__MACRO_TILE(1)
|
||||
//| TX_OFFSET__MICRO_TILE(1)
|
||||
, 0
|
||||
);
|
||||
|
||||
T3(_NOP, 0);
|
||||
ib[ix++].u32 = (reloc_indices->texturebuffer + texture_index) * 4; // index into relocs array
|
||||
|
||||
return ix;
|
||||
}
|
||||
|
||||
int aos(int ix,
|
||||
const struct reloc_indices * reloc_indices,
|
||||
int start,
|
||||
int vertex_count)
|
||||
{
|
||||
T0V(VAP_VTX_SIZE
|
||||
, VAP_VTX_SIZE__DWORDS_PER_VTX(5)
|
||||
);
|
||||
|
||||
T0V(VAP_INDEX_OFFSET, 0x00000000);
|
||||
|
||||
T0V(VAP_VF_MAX_VTX_INDX
|
||||
, VAP_VF_MAX_VTX_INDX__MAX_INDX(vertex_count - 1)
|
||||
);
|
||||
T0V(VAP_VF_MIN_VTX_INDX
|
||||
, VAP_VF_MIN_VTX_INDX__MIN_INDX(0)
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// AOS
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
T3(_3D_LOAD_VBPNTR, (4 - 1));
|
||||
ib[ix++].u32 // VAP_VTX_NUM_ARRAYS
|
||||
= VAP_VTX_NUM_ARRAYS__VTX_NUM_ARRAYS(2)
|
||||
| VAP_VTX_NUM_ARRAYS__VC_FORCE_PREFETCH(1)
|
||||
;
|
||||
ib[ix++].u32 // VAP_VTX_AOS_ATTR01
|
||||
= VAP_VTX_AOS_ATTR__VTX_AOS_COUNT0(3)
|
||||
| VAP_VTX_AOS_ATTR__VTX_AOS_STRIDE0(5)
|
||||
| VAP_VTX_AOS_ATTR__VTX_AOS_COUNT1(2)
|
||||
| VAP_VTX_AOS_ATTR__VTX_AOS_STRIDE1(5)
|
||||
;
|
||||
ib[ix++].u32 // VAP_VTX_AOS_ADDR0
|
||||
= (4 * (start + 0));
|
||||
ib[ix++].u32 // VAP_VTX_AOS_ADDR1
|
||||
= (4 * (start + 3));
|
||||
|
||||
// VAP_VTX_AOS_ADDR is an absolute address in VRAM. However, DRM_RADEON_CS
|
||||
// modifies this to be an offset relative to the GEM buffer handles given via
|
||||
// NOP:
|
||||
|
||||
T3(_NOP, 0);
|
||||
ib[ix++].u32 = reloc_indices->vertexbuffer * 4; // index into relocs array for VAP_VTX_AOS_ADDR0
|
||||
T3(_NOP, 0);
|
||||
ib[ix++].u32 = reloc_indices->vertexbuffer * 4; // index into relocs array for VAP_VTX_AOS_ADDR1
|
||||
|
||||
return ix;
|
||||
}
|
||||
|
||||
int _3d_object(int ix,
|
||||
const struct reloc_indices * reloc_indices,
|
||||
float theta,
|
||||
struct vb_object_offsets * object_offsets,
|
||||
int object_count)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// ZB
|
||||
@ -315,46 +426,6 @@ int _3d_object(int ix, const struct reloc_indices * reloc_indices,
|
||||
| RS_INST__TEX_ADDR(0)
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// TX
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
T0V(TX_INVALTAGS, 0x00000000);
|
||||
|
||||
T0V(TX_ENABLE
|
||||
, TX_ENABLE__TEX_0_ENABLE__ENABLE);
|
||||
T0V(TX_FILTER0_0
|
||||
, TX_FILTER0__MAG_FILTER__LINEAR
|
||||
| TX_FILTER0__MIN_FILTER__LINEAR
|
||||
);
|
||||
T0V(TX_FILTER1_0
|
||||
, TX_FILTER1__LOD_BIAS(1)
|
||||
);
|
||||
T0V(TX_BORDER_COLOR_0, 0);
|
||||
T0V(TX_FORMAT0_0
|
||||
, TX_FORMAT0__TXWIDTH(1024 - 1)
|
||||
| TX_FORMAT0__TXHEIGHT(1024 - 1)
|
||||
);
|
||||
|
||||
T0V(TX_FORMAT1_0
|
||||
, TX_FORMAT1__TXFORMAT__TX_FMT_8_8_8_8
|
||||
| TX_FORMAT1__SEL_ALPHA(5)
|
||||
| TX_FORMAT1__SEL_RED(0)
|
||||
| TX_FORMAT1__SEL_GREEN(1)
|
||||
| TX_FORMAT1__SEL_BLUE(2)
|
||||
| TX_FORMAT1__TEX_COORD_TYPE__2D
|
||||
);
|
||||
T0V(TX_FORMAT2_0, 0);
|
||||
|
||||
T0V(TX_OFFSET_0
|
||||
//, TX_OFFSET__MACRO_TILE(1)
|
||||
//| TX_OFFSET__MICRO_TILE(1)
|
||||
, 0
|
||||
);
|
||||
|
||||
T3(_NOP, 0);
|
||||
ib[ix++].u32 = reloc_indices->texturebuffer * 4; // index into relocs array
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// VAP_PVS
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -438,19 +509,6 @@ int _3d_object(int ix, const struct reloc_indices * reloc_indices,
|
||||
| VAP_PROG_STREAM_CNTL_EXT__WRITE_ENA_1(0b1111) // XYZW
|
||||
);
|
||||
|
||||
T0V(VAP_VTX_SIZE
|
||||
, VAP_VTX_SIZE__DWORDS_PER_VTX(5)
|
||||
);
|
||||
|
||||
T0V(VAP_INDEX_OFFSET, 0x00000000);
|
||||
|
||||
T0V(VAP_VF_MAX_VTX_INDX
|
||||
, VAP_VF_MAX_VTX_INDX__MAX_INDX(vertex_count - 1)
|
||||
);
|
||||
T0V(VAP_VF_MIN_VTX_INDX
|
||||
, VAP_VF_MIN_VTX_INDX__MIN_INDX(0)
|
||||
);
|
||||
|
||||
T0V(VAP_OUT_VTX_FMT_0
|
||||
, VAP_OUT_VTX_FMT_0__VTX_POS_PRESENT(1));
|
||||
T0V(VAP_OUT_VTX_FMT_1
|
||||
@ -472,34 +530,19 @@ int _3d_object(int ix, const struct reloc_indices * reloc_indices,
|
||||
| US_CODE_ADDR__END_ADDR(fragment_shader_instructions - 1)
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// AOS
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
for (int object_ix = 0; object_ix < object_count; object_ix++) {
|
||||
int start = object_offsets[object_ix].start;
|
||||
int material_index = object_offsets[object_ix].material_index;
|
||||
int end = object_offsets[object_ix+1].start;
|
||||
assert(end > 0 && end > start);
|
||||
int size = end - start;
|
||||
int vertex_count = size / 5;
|
||||
|
||||
T3(_3D_LOAD_VBPNTR, (4 - 1));
|
||||
ib[ix++].u32 // VAP_VTX_NUM_ARRAYS
|
||||
= VAP_VTX_NUM_ARRAYS__VTX_NUM_ARRAYS(2)
|
||||
| VAP_VTX_NUM_ARRAYS__VC_FORCE_PREFETCH(1)
|
||||
;
|
||||
ib[ix++].u32 // VAP_VTX_AOS_ATTR01
|
||||
= VAP_VTX_AOS_ATTR__VTX_AOS_COUNT0(3)
|
||||
| VAP_VTX_AOS_ATTR__VTX_AOS_STRIDE0(5)
|
||||
| VAP_VTX_AOS_ATTR__VTX_AOS_COUNT1(2)
|
||||
| VAP_VTX_AOS_ATTR__VTX_AOS_STRIDE1(5)
|
||||
;
|
||||
ib[ix++].u32 // VAP_VTX_AOS_ADDR0
|
||||
= (4 * 0);
|
||||
ib[ix++].u32 // VAP_VTX_AOS_ADDR1
|
||||
= (4 * 3);
|
||||
printf("object_ix %d start %d end %d vertex_count %d\n",
|
||||
object_ix, start, end, vertex_count);
|
||||
|
||||
// VAP_VTX_AOS_ADDR is an absolute address in VRAM. However, DRM_RADEON_CS
|
||||
// modifies this to be an offset relative to the GEM buffer handles given via
|
||||
// NOP:
|
||||
|
||||
T3(_NOP, 0);
|
||||
ib[ix++].u32 = reloc_indices->vertexbuffer * 4; // index into relocs array for VAP_VTX_AOS_ADDR0
|
||||
T3(_NOP, 0);
|
||||
ib[ix++].u32 = reloc_indices->vertexbuffer * 4; // index into relocs array for VAP_VTX_AOS_ADDR1
|
||||
ix = texture(ix, reloc_indices, material_index);
|
||||
ix = aos(ix, reloc_indices, start, vertex_count);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// 3D_DRAW
|
||||
@ -515,11 +558,15 @@ int _3d_object(int ix, const struct reloc_indices * reloc_indices,
|
||||
| VAP_VF_CNTL__USE_ALT_NUM_VERTS(0)
|
||||
| VAP_VF_CNTL__NUM_VERTICES(vertex_count)
|
||||
;
|
||||
}
|
||||
|
||||
return ix;
|
||||
}
|
||||
|
||||
int indirect_buffer(float theta, int vertex_count, const struct reloc_indices * reloc_indices)
|
||||
int indirect_buffer(const struct reloc_indices * reloc_indices,
|
||||
int object_count,
|
||||
struct vb_object_offsets * object_offsets,
|
||||
float theta)
|
||||
{
|
||||
int ix = 0;
|
||||
|
||||
@ -836,7 +883,9 @@ int indirect_buffer(float theta, int vertex_count, const struct reloc_indices *
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ix = _3d_clear(ix, reloc_indices);
|
||||
ix = _3d_object(ix, reloc_indices, theta, vertex_count);
|
||||
ix = _3d_object(ix, reloc_indices, theta,
|
||||
object_offsets,
|
||||
object_count);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// padding
|
||||
@ -900,19 +949,31 @@ int create_colorbuffer(int fd, int colorbuffer_size, void ** out_ptr)
|
||||
return args.handle;
|
||||
}
|
||||
|
||||
int fill_vertexbuffer(void * ptr, int size)
|
||||
int fill_vertexbuffer(void * ptr, int size,
|
||||
struct vb_object_offsets ** offsets_out)
|
||||
{
|
||||
float * fptr = (float *)ptr;
|
||||
|
||||
int ix = 0;
|
||||
|
||||
const int object_count = (sizeof (objects)) / (sizeof (objects[0]));
|
||||
|
||||
// FIXME: iterate through meshes, not objects
|
||||
struct vb_object_offsets * offsets = calloc((sizeof (struct vb_object_offsets)), object_count + 1);
|
||||
|
||||
for (int object_ix = 0; object_ix < object_count; object_ix++) {
|
||||
const struct mesh * mesh = objects[object_ix].mesh;
|
||||
|
||||
offsets[object_ix].start = ix;
|
||||
|
||||
printf("fill vertexbuffer: object_ix %d polygons %d\n",
|
||||
object_ix, mesh->polygons_length);
|
||||
|
||||
assert(mesh->uv_layers_length == 1);
|
||||
const vec2 * uvmap = mesh->uv_layers[0];
|
||||
const vec3 * position = mesh->position;
|
||||
|
||||
int last_mat_ix = -1;
|
||||
|
||||
for (int polygon_ix = 0; polygon_ix < mesh->polygons_length; polygon_ix++) {
|
||||
|
||||
int uv_ix = polygon_ix * 3;
|
||||
@ -924,6 +985,14 @@ int fill_vertexbuffer(void * ptr, int size)
|
||||
const vec2 * bt = &uvmap[uv_ix + 1];
|
||||
const vec2 * ct = &uvmap[uv_ix + 2];
|
||||
|
||||
if (last_mat_ix != polygon->material_index) {
|
||||
printf("new material: object_ix %d material_index %d\n",
|
||||
object_ix, polygon->material_index);
|
||||
offsets[object_ix].material_index = polygon->material_index;
|
||||
last_mat_ix = polygon->material_index;
|
||||
}
|
||||
//assert(polygon->material_index == object_ix);
|
||||
|
||||
assert((ix + (5 * 3)) < (size / 4));
|
||||
|
||||
fptr[ix++] = ap->x;
|
||||
@ -946,9 +1015,15 @@ int fill_vertexbuffer(void * ptr, int size)
|
||||
}
|
||||
}
|
||||
|
||||
offsets[object_count].start = ix;
|
||||
|
||||
printf("fill vertexbuffer: dwords %d size %d\n", ix, (int)(ix * (sizeof (float))));
|
||||
|
||||
*offsets_out = offsets;
|
||||
|
||||
asm volatile("" ::: "memory");
|
||||
|
||||
return ix;
|
||||
return object_count;
|
||||
}
|
||||
|
||||
static int * load_textures(int fd, int * length_out)
|
||||
@ -1036,10 +1111,10 @@ int main()
|
||||
fprintf(stderr, "zbuffer handle %d\n", zbuffer_handle);
|
||||
fprintf(stderr, "vertexbuffer handle %d\n", vertexbuffer_handle);
|
||||
|
||||
int vertexbuffer_length = fill_vertexbuffer(vertexbuffer_ptr, vertexbuffer_size);
|
||||
struct vb_object_offsets * object_offsets = NULL;
|
||||
int object_count = fill_vertexbuffer(vertexbuffer_ptr, vertexbuffer_size, &object_offsets);
|
||||
munmap(vertexbuffer_ptr, vertexbuffer_size);
|
||||
fprintf(stderr, "vertexbuffer length %d\n", vertexbuffer_length);
|
||||
int vertex_count = vertexbuffer_length / 5;
|
||||
fprintf(stderr, "object count %d\n", object_count);
|
||||
|
||||
int texture_handles_length = 0;
|
||||
int * texture_handles = load_textures(fd, &texture_handles_length);
|
||||
@ -1119,7 +1194,10 @@ int main()
|
||||
.flags = 8,
|
||||
};
|
||||
|
||||
int ib_dwords = indirect_buffer(theta, vertex_count, &reloc_indices);
|
||||
int ib_dwords = indirect_buffer(&reloc_indices,
|
||||
object_count,
|
||||
object_offsets,
|
||||
theta);
|
||||
|
||||
struct drm_radeon_cs_chunk chunks[3] = {
|
||||
{
|
||||
|
||||
89566
model/pumpkin/pumpkin.h
89566
model/pumpkin/pumpkin.h
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,29 @@ def sprint(*text):
|
||||
|
||||
print = sprint
|
||||
|
||||
def get_material_image(material):
|
||||
assert material.use_nodes, material.name
|
||||
for node in material.node_tree.nodes:
|
||||
if node.type == "TEX_IMAGE":
|
||||
return node.image
|
||||
|
||||
_offset = 0
|
||||
texture_ids = {}
|
||||
prefix = "textures_"
|
||||
|
||||
def get_image_id(image):
|
||||
global _offset
|
||||
global texture_ids
|
||||
if image.name in texture_ids:
|
||||
value = texture_ids[image.name]
|
||||
return value
|
||||
value = _offset
|
||||
texture_ids[image.name] = value
|
||||
width, height = image.size
|
||||
#_offset += width * height * 2
|
||||
_offset += 1
|
||||
return value
|
||||
|
||||
def render_vec3(v):
|
||||
return f"{{{v.x:.6f}, {v.y:.6f}, {v.z:.6f}}}"
|
||||
|
||||
@ -43,11 +66,11 @@ def render_polygon_normals(f, name, polygon_normals):
|
||||
def sort_by_material(polygons):
|
||||
return sorted(polygons, key=lambda p: p.material_index)
|
||||
|
||||
def render_polygons(f, name, polygons):
|
||||
def render_polygons(f, name, mesh):
|
||||
f.write(f"static const struct polygon {name}_polygons[] = {{\n")
|
||||
|
||||
uv_ix = 0
|
||||
for i, polygon in enumerate(polygons):
|
||||
for i, polygon in enumerate(mesh.polygons):
|
||||
if triangulate_meshes:
|
||||
assert len(polygon.vertices) == 3
|
||||
|
||||
@ -55,12 +78,16 @@ def render_polygons(f, name, polygons):
|
||||
f.write(f" {{-1, -1, -1, -1, -1, -1}}, // {{{s}}}\n")
|
||||
continue
|
||||
|
||||
material = mesh.materials[polygon.material_index]
|
||||
image = get_material_image(material)
|
||||
image_id = get_image_id(image)
|
||||
|
||||
if triangulate_meshes:
|
||||
indices = [*polygon.vertices, polygon.material_index]
|
||||
indices = [*polygon.vertices, image_id]
|
||||
elif len(polygon.vertices) == 4:
|
||||
indices = [*polygon.vertices, polygon.material_index, uv_ix]
|
||||
indices = [*polygon.vertices, image_id, uv_ix]
|
||||
else:
|
||||
indices = [*polygon.vertices, -1, polygon.material_index, uv_ix]
|
||||
indices = [*polygon.vertices, -1, image_id, uv_ix]
|
||||
|
||||
uv_ix += len(polygon.vertices)
|
||||
s = ", ".join(map(str, indices))
|
||||
@ -168,29 +195,6 @@ def mesh_meshes(collections):
|
||||
yield mesh.name, tri_mesh
|
||||
bpy.data.meshes.remove(tri_mesh)
|
||||
|
||||
def get_texture(material):
|
||||
assert material.use_nodes, material.name
|
||||
for node in material.node_tree.nodes:
|
||||
if node.type == "TEX_IMAGE":
|
||||
return node.image
|
||||
|
||||
_offset = 0
|
||||
texture_ids = {}
|
||||
prefix = "textures_"
|
||||
|
||||
def get_texture_id(image):
|
||||
global _offset
|
||||
global texture_ids
|
||||
if image.name in texture_ids:
|
||||
value = texture_ids[image.name]
|
||||
return value
|
||||
value = _offset
|
||||
texture_ids[image.name] = value
|
||||
width, height = image.size
|
||||
#_offset += width * height * 2
|
||||
_offset += 1
|
||||
return value
|
||||
|
||||
def texture_data_name(name):
|
||||
name = path.splitext(name)[0]
|
||||
name = translate_name(name)
|
||||
@ -200,12 +204,12 @@ def render_mesh_materials(f, name, materials):
|
||||
f.write(f"static const struct mesh_material {name}_materials[] = {{\n")
|
||||
print("materials", materials)
|
||||
for material in materials:
|
||||
image = get_texture(material)
|
||||
print("image", image)
|
||||
image = get_material_image(material)
|
||||
print("image", material, image)
|
||||
if image is not None:
|
||||
f.write(f" {{ // {material.name} {image.name}\n")
|
||||
width, height = image.size
|
||||
texture_id = get_texture_id(image)
|
||||
texture_id = get_image_id(image)
|
||||
f.write(f" .width = {width},\n")
|
||||
f.write(f" .height = {height},\n")
|
||||
f.write(f" .texture_id = {texture_id},\n")
|
||||
@ -243,7 +247,7 @@ def export_meshes(f):
|
||||
render_uv_map(f, mesh_name, translate_name(layer_name), layer.uv)
|
||||
render_vertex_normals(f, mesh_name, mesh.vertices)
|
||||
render_polygon_normals(f, mesh_name, mesh.polygon_normals)
|
||||
render_polygons(f, mesh_name, mesh.polygons)
|
||||
render_polygons(f, mesh_name, mesh)
|
||||
render_polygon_edge_pairs(f, mesh_name, mesh.polygons)
|
||||
render_mesh_materials(f, mesh_name, mesh.materials)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user