pumpkin_man: use blender.py exporter
@ -1,7 +1,7 @@
|
|||||||
OPT = -O0
|
OPT = -O0
|
||||||
|
|
||||||
CFLAGS += -g
|
CFLAGS += -g
|
||||||
CFLAGS += -Wall -Werror -Wfatal-errors
|
CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable
|
||||||
CFLAGS += $(shell pkg-config --cflags libdrm)
|
CFLAGS += $(shell pkg-config --cflags libdrm)
|
||||||
|
|
||||||
LDFLAGS += $(shell pkg-config --libs libdrm) -lm
|
LDFLAGS += $(shell pkg-config --libs libdrm) -lm
|
||||||
|
|||||||
@ -19,17 +19,22 @@
|
|||||||
#include "3d_registers_bits.h"
|
#include "3d_registers_bits.h"
|
||||||
#include "command_processor.h"
|
#include "command_processor.h"
|
||||||
|
|
||||||
#define pumpkin_Material_002 0
|
#include "../model/vec.h"
|
||||||
#define pumpkin_pumpkin 0
|
#include "../model/blender_model.h"
|
||||||
#define pumpkin_belt 0
|
|
||||||
|
|
||||||
#include "../model/model.h"
|
|
||||||
#include "../model/pumpkin/pumpkin.h"
|
#include "../model/pumpkin/pumpkin.h"
|
||||||
|
|
||||||
#define PI (3.14159274101257324219f)
|
#define PI (3.14159274101257324219f)
|
||||||
#define PI_2 (PI * 2.0f)
|
#define PI_2 (PI * 2.0f)
|
||||||
#define I_PI_2 (1.0f / (PI_2))
|
#define I_PI_2 (1.0f / (PI_2))
|
||||||
|
|
||||||
|
struct reloc_indices {
|
||||||
|
int colorbuffer;
|
||||||
|
int zbuffer;
|
||||||
|
int vertexbuffer;
|
||||||
|
int texturebuffer;
|
||||||
|
int flush;
|
||||||
|
};
|
||||||
|
|
||||||
static inline uint32_t rreg(void * rmmio, uint32_t offset)
|
static inline uint32_t rreg(void * rmmio, uint32_t offset)
|
||||||
{
|
{
|
||||||
uint32_t value = *((volatile uint32_t *)(((uintptr_t)rmmio) + offset));
|
uint32_t value = *((volatile uint32_t *)(((uintptr_t)rmmio) + offset));
|
||||||
@ -43,7 +48,7 @@ static inline void wreg(void * rmmio, uint32_t offset, uint32_t value)
|
|||||||
asm volatile ("" ::: "memory");
|
asm volatile ("" ::: "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void * read_file(const char * filename)
|
static void * read_file(const char * filename, int * out_size)
|
||||||
{
|
{
|
||||||
int fd = open(filename, O_RDONLY);
|
int fd = open(filename, O_RDONLY);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
@ -74,6 +79,9 @@ static void * read_file(const char * filename)
|
|||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
|
if (out_size != NULL)
|
||||||
|
*out_size = size;
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +106,7 @@ union u32_f32 {
|
|||||||
|
|
||||||
static union u32_f32 ib[16384];
|
static union u32_f32 ib[16384];
|
||||||
|
|
||||||
int _3d_clear(int ix)
|
int _3d_clear(int ix, const struct reloc_indices * reloc_indices)
|
||||||
{
|
{
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// ZB
|
// ZB
|
||||||
@ -118,7 +126,7 @@ int _3d_clear(int ix)
|
|||||||
|
|
||||||
T0V(ZB_DEPTHOFFSET, 0);
|
T0V(ZB_DEPTHOFFSET, 0);
|
||||||
T3(_NOP, 0);
|
T3(_NOP, 0);
|
||||||
ib[ix++].u32 = 1 * 4; // index into relocs array
|
ib[ix++].u32 = reloc_indices->zbuffer * 4; // index into relocs array
|
||||||
|
|
||||||
T0V(ZB_DEPTHPITCH
|
T0V(ZB_DEPTHPITCH
|
||||||
, ZB_DEPTHPITCH__DEPTHPITCH(1600 >> 2)
|
, ZB_DEPTHPITCH__DEPTHPITCH(1600 >> 2)
|
||||||
@ -126,7 +134,7 @@ int _3d_clear(int ix)
|
|||||||
| ZB_DEPTHPITCH__DEPTHMICROTILE(1)
|
| ZB_DEPTHPITCH__DEPTHMICROTILE(1)
|
||||||
);
|
);
|
||||||
T3(_NOP, 0);
|
T3(_NOP, 0);
|
||||||
ib[ix++].u32 = 1 * 4; // index into relocs array
|
ib[ix++].u32 = reloc_indices->zbuffer * 4; // index into relocs array
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// RS
|
// RS
|
||||||
@ -209,35 +217,6 @@ int _3d_clear(int ix)
|
|||||||
T0V(VAP_OUT_VTX_FMT_1
|
T0V(VAP_OUT_VTX_FMT_1
|
||||||
, 0x0);
|
, 0x0);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 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 * 0);
|
|
||||||
ib[ix++].u32 // VAP_VTX_AOS_ADDR1
|
|
||||||
= (4 * 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 = 3 * 4; // index into relocs array for VAP_VTX_AOS_ADDR0
|
|
||||||
T3(_NOP, 0);
|
|
||||||
ib[ix++].u32 = 3 * 4; // index into relocs array for VAP_VTX_AOS_ADDR1
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// GA_US
|
// GA_US
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@ -278,7 +257,9 @@ int _3d_clear(int ix)
|
|||||||
return ix;
|
return ix;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _3d_object(int ix, float theta, int vertex_count)
|
int _3d_object(int ix, const struct reloc_indices * reloc_indices,
|
||||||
|
float theta,
|
||||||
|
int vertex_count)
|
||||||
{
|
{
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// ZB
|
// ZB
|
||||||
@ -298,7 +279,7 @@ int _3d_object(int ix, float theta, int vertex_count)
|
|||||||
|
|
||||||
T0V(ZB_DEPTHOFFSET, 0);
|
T0V(ZB_DEPTHOFFSET, 0);
|
||||||
T3(_NOP, 0);
|
T3(_NOP, 0);
|
||||||
ib[ix++].u32 = 1 * 4; // index into relocs array
|
ib[ix++].u32 = reloc_indices->zbuffer * 4; // index into relocs array
|
||||||
|
|
||||||
T0V(ZB_DEPTHPITCH
|
T0V(ZB_DEPTHPITCH
|
||||||
, ZB_DEPTHPITCH__DEPTHPITCH(1600 >> 2)
|
, ZB_DEPTHPITCH__DEPTHPITCH(1600 >> 2)
|
||||||
@ -306,7 +287,7 @@ int _3d_object(int ix, float theta, int vertex_count)
|
|||||||
| ZB_DEPTHPITCH__DEPTHMICROTILE(1)
|
| ZB_DEPTHPITCH__DEPTHMICROTILE(1)
|
||||||
);
|
);
|
||||||
T3(_NOP, 0);
|
T3(_NOP, 0);
|
||||||
ib[ix++].u32 = 1 * 4; // index into relocs array
|
ib[ix++].u32 = reloc_indices->zbuffer * 4; // index into relocs array
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// RS
|
// RS
|
||||||
@ -372,7 +353,7 @@ int _3d_object(int ix, float theta, int vertex_count)
|
|||||||
);
|
);
|
||||||
|
|
||||||
T3(_NOP, 0);
|
T3(_NOP, 0);
|
||||||
ib[ix++].u32 = 2 * 4; // index into relocs array
|
ib[ix++].u32 = reloc_indices->texturebuffer * 4; // index into relocs array
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// VAP_PVS
|
// VAP_PVS
|
||||||
@ -491,6 +472,35 @@ int _3d_object(int ix, float theta, int vertex_count)
|
|||||||
| US_CODE_ADDR__END_ADDR(fragment_shader_instructions - 1)
|
| US_CODE_ADDR__END_ADDR(fragment_shader_instructions - 1)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 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 * 0);
|
||||||
|
ib[ix++].u32 // VAP_VTX_AOS_ADDR1
|
||||||
|
= (4 * 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
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// 3D_DRAW
|
// 3D_DRAW
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@ -509,7 +519,7 @@ int _3d_object(int ix, float theta, int vertex_count)
|
|||||||
return ix;
|
return ix;
|
||||||
}
|
}
|
||||||
|
|
||||||
int indirect_buffer(float theta, int vertex_count)
|
int indirect_buffer(float theta, int vertex_count, const struct reloc_indices * reloc_indices)
|
||||||
{
|
{
|
||||||
int ix = 0;
|
int ix = 0;
|
||||||
|
|
||||||
@ -753,7 +763,7 @@ int indirect_buffer(float theta, int vertex_count)
|
|||||||
, 0x00000000 // value replaced by kernel from relocs
|
, 0x00000000 // value replaced by kernel from relocs
|
||||||
);
|
);
|
||||||
T3(_NOP, 0);
|
T3(_NOP, 0);
|
||||||
ib[ix++].u32 = 0 * 4; // index into relocs array
|
ib[ix++].u32 = reloc_indices->colorbuffer * 4; // index into relocs array
|
||||||
|
|
||||||
T0V(RB3D_COLORPITCH0
|
T0V(RB3D_COLORPITCH0
|
||||||
, RB3D_COLORPITCH__COLORPITCH(1600 >> 1)
|
, RB3D_COLORPITCH__COLORPITCH(1600 >> 1)
|
||||||
@ -762,7 +772,7 @@ int indirect_buffer(float theta, int vertex_count)
|
|||||||
// The COLORPITCH NOP is ignored/not applied due to
|
// The COLORPITCH NOP is ignored/not applied due to
|
||||||
// RADEON_CS_KEEP_TILING_FLAGS, but is still required.
|
// RADEON_CS_KEEP_TILING_FLAGS, but is still required.
|
||||||
T3(_NOP, 0);
|
T3(_NOP, 0);
|
||||||
ib[ix++].u32 = 0 * 4; // index into relocs array
|
ib[ix++].u32 = reloc_indices->colorbuffer * 4; // index into relocs array
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// SC
|
// SC
|
||||||
@ -825,8 +835,8 @@ int indirect_buffer(float theta, int vertex_count)
|
|||||||
// DRAW
|
// DRAW
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ix = _3d_clear(ix);
|
ix = _3d_clear(ix, reloc_indices);
|
||||||
ix = _3d_object(ix, theta, vertex_count);
|
ix = _3d_object(ix, reloc_indices, theta, vertex_count);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// padding
|
// padding
|
||||||
@ -896,31 +906,93 @@ int fill_vertexbuffer(void * ptr, int size)
|
|||||||
|
|
||||||
int ix = 0;
|
int ix = 0;
|
||||||
|
|
||||||
const struct model * model = &pumpkin_model;
|
const int object_count = (sizeof (objects)) / (sizeof (objects[0]));
|
||||||
|
for (int object_ix = 0; object_ix < object_count; object_ix++) {
|
||||||
|
const struct mesh * mesh = objects[object_ix].mesh;
|
||||||
|
|
||||||
for (int i = 0; i < model->object_count; i++) {
|
assert(mesh->uv_layers_length == 1);
|
||||||
const struct object * object = model->object[i];
|
const vec2 * uvmap = mesh->uv_layers[0];
|
||||||
for (int j = 0; j < object->triangle_count; j++) {
|
const vec3 * position = mesh->position;
|
||||||
const union triangle * triangle = &object->triangle[j];
|
for (int polygon_ix = 0; polygon_ix < mesh->polygons_length; polygon_ix++) {
|
||||||
for (int k = 0; k < 3; k++) {
|
|
||||||
const struct vec3 * p = &model->position[triangle->v[k].position];
|
|
||||||
const struct vec2 * t = &model->texture[triangle->v[k].texture];
|
|
||||||
|
|
||||||
assert((ix + 5) < (size / 4));
|
int uv_ix = polygon_ix * 3;
|
||||||
|
const struct polygon * polygon = &mesh->polygons[polygon_ix];
|
||||||
|
const vec3 * ap = &position[polygon->a];
|
||||||
|
const vec3 * bp = &position[polygon->b];
|
||||||
|
const vec3 * cp = &position[polygon->c];
|
||||||
|
const vec2 * at = &uvmap[uv_ix + 0];
|
||||||
|
const vec2 * bt = &uvmap[uv_ix + 1];
|
||||||
|
const vec2 * ct = &uvmap[uv_ix + 2];
|
||||||
|
|
||||||
fptr[ix++] = p->x;
|
assert((ix + (5 * 3)) < (size / 4));
|
||||||
fptr[ix++] = p->y;
|
|
||||||
fptr[ix++] = p->z;
|
fptr[ix++] = ap->x;
|
||||||
fptr[ix++] = t->x;
|
fptr[ix++] = ap->y;
|
||||||
fptr[ix++] = t->y;
|
fptr[ix++] = ap->z;
|
||||||
}
|
fptr[ix++] = at->x;
|
||||||
|
fptr[ix++] = 1.0f - at->y;
|
||||||
|
|
||||||
|
fptr[ix++] = bp->x;
|
||||||
|
fptr[ix++] = bp->y;
|
||||||
|
fptr[ix++] = bp->z;
|
||||||
|
fptr[ix++] = bt->x;
|
||||||
|
fptr[ix++] = 1.0f - bt->y;
|
||||||
|
|
||||||
|
fptr[ix++] = cp->x;
|
||||||
|
fptr[ix++] = cp->y;
|
||||||
|
fptr[ix++] = cp->z;
|
||||||
|
fptr[ix++] = ct->x;
|
||||||
|
fptr[ix++] = 1.0f - ct->y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
asm volatile("" ::: "memory");
|
asm volatile("" ::: "memory");
|
||||||
|
|
||||||
return ix;
|
return ix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int * load_textures(int fd, int * length_out)
|
||||||
|
{
|
||||||
|
int * texture_handles = NULL;
|
||||||
|
|
||||||
|
const int materials_length = (sizeof (materials)) / (sizeof (materials[0]));
|
||||||
|
|
||||||
|
texture_handles = (int *)calloc((sizeof (int)), materials_length);
|
||||||
|
|
||||||
|
char buf[512];
|
||||||
|
for (int i = 0; i < materials_length; i++) {
|
||||||
|
assert(strlen(materials[i].name) < 300);
|
||||||
|
snprintf(buf, (sizeof (buf)), "../model/pumpkin/textures/%s.data", materials[i].name);
|
||||||
|
|
||||||
|
int size = 0;
|
||||||
|
void * file_ptr = read_file(buf, &size);
|
||||||
|
assert(file_ptr != NULL);
|
||||||
|
assert(size > 0);
|
||||||
|
|
||||||
|
printf("load %s %d\n", buf, size);
|
||||||
|
|
||||||
|
assert(materials[i].texture_id < materials_length);
|
||||||
|
assert(texture_handles[materials[i].texture_id] == 0);
|
||||||
|
|
||||||
|
void * buffer_ptr;
|
||||||
|
int handle = create_colorbuffer(fd, size, &buffer_ptr);
|
||||||
|
for (int i = 0; i < size / 4; i++) {
|
||||||
|
((uint32_t *)buffer_ptr)[i] = ((uint32_t *)file_ptr)[i];
|
||||||
|
}
|
||||||
|
asm volatile ("" ::: "memory");
|
||||||
|
|
||||||
|
free(file_ptr);
|
||||||
|
munmap(buffer_ptr, size);
|
||||||
|
|
||||||
|
texture_handles[materials[i].texture_id] = handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(length_out != NULL);
|
||||||
|
*length_out = materials_length;
|
||||||
|
|
||||||
|
return texture_handles;
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@ -948,7 +1020,6 @@ int main()
|
|||||||
|
|
||||||
int colorbuffer_handle[2];
|
int colorbuffer_handle[2];
|
||||||
int zbuffer_handle;
|
int zbuffer_handle;
|
||||||
int texturebuffer_handle;
|
|
||||||
int vertexbuffer_handle;
|
int vertexbuffer_handle;
|
||||||
int flush_handle;
|
int flush_handle;
|
||||||
|
|
||||||
@ -968,54 +1039,10 @@ int main()
|
|||||||
int vertexbuffer_length = fill_vertexbuffer(vertexbuffer_ptr, vertexbuffer_size);
|
int vertexbuffer_length = fill_vertexbuffer(vertexbuffer_ptr, vertexbuffer_size);
|
||||||
munmap(vertexbuffer_ptr, vertexbuffer_size);
|
munmap(vertexbuffer_ptr, vertexbuffer_size);
|
||||||
fprintf(stderr, "vertexbuffer length %d\n", vertexbuffer_length);
|
fprintf(stderr, "vertexbuffer length %d\n", vertexbuffer_length);
|
||||||
|
|
||||||
int vertex_count = vertexbuffer_length / 5;
|
int vertex_count = vertexbuffer_length / 5;
|
||||||
|
|
||||||
// texture
|
int texture_handles_length = 0;
|
||||||
{
|
int * texture_handles = load_textures(fd, &texture_handles_length);
|
||||||
const int texture_size = 1024 * 1024 * 4;
|
|
||||||
|
|
||||||
struct drm_radeon_gem_create args = {
|
|
||||||
.size = texture_size,
|
|
||||||
.alignment = 4096,
|
|
||||||
.handle = 0,
|
|
||||||
.initial_domain = 4, // RADEON_GEM_DOMAIN_VRAM
|
|
||||||
.flags = 4
|
|
||||||
};
|
|
||||||
|
|
||||||
ret = drmCommandWriteRead(fd, DRM_RADEON_GEM_CREATE, &args, (sizeof (struct drm_radeon_gem_create)));
|
|
||||||
if (ret != 0) {
|
|
||||||
perror("drmCommandWriteRead(DRM_RADEON_GEM_CREATE)");
|
|
||||||
}
|
|
||||||
assert(args.handle != 0);
|
|
||||||
|
|
||||||
texturebuffer_handle = args.handle;
|
|
||||||
|
|
||||||
struct drm_radeon_gem_mmap mmap_args = {
|
|
||||||
.handle = texturebuffer_handle,
|
|
||||||
.offset = 0,
|
|
||||||
.size = texture_size,
|
|
||||||
};
|
|
||||||
ret = drmCommandWriteRead(fd, DRM_RADEON_GEM_MMAP, &mmap_args, (sizeof (struct drm_radeon_gem_mmap)));
|
|
||||||
if (ret != 0) {
|
|
||||||
perror("drmCommandWriteRead(DRM_RADEON_GEM_MMAP)");
|
|
||||||
}
|
|
||||||
|
|
||||||
void * texturebuffer_ptr = mmap(0, mmap_args.size, PROT_READ|PROT_WRITE, MAP_SHARED,
|
|
||||||
fd, mmap_args.addr_ptr);
|
|
||||||
assert(texturebuffer_ptr != MAP_FAILED);
|
|
||||||
|
|
||||||
// copy texture
|
|
||||||
void * texture_buf = read_file("../texture/butterfly_1024x1024_argb8888.data");
|
|
||||||
assert(texture_buf != NULL);
|
|
||||||
|
|
||||||
for (int i = 0; i < texture_size / 4; i++) {
|
|
||||||
((uint32_t*)texturebuffer_ptr)[i] = ((uint32_t*)texture_buf)[i];
|
|
||||||
}
|
|
||||||
asm volatile ("" ::: "memory");
|
|
||||||
free(texture_buf);
|
|
||||||
munmap(texturebuffer_ptr, texture_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// flush
|
// flush
|
||||||
{
|
{
|
||||||
@ -1041,45 +1068,59 @@ int main()
|
|||||||
0, // RADEON_CS_RING_GFX
|
0, // RADEON_CS_RING_GFX
|
||||||
};
|
};
|
||||||
|
|
||||||
int ib_dwords = indirect_buffer(0, vertex_count);
|
|
||||||
|
|
||||||
int colorbuffer_ix = 0;
|
int colorbuffer_ix = 0;
|
||||||
float theta = 0;
|
float theta = 0;
|
||||||
|
|
||||||
while (true) {
|
int relocs_length = 4 + texture_handles_length;
|
||||||
struct drm_radeon_cs_reloc relocs[] = {
|
struct drm_radeon_cs_reloc * relocs = calloc((sizeof (struct drm_radeon_cs_reloc)), relocs_length);
|
||||||
{
|
int relocs_size = (sizeof (struct drm_radeon_cs_reloc)) * relocs_length;
|
||||||
.handle = colorbuffer_handle[colorbuffer_ix],
|
|
||||||
.read_domains = 4, // RADEON_GEM_DOMAIN_VRAM
|
const struct reloc_indices reloc_indices = {
|
||||||
.write_domain = 4, // RADEON_GEM_DOMAIN_VRAM
|
.colorbuffer = 0,
|
||||||
.flags = 8,
|
.zbuffer = 1,
|
||||||
},
|
.vertexbuffer = 2,
|
||||||
{
|
.texturebuffer = 3,
|
||||||
|
.flush = relocs_length - 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
relocs[reloc_indices.zbuffer] = (struct drm_radeon_cs_reloc){
|
||||||
.handle = zbuffer_handle,
|
.handle = zbuffer_handle,
|
||||||
.read_domains = 4, // RADEON_GEM_DOMAIN_VRAM
|
.read_domains = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||||
.write_domain = 4, // RADEON_GEM_DOMAIN_VRAM
|
.write_domain = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||||
.flags = 8,
|
.flags = 8,
|
||||||
},
|
};
|
||||||
{
|
relocs[reloc_indices.vertexbuffer] = (struct drm_radeon_cs_reloc){
|
||||||
.handle = texturebuffer_handle,
|
|
||||||
.read_domains = 4, // RADEON_GEM_DOMAIN_VRAM
|
|
||||||
.write_domain = 4, // RADEON_GEM_DOMAIN_VRAM
|
|
||||||
.flags = 8,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.handle = vertexbuffer_handle,
|
.handle = vertexbuffer_handle,
|
||||||
.read_domains = 4, // RADEON_GEM_DOMAIN_VRAM
|
.read_domains = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||||
.write_domain = 4, // RADEON_GEM_DOMAIN_VRAM
|
.write_domain = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||||
.flags = 8,
|
.flags = 8,
|
||||||
},
|
};
|
||||||
{
|
relocs[reloc_indices.flush] = (struct drm_radeon_cs_reloc){
|
||||||
.handle = flush_handle,
|
.handle = flush_handle,
|
||||||
.read_domains = 2, // RADEON_GEM_DOMAIN_GTT
|
.read_domains = 2, // RADEON_GEM_DOMAIN_GTT
|
||||||
.write_domain = 2, // RADEON_GEM_DOMAIN_GTT
|
.write_domain = 2, // RADEON_GEM_DOMAIN_GTT
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < texture_handles_length; i++) {
|
||||||
|
relocs[reloc_indices.texturebuffer + i] = (struct drm_radeon_cs_reloc){
|
||||||
|
.handle = texture_handles[i],
|
||||||
|
.read_domains = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||||
|
.write_domain = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||||
|
.flags = 8,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
relocs[reloc_indices.colorbuffer] = (struct drm_radeon_cs_reloc){
|
||||||
|
.handle = colorbuffer_handle[colorbuffer_ix],
|
||||||
|
.read_domains = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||||
|
.write_domain = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||||
|
.flags = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
int ib_dwords = indirect_buffer(theta, vertex_count, &reloc_indices);
|
||||||
|
|
||||||
struct drm_radeon_cs_chunk chunks[3] = {
|
struct drm_radeon_cs_chunk chunks[3] = {
|
||||||
{
|
{
|
||||||
.chunk_id = RADEON_CHUNK_ID_IB,
|
.chunk_id = RADEON_CHUNK_ID_IB,
|
||||||
@ -1088,7 +1129,7 @@ int main()
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
.chunk_id = RADEON_CHUNK_ID_RELOCS,
|
.chunk_id = RADEON_CHUNK_ID_RELOCS,
|
||||||
.length_dw = (sizeof (relocs)) / (sizeof (uint32_t)),
|
.length_dw = relocs_size / (sizeof (uint32_t)),
|
||||||
.chunk_data = (uint64_t)(uintptr_t)relocs,
|
.chunk_data = (uint64_t)(uintptr_t)relocs,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1147,9 +1188,6 @@ int main()
|
|||||||
// next state
|
// next state
|
||||||
theta += 0.01f;
|
theta += 0.01f;
|
||||||
colorbuffer_ix = (colorbuffer_ix + 1) & 1;
|
colorbuffer_ix = (colorbuffer_ix + 1) & 1;
|
||||||
|
|
||||||
// next indirect buffer
|
|
||||||
ib_dwords = indirect_buffer(theta, vertex_count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -57,12 +57,14 @@ union u32_f32 {
|
|||||||
float f32;
|
float f32;
|
||||||
};
|
};
|
||||||
|
|
||||||
static union u32_f32 ib[16384];
|
static union u32_f32 ib[16384 * 20];
|
||||||
|
|
||||||
int indirect_buffer(int ix,
|
int indirect_buffer(int ix,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
int colorbuffer_reloc_ix,
|
int colorbuffer_reloc_ix,
|
||||||
|
int texture_width,
|
||||||
|
int texture_height,
|
||||||
int texturebuffer_reloc_ix,
|
int texturebuffer_reloc_ix,
|
||||||
int shader_ix,
|
int shader_ix,
|
||||||
bool intermediate)
|
bool intermediate)
|
||||||
@ -479,9 +481,9 @@ int indirect_buffer(int ix,
|
|||||||
T0V(TX_ENABLE
|
T0V(TX_ENABLE
|
||||||
, TX_ENABLE__TEX_0_ENABLE__ENABLE);
|
, TX_ENABLE__TEX_0_ENABLE__ENABLE);
|
||||||
T0V(TX_FILTER0_0
|
T0V(TX_FILTER0_0
|
||||||
//, TX_FILTER0__CLAMP_S(2) // clamp to (0.0, 1.0)
|
, TX_FILTER0__CLAMP_S(2) // clamp to (0.0, 1.0)
|
||||||
//| TX_FILTER0__CLAMP_T(2) // clamp to (0.0, 1.0)
|
| TX_FILTER0__CLAMP_T(2) // clamp to (0.0, 1.0)
|
||||||
, TX_FILTER0__MAG_FILTER__POINT
|
| TX_FILTER0__MAG_FILTER__POINT
|
||||||
| TX_FILTER0__MIN_FILTER__POINT
|
| TX_FILTER0__MIN_FILTER__POINT
|
||||||
);
|
);
|
||||||
T0V(TX_FILTER1_0
|
T0V(TX_FILTER1_0
|
||||||
@ -489,8 +491,8 @@ int indirect_buffer(int ix,
|
|||||||
);
|
);
|
||||||
T0V(TX_BORDER_COLOR_0, 0);
|
T0V(TX_BORDER_COLOR_0, 0);
|
||||||
T0V(TX_FORMAT0_0
|
T0V(TX_FORMAT0_0
|
||||||
, TX_FORMAT0__TXWIDTH(128 - 1)
|
, TX_FORMAT0__TXWIDTH(texture_width - 1)
|
||||||
| TX_FORMAT0__TXHEIGHT(128 - 1)
|
| TX_FORMAT0__TXHEIGHT(texture_height - 1)
|
||||||
);
|
);
|
||||||
|
|
||||||
T0V(TX_FORMAT1_0
|
T0V(TX_FORMAT1_0
|
||||||
@ -563,8 +565,8 @@ int indirect_buffer(int ix,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const float fragment_consts[] = {
|
const float fragment_consts[] = {
|
||||||
-1.0f / 128.f, 1.0f / 128.f, -2.0f / 128.f, 2.0f / 128.f,
|
-1.0f / 1024.f, 1.0f / 1024.f, -2.0f / 1024.f, 2.0f / 1024.f,
|
||||||
-3.0f / 128.f, 3.0f / 128.f, 0.0f, 0.0f,
|
-3.0f / 1024.f, 3.0f / 1024.f, 0.0f, 0.0f,
|
||||||
0.24609375 + 0.021484375, 0.205078125, 0.1171875, 0.0439453125,
|
0.24609375 + 0.021484375, 0.205078125, 0.1171875, 0.0439453125,
|
||||||
};
|
};
|
||||||
int fragment_consts_length = (sizeof (fragment_consts)) / (sizeof (fragment_consts[0]));
|
int fragment_consts_length = (sizeof (fragment_consts)) / (sizeof (fragment_consts[0]));
|
||||||
@ -689,7 +691,7 @@ int main()
|
|||||||
int ret;
|
int ret;
|
||||||
int fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
|
int fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
|
||||||
|
|
||||||
const int texture_size = 128 * 128 * 4;
|
const int texture_size = 1024 * 1024 * 4;
|
||||||
const int colorbuffer_size = 1600 * 1200 * 4;
|
const int colorbuffer_size = 1600 * 1200 * 4;
|
||||||
int intermediate_handle[2];
|
int intermediate_handle[2];
|
||||||
int colorbuffer_handle;
|
int colorbuffer_handle;
|
||||||
@ -705,7 +707,7 @@ int main()
|
|||||||
intermediate_handle[1] = create_colorbuffer(fd, texture_size, NULL);
|
intermediate_handle[1] = create_colorbuffer(fd, texture_size, NULL);
|
||||||
|
|
||||||
{
|
{
|
||||||
void * texture_buf = read_file("../texture/butterfly_128x128_argb8888.data");
|
void * texture_buf = read_file("../texture/butterfly_1024x1024_argb8888.data");
|
||||||
assert(texture_buf != NULL);
|
assert(texture_buf != NULL);
|
||||||
for (int i = 0; i < texture_size / 4; i++) {
|
for (int i = 0; i < texture_size / 4; i++) {
|
||||||
((uint32_t*)texturebuffer_ptr)[i] = ((uint32_t*)texture_buf)[i];
|
((uint32_t*)texturebuffer_ptr)[i] = ((uint32_t*)texture_buf)[i];
|
||||||
@ -774,26 +776,30 @@ int main()
|
|||||||
0, // RADEON_CS_RING_GFX
|
0, // RADEON_CS_RING_GFX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int image_dim = 1024;
|
||||||
|
|
||||||
int ib_dwords = 0;
|
int ib_dwords = 0;
|
||||||
{
|
{
|
||||||
int texturebuffer_reloc_ix = 1;
|
int texturebuffer_reloc_ix = 1;
|
||||||
int colorbuffer_reloc_ix = 2;
|
int colorbuffer_reloc_ix = 2;
|
||||||
int shader_ix = 0;
|
int shader_ix = 0;
|
||||||
ib_dwords = indirect_buffer(ib_dwords,
|
ib_dwords = indirect_buffer(ib_dwords,
|
||||||
128, 128,
|
image_dim, image_dim,
|
||||||
colorbuffer_reloc_ix,
|
colorbuffer_reloc_ix,
|
||||||
|
image_dim, image_dim,
|
||||||
texturebuffer_reloc_ix,
|
texturebuffer_reloc_ix,
|
||||||
shader_ix,
|
shader_ix,
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 40; i++) {
|
||||||
{
|
{
|
||||||
int texturebuffer_reloc_ix = 2;
|
int texturebuffer_reloc_ix = 2;
|
||||||
int colorbuffer_reloc_ix = 3;
|
int colorbuffer_reloc_ix = 3;
|
||||||
int shader_ix = 1;
|
int shader_ix = 1;
|
||||||
ib_dwords = indirect_buffer(ib_dwords,
|
ib_dwords = indirect_buffer(ib_dwords,
|
||||||
128, 128,
|
image_dim, image_dim,
|
||||||
colorbuffer_reloc_ix,
|
colorbuffer_reloc_ix,
|
||||||
|
image_dim, image_dim,
|
||||||
texturebuffer_reloc_ix,
|
texturebuffer_reloc_ix,
|
||||||
shader_ix,
|
shader_ix,
|
||||||
true);
|
true);
|
||||||
@ -803,8 +809,9 @@ int main()
|
|||||||
int colorbuffer_reloc_ix = 2;
|
int colorbuffer_reloc_ix = 2;
|
||||||
int shader_ix = 0;
|
int shader_ix = 0;
|
||||||
ib_dwords = indirect_buffer(ib_dwords,
|
ib_dwords = indirect_buffer(ib_dwords,
|
||||||
128, 128,
|
image_dim, image_dim,
|
||||||
colorbuffer_reloc_ix,
|
colorbuffer_reloc_ix,
|
||||||
|
image_dim, image_dim,
|
||||||
texturebuffer_reloc_ix,
|
texturebuffer_reloc_ix,
|
||||||
shader_ix,
|
shader_ix,
|
||||||
true);
|
true);
|
||||||
@ -817,6 +824,7 @@ int main()
|
|||||||
ib_dwords = indirect_buffer(ib_dwords,
|
ib_dwords = indirect_buffer(ib_dwords,
|
||||||
1600, 1200,
|
1600, 1200,
|
||||||
colorbuffer_reloc_ix,
|
colorbuffer_reloc_ix,
|
||||||
|
image_dim, image_dim,
|
||||||
texturebuffer_reloc_ix,
|
texturebuffer_reloc_ix,
|
||||||
shader_ix,
|
shader_ix,
|
||||||
false);
|
false);
|
||||||
|
|||||||
54
model/blender_model.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct polygon {
|
||||||
|
int a, b, c;
|
||||||
|
int material_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mesh_material {
|
||||||
|
const int width;
|
||||||
|
const int height;
|
||||||
|
const int texture_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct edge {
|
||||||
|
int a; // vertices index
|
||||||
|
int b; // vertices index
|
||||||
|
};
|
||||||
|
|
||||||
|
struct edge_polygon {
|
||||||
|
struct edge edge;
|
||||||
|
struct {
|
||||||
|
int a;
|
||||||
|
int b;
|
||||||
|
} polygon_index; // polygon indices
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mesh {
|
||||||
|
const vec3 * position;
|
||||||
|
const int position_length;
|
||||||
|
const vec3 * normal;
|
||||||
|
const int normal_length;
|
||||||
|
const vec3 * polygon_normal;
|
||||||
|
const int polygon_normal_length;
|
||||||
|
const struct polygon * polygons;
|
||||||
|
const int polygons_length;
|
||||||
|
const vec2 ** uv_layers;
|
||||||
|
const int uv_layers_length;
|
||||||
|
const struct mesh_material * materials;
|
||||||
|
const int materials_length;
|
||||||
|
const struct edge_polygon * edge_polygons;
|
||||||
|
const int edge_polygons_length;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct object {
|
||||||
|
const struct mesh * mesh;
|
||||||
|
vec3 scale;
|
||||||
|
vec4 rotation;
|
||||||
|
vec3 location;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct material {
|
||||||
|
const char * name;
|
||||||
|
const int texture_id;
|
||||||
|
};
|
||||||
@ -1,15 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
struct vec3 {
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
float z;
|
|
||||||
};
|
|
||||||
struct vec2 {
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct vec3 vertex_position;
|
typedef struct vec3 vertex_position;
|
||||||
typedef struct vec2 vertex_texture;
|
typedef struct vec2 vertex_texture;
|
||||||
typedef struct vec3 vertex_normal;
|
typedef struct vec3 vertex_normal;
|
||||||
|
|||||||
79669
model/pumpkin/pumpkin.h
BIN
model/pumpkin/textures/Untitled.data
Normal file
BIN
model/pumpkin/textures/Untitled.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
model/pumpkin/textures/armtext.data
Normal file
BIN
model/pumpkin/textures/armtext.png
Normal file
|
After Width: | Height: | Size: 218 KiB |
BIN
model/pumpkin/textures/bellytexture.data
Normal file
BIN
model/pumpkin/textures/bellytexture.png
Normal file
|
After Width: | Height: | Size: 158 KiB |
BIN
model/pumpkin/textures/belttexture.data
Normal file
BIN
model/pumpkin/textures/belttexture.png
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
model/pumpkin/textures/chesttext.data
Normal file
BIN
model/pumpkin/textures/chesttext.png
Normal file
|
After Width: | Height: | Size: 248 KiB |
BIN
model/pumpkin/textures/eyetext.data
Normal file
BIN
model/pumpkin/textures/eyetext.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
model/pumpkin/textures/legtext.data
Normal file
BIN
model/pumpkin/textures/legtext.png
Normal file
|
After Width: | Height: | Size: 219 KiB |
3
model/pumpkin/textures/pumpkin.data
Normal file
BIN
model/pumpkin/textures/pumpkin.png
Normal file
|
After Width: | Height: | Size: 337 KiB |
19
model/vec.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef struct vec4 {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
float w;
|
||||||
|
} vec4;
|
||||||
|
|
||||||
|
typedef struct vec3 {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
} vec3;
|
||||||
|
|
||||||
|
typedef struct vec2 {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
} vec2;
|
||||||
302
tools/blender.py
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
import bpy
|
||||||
|
from os import path
|
||||||
|
from collections import defaultdict
|
||||||
|
import bmesh
|
||||||
|
|
||||||
|
triangulate_meshes = True
|
||||||
|
|
||||||
|
def sprint(*text):
|
||||||
|
screen = bpy.data.screens['Scripting']
|
||||||
|
for area in screen.areas:
|
||||||
|
if area.type != "CONSOLE":
|
||||||
|
continue
|
||||||
|
override = {'screen': screen, 'area': area}
|
||||||
|
with bpy.context.temp_override(**override):
|
||||||
|
bpy.ops.console.scrollback_append(text=" ".join(map(str, text)))
|
||||||
|
|
||||||
|
print = sprint
|
||||||
|
|
||||||
|
def render_vec3(v):
|
||||||
|
return f"{{{v.x:.6f}, {v.y:.6f}, {v.z:.6f}}}"
|
||||||
|
|
||||||
|
def render_vec2(v):
|
||||||
|
return f"{{{v.x:.6f}, {v.y:.6f}}}"
|
||||||
|
|
||||||
|
def render_mesh_vertices(f, name, vertices):
|
||||||
|
f.write(f"static const vec3 {name}_position[] = {{\n")
|
||||||
|
for vertex in vertices:
|
||||||
|
f.write(f" {render_vec3(vertex.co)},\n")
|
||||||
|
f.write("};\n\n")
|
||||||
|
|
||||||
|
def render_vertex_normals(f, name, vertices):
|
||||||
|
f.write(f"static const vec3 {name}_normal[] = {{\n")
|
||||||
|
for vertex in vertices:
|
||||||
|
f.write(f" {render_vec3(vertex.normal)},\n")
|
||||||
|
f.write("};\n\n")
|
||||||
|
|
||||||
|
def render_polygon_normals(f, name, polygon_normals):
|
||||||
|
f.write(f"static const vec3 {name}_polygon_normal[] = {{\n")
|
||||||
|
for normal in polygon_normals:
|
||||||
|
f.write(f" {render_vec3(normal.vector)},\n")
|
||||||
|
f.write("};\n\n")
|
||||||
|
|
||||||
|
def sort_by_material(polygons):
|
||||||
|
return sorted(polygons, key=lambda p: p.material_index)
|
||||||
|
|
||||||
|
def render_polygons(f, name, polygons):
|
||||||
|
f.write(f"static const struct polygon {name}_polygons[] = {{\n")
|
||||||
|
|
||||||
|
uv_ix = 0
|
||||||
|
for i, polygon in enumerate(polygons):
|
||||||
|
if triangulate_meshes:
|
||||||
|
assert len(polygon.vertices) == 3
|
||||||
|
|
||||||
|
if len(polygon.vertices) not in {3, 4}:
|
||||||
|
f.write(f" {{-1, -1, -1, -1, -1, -1}}, // {{{s}}}\n")
|
||||||
|
continue
|
||||||
|
|
||||||
|
if triangulate_meshes:
|
||||||
|
indices = [*polygon.vertices, polygon.material_index]
|
||||||
|
elif len(polygon.vertices) == 4:
|
||||||
|
indices = [*polygon.vertices, polygon.material_index, uv_ix]
|
||||||
|
else:
|
||||||
|
indices = [*polygon.vertices, -1, polygon.material_index, uv_ix]
|
||||||
|
|
||||||
|
uv_ix += len(polygon.vertices)
|
||||||
|
s = ", ".join(map(str, indices))
|
||||||
|
f.write(f" {{{s}}},\n")
|
||||||
|
|
||||||
|
f.write("};\n\n")
|
||||||
|
|
||||||
|
def render_polygon_edge_pairs(f, name, polygons):
|
||||||
|
by_edge = defaultdict(list)
|
||||||
|
for i, polygon in enumerate(polygons):
|
||||||
|
for edge in polygon.edge_keys:
|
||||||
|
by_edge[frozenset(edge)].append(i)
|
||||||
|
|
||||||
|
f.write(f"static const struct edge_polygon {name}_edge_polygons[] = {{\n")
|
||||||
|
if all(len(p) == 2 for p in by_edge.values()):
|
||||||
|
for edge, polygons in by_edge.items():
|
||||||
|
edges = sorted(list(edge))
|
||||||
|
assert len(edges) == 2, edges
|
||||||
|
assert len(polygons) == 2, polygons
|
||||||
|
f.write(f" {{{{{edges[0]}, {edges[1]}}}, {{{polygons[0]}, {polygons[1]}}}}},\n")
|
||||||
|
else:
|
||||||
|
f.write("// non-solid polygon\n")
|
||||||
|
f.write("};\n\n")
|
||||||
|
|
||||||
|
def render_uv_map(f, name, name2, uvm):
|
||||||
|
f.write(f"static const vec2 {name}_{name2}_uvmap[] = {{\n")
|
||||||
|
for uv in uvm:
|
||||||
|
s = render_vec2(uv.vector)
|
||||||
|
f.write(f" {s},\n")
|
||||||
|
f.write("};\n\n")
|
||||||
|
|
||||||
|
def render_location(f, location):
|
||||||
|
s = render_vec3(location)
|
||||||
|
f.write(f" .location = {s},\n")
|
||||||
|
|
||||||
|
def render_scale(f, scale):
|
||||||
|
s = render_vec3(scale)
|
||||||
|
f.write(f" .scale = {s},\n")
|
||||||
|
|
||||||
|
def render_rotation_axis_angle(f, r):
|
||||||
|
r = f"{{{r[1]:.6f}, {r[2]:.6f}, {r[3]:.6f}, {r[0]:.6f}}}"
|
||||||
|
f.write(f" .rotation = {r}, // rotation_axis_angle (XYZ T)\n")
|
||||||
|
|
||||||
|
def render_rotation_quaternion(f, r):
|
||||||
|
r = f"{{{r[1]:.6f}, {r[2]:.6f}, {r[3]:.6f}, {r[0]:.6f}}}"
|
||||||
|
f.write(f" .rotation = {r}, // quaternion (XYZW)\n")
|
||||||
|
|
||||||
|
def render_mesh(f, name, mesh):
|
||||||
|
f.write(f"static const vec2 * {name}_uv_layers[] = {{\n")
|
||||||
|
for layer_name in mesh.uv_layers.keys():
|
||||||
|
f.write(f" {name}_{translate_name(layer_name)}_uvmap,\n");
|
||||||
|
f.write( "};\n\n")
|
||||||
|
|
||||||
|
f.write(f"static const struct mesh {name} = {{\n")
|
||||||
|
f.write(f" .position = {name}_position,\n")
|
||||||
|
f.write(f" .position_length = (sizeof ({name}_position)) / (sizeof ({name}_position[0])),\n")
|
||||||
|
f.write(f" .normal = {name}_normal,\n")
|
||||||
|
f.write(f" .normal_length = (sizeof ({name}_normal)) / (sizeof ({name}_normal[0])),\n")
|
||||||
|
f.write(f" .polygon_normal = {name}_polygon_normal,\n")
|
||||||
|
f.write(f" .polygon_normal_length = (sizeof ({name}_polygon_normal)) / (sizeof ({name}_polygon_normal[0])),\n")
|
||||||
|
f.write(f" .polygons = {name}_polygons,\n")
|
||||||
|
f.write(f" .polygons_length = (sizeof ({name}_polygons)) / (sizeof ({name}_polygons[0])),\n")
|
||||||
|
f.write(f" .uv_layers = {name}_uv_layers,\n")
|
||||||
|
f.write(f" .uv_layers_length = (sizeof ({name}_uv_layers)) / (sizeof ({name}_uv_layers[0])),\n")
|
||||||
|
f.write(f" .materials = {name}_materials,\n")
|
||||||
|
f.write(f" .materials_length = (sizeof ({name}_materials)) / (sizeof ({name}_materials[0])),\n")
|
||||||
|
f.write(f" .edge_polygons = {name}_edge_polygons,\n");
|
||||||
|
f.write(f" .edge_polygons_length = (sizeof ({name}_edge_polygons)) / (sizeof ({name}_edge_polygons[0])),\n")
|
||||||
|
f.write( "};\n\n")
|
||||||
|
|
||||||
|
def translate_name(name):
|
||||||
|
return name.replace(".", "_").replace("-", "_").replace(" ", "_")
|
||||||
|
|
||||||
|
def mesh_objects(collections):
|
||||||
|
objects = set()
|
||||||
|
for collection in collections:
|
||||||
|
if collection.hide_render:
|
||||||
|
continue
|
||||||
|
for object in collection.objects:
|
||||||
|
assert object.name not in objects, object.name
|
||||||
|
objects.add(object.name)
|
||||||
|
if object.hide_render:
|
||||||
|
continue
|
||||||
|
if object.type == "MESH":
|
||||||
|
yield object
|
||||||
|
|
||||||
|
def mesh_meshes(collections):
|
||||||
|
mesh_names = set()
|
||||||
|
for object in mesh_objects(collections):
|
||||||
|
mesh = object.data
|
||||||
|
if mesh.name in mesh_names:
|
||||||
|
continue
|
||||||
|
mesh_names.add(mesh.name)
|
||||||
|
|
||||||
|
if not triangulate_meshes:
|
||||||
|
yield mesh.name, mesh
|
||||||
|
else:
|
||||||
|
# triangulate
|
||||||
|
tri_mesh = mesh.copy()
|
||||||
|
bm = bmesh.new()
|
||||||
|
bm.from_mesh(mesh)
|
||||||
|
bmesh.ops.triangulate(bm, faces=bm.faces[:])
|
||||||
|
bm.to_mesh(tri_mesh)
|
||||||
|
bm.free()
|
||||||
|
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)
|
||||||
|
return f"{prefix}{name}_data"
|
||||||
|
|
||||||
|
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)
|
||||||
|
if image is not None:
|
||||||
|
f.write(f" {{ // {material.name} {image.name}\n")
|
||||||
|
width, height = image.size
|
||||||
|
texture_id = get_texture_id(image)
|
||||||
|
f.write(f" .width = {width},\n")
|
||||||
|
f.write(f" .height = {height},\n")
|
||||||
|
f.write(f" .texture_id = {texture_id},\n")
|
||||||
|
f.write(" },\n")
|
||||||
|
else:
|
||||||
|
f.write(" {},\n")
|
||||||
|
f.write("};\n")
|
||||||
|
|
||||||
|
def render_materials(f):
|
||||||
|
f.write("static const struct material materials[] = {\n")
|
||||||
|
for image_name, texture_id in sorted(texture_ids.items(), key=lambda i: i[1]):
|
||||||
|
name = texture_data_name(image_name)
|
||||||
|
f.write(" {\n")
|
||||||
|
#f.write(f" .start = (void *)&_binary_{name}_start,\n")
|
||||||
|
#f.write(f" .size = (int)&_binary_{name}_size,\n")
|
||||||
|
f.write(f" .name = \"{image_name}\",\n")
|
||||||
|
f.write(f" .texture_id = {texture_id},\n")
|
||||||
|
f.write(" },\n")
|
||||||
|
f.write("};\n\n");
|
||||||
|
|
||||||
|
def export_meshes(f):
|
||||||
|
for mesh_name, mesh in mesh_meshes(bpy.data.collections):
|
||||||
|
#mesh.vertex_normals
|
||||||
|
#mesh.vertex_colors
|
||||||
|
#mesh.vertices
|
||||||
|
#mesh.uv_layers
|
||||||
|
#mesh.polygons
|
||||||
|
#mesh.polygon_normals
|
||||||
|
#mesh.name
|
||||||
|
|
||||||
|
mesh_name = "mesh_" + translate_name(mesh_name)
|
||||||
|
|
||||||
|
render_mesh_vertices(f, mesh_name, mesh.vertices)
|
||||||
|
for layer_name, layer in mesh.uv_layers.items():
|
||||||
|
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_polygon_edge_pairs(f, mesh_name, mesh.polygons)
|
||||||
|
render_mesh_materials(f, mesh_name, mesh.materials)
|
||||||
|
|
||||||
|
render_mesh(f, mesh_name, mesh)
|
||||||
|
|
||||||
|
#mesh.polygons[0].vertices
|
||||||
|
# [0, 1, 3, 2]
|
||||||
|
|
||||||
|
# v = mesh.vertices[0]
|
||||||
|
# v.normal
|
||||||
|
# v.index
|
||||||
|
|
||||||
|
def mesh_objects_sorted(objects):
|
||||||
|
def key(o):
|
||||||
|
return (o.data.name, o.name)
|
||||||
|
return sorted(mesh_objects(objects), key=key)
|
||||||
|
|
||||||
|
def export_objects(f):
|
||||||
|
f.write("static const struct object objects[] = {\n")
|
||||||
|
for object in mesh_objects_sorted(bpy.data.collections):
|
||||||
|
|
||||||
|
#object.rotation_mode = 'AXIS_ANGLE'
|
||||||
|
#object.name
|
||||||
|
#object.rotation_axis_angle
|
||||||
|
#object.rotation_euler
|
||||||
|
#object.location
|
||||||
|
|
||||||
|
obj_name = "object_" + translate_name(object.name)
|
||||||
|
|
||||||
|
f.write(f" {{ // {obj_name}\n")
|
||||||
|
|
||||||
|
obj_mesh_name = "mesh_" + translate_name(object.data.name)
|
||||||
|
|
||||||
|
f.write(" ")
|
||||||
|
f.write(f" .mesh = &{obj_mesh_name},\n")
|
||||||
|
|
||||||
|
location, rotation, scale = object.matrix_world.decompose()
|
||||||
|
f.write(" ")
|
||||||
|
render_scale(f, scale)
|
||||||
|
f.write(" ")
|
||||||
|
render_rotation_quaternion(f, rotation)
|
||||||
|
f.write(" ")
|
||||||
|
render_location(f, location)
|
||||||
|
|
||||||
|
f.write(" },\n")
|
||||||
|
f.write("};\n\n")
|
||||||
|
|
||||||
|
def export_scene(f):
|
||||||
|
export_meshes(f)
|
||||||
|
export_objects(f)
|
||||||
|
render_materials(f)
|
||||||
|
|
||||||
|
home = path.expanduser('~')
|
||||||
|
with open(path.join(home, "output.h"), "w") as f:
|
||||||
|
offset = 0
|
||||||
|
export_scene(f)
|
||||||
9
tools/png_to_data.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import sys
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
im = Image.open(sys.argv[1])
|
||||||
|
im = im.convert("RGBA")
|
||||||
|
buf = im.tobytes()
|
||||||
|
|
||||||
|
with open(sys.argv[2], 'wb') as f:
|
||||||
|
f.write(buf)
|
||||||