From d5ce251cad67df18392e5b0a733d22b137cc2a93 Mon Sep 17 00:00:00 2001 From: Dylan Whichard Date: Fri, 20 Oct 2023 13:44:32 -0700 Subject: [PATCH 01/11] Remove old duplicate hdw-accel --- components/hdw-accel/CMakeLists.txt | 3 - components/hdw-accel/hdw-accel.c | 289 ----------------------- components/hdw-accel/include/hdw-accel.h | 82 ------- 3 files changed, 374 deletions(-) delete mode 100644 components/hdw-accel/CMakeLists.txt delete mode 100644 components/hdw-accel/hdw-accel.c delete mode 100644 components/hdw-accel/include/hdw-accel.h diff --git a/components/hdw-accel/CMakeLists.txt b/components/hdw-accel/CMakeLists.txt deleted file mode 100644 index 421570635..000000000 --- a/components/hdw-accel/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -idf_component_register(SRCS "" - INCLUDE_DIRS "" - REQUIRES driver) diff --git a/components/hdw-accel/hdw-accel.c b/components/hdw-accel/hdw-accel.c deleted file mode 100644 index 7ff0a607d..000000000 --- a/components/hdw-accel/hdw-accel.c +++ /dev/null @@ -1,289 +0,0 @@ -//============================================================================== -// Includes -//============================================================================== - -#include - -#include "hdw-accel.h" - -//============================================================================== -// Enums -//============================================================================== - -typedef enum __attribute__((packed)) -{ - QMA7981_REG_CHIP_ID = 0x00, - QMA7981_REG_DX_L = 0x01, - QMA7981_REG_DX_H = 0x02, - QMA7981_REG_DY_L = 0x03, - QMA7981_REG_DY_H = 0x04, - QMA7981_REG_DZ_L = 0x05, - QMA7981_REG_DZ_H = 0x06, - QMA7981_REG_STEP_L = 0x07, - QMA7981_REG_STEP_H = 0x08, - QMA7981_REG_INT_STAT_0 = 0x0A, - QMA7981_REG_INT_STAT_1 = 0x0B, - QMA7981_REG_INT_STAT_4 = 0x0D, - QMA7981_REG_RANGE = 0x0F, - QMA7981_REG_BAND_WIDTH = 0x10, - QMA7981_REG_PWR_MANAGE = 0x11, - QMA7981_REG_STEP_CONF_0 = 0x12, - QMA7981_REG_STEP_CONF_1 = 0x13, - QMA7981_REG_STEP_CONF_2 = 0x14, - QMA7981_REG_STEP_CONF_3 = 0x15, - QMA7981_REG_INT_EN_0 = 0x16, - QMA7981_REG_INT_EN_1 = 0x17, - QMA7981_REG_INT_MAP_0 = 0x19, - QMA7981_REG_INT_MAP_1 = 0x1A, - QMA7981_REG_INT_MAP_2 = 0x1B, - QMA7981_REG_INT_MAP_3 = 0x1C, - QMA7981_REG_SIG_STEP_TH = 0x1D, - QMA7981_REG_STEP = 0x1F -} qmaReg_t; - -//============================================================================== -// Defines -//============================================================================== - -#define QMA7981_ADDR 0x12 - -//============================================================================== -// Variables -//============================================================================== - -static qma_range_t qma_range = QMA_RANGE_2G; -static i2c_port_t i2c_port; - -//============================================================================== -// Function Prototypes -//============================================================================== - -static esp_err_t qma7981_read_byte(qmaReg_t reg_addr, uint8_t* data); -static esp_err_t qma7981_write_byte(qmaReg_t reg_addr, uint8_t data); -static esp_err_t qma7981_read_bytes(qmaReg_t reg_addr, size_t data_len, uint8_t* data); -static int16_t signExtend10bit(uint16_t in); - -//============================================================================== -// Functions -//============================================================================== - -/** - * @brief Initialize the accelerometer - * - * @param _i2c_port The i2c port to use for the accelerometer - * @param sda The GPIO for the Serial DAta line - * @param scl The GPIO for the Serial CLock line - * @param pullup Either \c GPIO_PULLUP_DISABLE if there are external pullup resistors on SDA and SCL or \c - * GPIO_PULLUP_ENABLE if internal pull-ups should be used - * @param clkHz The frequency of the I2C clock - * @param range The range to measure, between ::QMA_RANGE_2G and ::QMA_RANGE_32G - * @param bandwidth The bandwidth to measure at, between ::QMA_BANDWIDTH_128_HZ and ::QMA_BANDWIDTH_1024_HZ - * @return ESP_OK if the accelerometer initialized, or a non-zero value if it did not - */ -esp_err_t initAccelerometer(i2c_port_t _i2c_port, gpio_num_t sda, gpio_num_t scl, gpio_pullup_t pullup, uint32_t clkHz, - qma_range_t range, qma_bandwidth_t bandwidth) -{ - i2c_port = _i2c_port; - esp_err_t ret_val = ESP_OK; - - /* Install i2c driver */ - i2c_config_t conf = { - .mode = I2C_MODE_MASTER, - .sda_io_num = sda, - .sda_pullup_en = pullup, - .scl_io_num = scl, - .scl_pullup_en = pullup, - .master.clk_speed = clkHz, - .clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL, - }; - ret_val |= i2c_param_config(i2c_port, &conf); - ret_val |= i2c_driver_install(i2c_port, conf.mode, 0, 0, 0); - - /* Exit sleep mode*/ - ret_val |= qma7981_write_byte(QMA7981_REG_PWR_MANAGE, 0xC0); - vTaskDelay(pdMS_TO_TICKS(20)); - - /* Set range */ - ret_val |= qma7981_write_byte(QMA7981_REG_RANGE, range); - /* Set bandwidth */ - ret_val |= qma7981_write_byte(QMA7981_REG_BAND_WIDTH, bandwidth); - - return ret_val; -} - -/** - * @brief Deinit the accelerometer (nothing to do) - * - * @return ESP_OK - */ -esp_err_t deInitAccelerometer(void) -{ - return ESP_OK; -} - -/** - * @brief Read a single byte from the accelerometer - * - * @param reg_addr The register to read from - * @param data The byte which was read is written here - * @return ESP_OK if the byte was read, or a non-zero value if it was not - */ -static esp_err_t qma7981_read_byte(qmaReg_t reg_addr, uint8_t* data) -{ - return qma7981_read_bytes(reg_addr, 1, data); -} - -/** - * @brief Read multiple bytes from the accelerometer - * - * @param reg_addr The register to read from - * @param data_len The number of bytes to read - * @param data The bytes which were read are written here - * @return ESP_OK if the bytes were read, or a non-zero value if they were not - */ -static esp_err_t qma7981_read_bytes(qmaReg_t reg_addr, size_t data_len, uint8_t* data) -{ - // Write the register to read from - i2c_cmd_handle_t cmdHandle = i2c_cmd_link_create(); - i2c_master_start(cmdHandle); - i2c_master_write_byte(cmdHandle, QMA7981_ADDR << 1 | I2C_MASTER_WRITE, false); - i2c_master_write_byte(cmdHandle, reg_addr, false); - i2c_master_stop(cmdHandle); - esp_err_t err = i2c_master_cmd_begin(i2c_port, cmdHandle, 100); - i2c_cmd_link_delete(cmdHandle); - - if (ESP_OK != err) - { - return err; - } - - // Read from the register - cmdHandle = i2c_cmd_link_create(); - i2c_master_start(cmdHandle); - i2c_master_write_byte(cmdHandle, QMA7981_ADDR << 1 | I2C_MASTER_READ, false); - i2c_master_read(cmdHandle, data, data_len, I2C_MASTER_LAST_NACK); - i2c_master_stop(cmdHandle); - err = i2c_master_cmd_begin(i2c_port, cmdHandle, 100); - i2c_cmd_link_delete(cmdHandle); - - return err; -} - -/** - * @brief Write a single byte to the accelerometer - * - * @param reg_addr The register address to write to - * @param data The byte to write - * @return ESP_OK if the byte was written, or a non-zero value if it was not - */ -static esp_err_t qma7981_write_byte(qmaReg_t reg_addr, uint8_t data) -{ - i2c_cmd_handle_t cmdHandle = i2c_cmd_link_create(); - i2c_master_start(cmdHandle); - - i2c_master_write_byte(cmdHandle, QMA7981_ADDR << 1, false); - i2c_master_write_byte(cmdHandle, reg_addr, false); - i2c_master_write_byte(cmdHandle, data, false); - - i2c_master_stop(cmdHandle); - esp_err_t err = i2c_master_cmd_begin(i2c_port, cmdHandle, 100); - i2c_cmd_link_delete(cmdHandle); - return err; -} - -/** - * @brief Read and return the 16-bit step counter - * - * Note that this can be configured with ::QMA7981_REG_STEP_CONF_0 through ::QMA7981_REG_STEP_CONF_3 - * - * @param data The step counter value is written here - * @return ESP_OK if the step count was read, or a non-zero value if it was not - */ -esp_err_t accelGetStep(uint16_t* data) -{ - esp_err_t ret_val = ESP_OK; - uint8_t step_h = 0, step_l = 0; - - if (NULL == data) - { - return ESP_ERR_INVALID_ARG; - } - - ret_val |= qma7981_read_byte(QMA7981_REG_STEP_L, &step_l); - ret_val |= qma7981_read_byte(QMA7981_REG_STEP_H, &step_h); - - *data = (step_h << 8) + step_l; - - return ret_val; -} - -/** - * @brief Set the accelerometer's measurement range - * - * @param range The range to measure, from ::QMA_RANGE_2G to ::QMA_RANGE_32G - * @return ESP_OK if the range was set, or a non-zero value if it was not - */ -esp_err_t accelSetRange(qma_range_t range) -{ - esp_err_t ret_val = qma7981_write_byte(QMA7981_REG_RANGE, range); - qma_range = range; - - return ret_val; -} - -/** - * @brief Read the current acceleration vector from the accelerometer and return - * the vector through arguments. If the read fails, the last known values are - * returned instead. - * - * @param x The X component of the acceleration vector is written here - * @param y The Y component of the acceleration vector is written here - * @param z The Z component of the acceleration vector is written here - * @return ESP_OK if the acceleration was read, or a non-zero value if it was not - */ -esp_err_t accelGetAccelVec(int16_t* x, int16_t* y, int16_t* z) -{ - static int16_t lastX = 0; - static int16_t lastY = 0; - static int16_t lastZ = 0; - - // Read 6 bytes of data(0x00) - uint8_t raw_data[6]; - // Do the read - esp_err_t ret_val = qma7981_read_bytes(QMA7981_REG_DX_L, 6, raw_data); - - // If the read was successful - if (ESP_OK == ret_val) - { - // Sign extend the 10 bit value to 16 bits and save it as the last known value - // TODO The datasheet mentions this is a 14 bit reading, not a 10 bit one? - lastX = signExtend10bit(((raw_data[0] >> 6) | (raw_data[1]) << 2) & 0x03FF); - lastY = -signExtend10bit(((raw_data[2] >> 6) | (raw_data[3]) << 2) & 0x03FF); - lastZ = -signExtend10bit(((raw_data[4] >> 6) | (raw_data[5]) << 2) & 0x03FF); - } - - // Copy out the acceleration value - *x = lastX; - *y = lastY; - *z = lastZ; - - return ret_val; -} - -/** - * @brief Helper function to sign-extend a 10 bit two's complement number to 16 bit - * - * @param in The two's compliment number to sign-extend - * @return The sign-extended two's compliment number - */ -static int16_t signExtend10bit(uint16_t in) -{ - if (in & 0x200) - { - return (in | 0xFC00); // extend the sign bit all the way out - } - else - { - return (in & 0x01FF); // make sure the sign bits are cleared - } -} diff --git a/components/hdw-accel/include/hdw-accel.h b/components/hdw-accel/include/hdw-accel.h deleted file mode 100644 index 2aa8f7312..000000000 --- a/components/hdw-accel/include/hdw-accel.h +++ /dev/null @@ -1,82 +0,0 @@ -/*! \file hdw-accel.h - * - * \section accel_design Design Philosophy - * - * The accelerometer used is a QMA7981. - * The datasheet can be found here: QMA7981 - * Datasheet. - * - * The accelerometer component does not automatically poll the accelerometer. - * All it does is set up and configure the accelerometer, then it is up to the Swadge mode to query for acceleration as - * appropriate. - * - * This component requires the I2C bus to be initialized, so it does that as well. - * If other I2C peripherals are added in the future, common I2C bus initialization should be moved to a more common - * location. - * - * \section accel_usage Usage - * - * You don't need to call initAccelerometer() or deInitAccelerometer(). The system does this the appropriate time. - * - * You do need to call accelGetAccelVec() to get the current acceleration vector. - * If you want to poll this from your Swadge mode's main function, you may. - * - * You may call accelSetRange() if you want to adjust the measurement range. - * - * accelGetStep() exists, but it has not been tested, so use it with caution. - * You may need to configure parameters related to step counting. - * - * \section accel_example Example - * - * \code{.c} - * // Declare variables to receive acceleration - * int16_t a_x, a_y, a_z; - * - * // Get the current acceleration - * if(ESP_OK == accelGetAccelVec(&a_x, &a_y, &a_z)) - * { - * // Print data to debug logs - * printf("x: %"PRId16", y: %"PRId16", z:%"PRId16, a_x, a_y, a_z); - * } - * \endcode - */ - -#ifndef _HDW_ACCEL_H_ -#define _HDW_ACCEL_H_ - -#include - -#include -#include -#include - -/** - * @brief The ranges for acceleration measurement from 2G to 32G (Earth gravity) - */ -typedef enum -{ - QMA_RANGE_2G = 0b0001, ///< Two G's of measurement range - QMA_RANGE_4G = 0b0010, ///< Four G's of measurement range - QMA_RANGE_8G = 0b0100, ///< Eight G's of measurement range - QMA_RANGE_16G = 0b1000, ///< Sixteen G's of measurement range - QMA_RANGE_32G = 0b1111, ///< Thirty-two G's of measurement range -} qma_range_t; - -/** - * @brief The bandwidth for acceleration measurement - */ -typedef enum -{ - QMA_BANDWIDTH_128_HZ = 0b111, ///< 128Hz bandwidth - QMA_BANDWIDTH_256_HZ = 0b110, ///< 256Hz bandwidth - QMA_BANDWIDTH_1024_HZ = 0b101, ///< 1024Hz bandwidth -} qma_bandwidth_t; - -esp_err_t initAccelerometer(i2c_port_t _i2c_port, gpio_num_t sda, gpio_num_t scl, gpio_pullup_t pullup, uint32_t clkHz, - qma_range_t range, qma_bandwidth_t bandwidth); -esp_err_t deInitAccelerometer(void); -esp_err_t accelSetRange(qma_range_t range); -esp_err_t accelGetAccelVec(int16_t* x, int16_t* y, int16_t* z); -esp_err_t accelGetStep(uint16_t* data); - -#endif From f18a29bcbcece6efbebb972fd66cbac291741874 Mon Sep 17 00:00:00 2001 From: Dylan Whichard Date: Fri, 20 Oct 2023 18:07:45 -0700 Subject: [PATCH 02/11] Add support for .obj files as .mdl files in spiffs --- main/CMakeLists.txt | 2 + main/asset_loaders/spiffs_model.c | 105 +++++++ main/asset_loaders/spiffs_model.h | 6 + main/display/model.c | 185 +++++++++++ main/display/model.h | 61 ++++ main/modes/accelTest/accelTest.c | 52 +-- .../src/obj_processor.c | 295 ++++++++++++++++++ .../src/obj_processor.h | 6 + .../src/spiffs_file_preprocessor.c | 5 + 9 files changed, 676 insertions(+), 41 deletions(-) create mode 100644 main/asset_loaders/spiffs_model.c create mode 100644 main/asset_loaders/spiffs_model.h create mode 100644 main/display/model.c create mode 100644 main/display/model.h create mode 100644 tools/spiffs_file_preprocessor/src/obj_processor.c create mode 100644 tools/spiffs_file_preprocessor/src/obj_processor.h diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 46c667a82..6a37e4ac4 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -3,6 +3,7 @@ idf_component_register(SRCS "swadge2024.c" "asset_loaders/heatshrink_helper.c" "asset_loaders/spiffs_font.c" "asset_loaders/spiffs_json.c" + "asset_loaders/spiffs_model.c" "asset_loaders/spiffs_song.c" "asset_loaders/spiffs_txt.c" "asset_loaders/spiffs_wsg.c" @@ -11,6 +12,7 @@ idf_component_register(SRCS "swadge2024.c" "colorchord/embeddedOut.c" "display/fill.c" "display/font.c" + "display/model.c" "display/shapes.c" "display/wsg.c" "menu/menu.c" diff --git a/main/asset_loaders/spiffs_model.c b/main/asset_loaders/spiffs_model.c new file mode 100644 index 000000000..7224b177e --- /dev/null +++ b/main/asset_loaders/spiffs_model.c @@ -0,0 +1,105 @@ +#include "model.h" + +#include "heatshrink_helper.h" + +#include +#include +#include +#include + +bool loadModel(const char* name, model_t* model, bool useSpiRam) +{ + uint32_t decompressedSize = 0; + uint8_t* decompressedBuf = readHeatshrinkFile(name, &decompressedSize, useSpiRam); + + if (NULL == decompressedBuf) + { + return false; + } + + // Save the decompressed info into the model struct + // The first 2 bytes are version, currently unused + uint16_t version = (decompressedBuf[0] << 8) | decompressedBuf[1]; + + // Next 2 bytes are vertex count + uint16_t vertCount = (decompressedBuf[2] << 8) | decompressedBuf[3]; + + // Next 2 bytes are face count + uint16_t triCount = (decompressedBuf[4] << 8) | decompressedBuf[5]; + + // Next 2 bytes are line count + uint16_t lineCount = (decompressedBuf[6] << 8) | decompressedBuf[7]; + + // Then, the verts are immediately after the triCount + uint16_t vertOffset = 8; + + // Then, triangles are immediately vertexes, padded to a 4-byte offset + uint16_t triOffset = vertOffset + 3 * vertCount; + + // Then, triangle colors are after those + uint16_t triColOffset = (triOffset + 6 * triCount); + + // Then, lines are last + uint16_t lineOffset = triColOffset + triCount; + + model->vertCount = vertCount; + model->triCount = triCount; + model->lineCount = lineCount; + + if (useSpiRam) + { + model->verts = heap_caps_malloc(sizeof(modelVert_t) * vertCount, MALLOC_CAP_SPIRAM); + model->tris = (triCount > 0) ? heap_caps_malloc(sizeof(modelTri_t) * triCount, MALLOC_CAP_SPIRAM) : NULL; + model->lines = (lineCount > 0) ? heap_caps_malloc(sizeof(modelLine_t) * lineCount, MALLOC_CAP_SPIRAM) : NULL; + } + else + { + model->verts = malloc(sizeof(modelVert_t) * vertCount); + model->tris = (triCount > 0) ? malloc(sizeof(modelTri_t) * triCount) : NULL; + model->lines = (lineCount > 0) ? malloc(sizeof(modelLine_t) * lineCount) : NULL; + } + + uint16_t i; + + // Write all the verts into the struct + for (i = 0; i < vertCount; i++) + { + model->verts[i][0] = (int8_t)decompressedBuf[vertOffset + i * sizeof(modelVert_t)]; + model->verts[i][1] = (int8_t)decompressedBuf[vertOffset + i * sizeof(modelVert_t) + 1]; + model->verts[i][2] = (int8_t)decompressedBuf[vertOffset + i * sizeof(modelVert_t) + 2]; + } + + // Write all the tris into the struct + for (i = 0; i < triCount; i++) + { + model->tris[i].verts[0] = decompressedBuf[triOffset + i * 6] << 8 | decompressedBuf[triOffset + i * 6 + 1]; + model->tris[i].verts[1] = decompressedBuf[triOffset + i * 6 + 2] << 8 | decompressedBuf[triOffset + i * 6 + 3]; + model->tris[i].verts[2] = decompressedBuf[triOffset + i * 6 + 4] << 8 | decompressedBuf[triOffset + i * 6 + 5]; + model->tris[i].color = (paletteColor_t)decompressedBuf[triColOffset + i]; + } + + for (i = 0; i < lineCount; i++) + { + model->lines[i][0] = decompressedBuf[lineOffset + i * 4] << 8 | decompressedBuf[lineOffset + i * 4 + 1]; + model->lines[i][1] = decompressedBuf[lineOffset + i * 4 + 2] << 8 | decompressedBuf[lineOffset + i * 4 + 3]; + } + + free(decompressedBuf); + + return true; +} + +void freeModel(model_t* model) +{ + free(model->verts); + + if (NULL != model->tris) + { + free(model->tris); + } + + if (NULL != model->lines) + { + free(model->lines); + } +} \ No newline at end of file diff --git a/main/asset_loaders/spiffs_model.h b/main/asset_loaders/spiffs_model.h new file mode 100644 index 000000000..f2d963eb1 --- /dev/null +++ b/main/asset_loaders/spiffs_model.h @@ -0,0 +1,6 @@ +#include "model.h" + +#include + +bool loadModel(const char* name, model_t* model, bool useSpiRam); +void freeModel(model_t* model); \ No newline at end of file diff --git a/main/display/model.c b/main/display/model.c new file mode 100644 index 000000000..5ccdd0125 --- /dev/null +++ b/main/display/model.c @@ -0,0 +1,185 @@ +// Includes +#include "model.h" + +#include +#include +#include +#include +#include + +#include "hdw-imu.h" +#include "hdw-tft.h" +#include "shapes.h" +#include "palette.h" + +// Static Function Prototypes +static void intcross(int* p, const int* a, const int* b); +static int zcompare(const int16_t *a, const int16_t* b); +static unsigned julery_isqrt(unsigned long val); + +// Function Definitions +static void intcross(int* p, const int* a, const int* b) +{ + float tx = a[1] * b[2] - a[2] * b[1]; + float ty = a[2] * b[0] - a[0] * b[2]; + p[2] = a[0] * b[1] - a[1] * b[0]; + p[1] = ty; + p[0] = tx; +} + +static int zcompare(const int16_t *a, const int16_t* b) +{ + return a[0] - b[0]; +} + +static unsigned julery_isqrt(unsigned long val) { + unsigned long temp, g=0, b = 0x8000, bshft = 15; + do { + if (val >= (temp = (((g << 1) + b)<>= 1); + return g; +} + +void drawModel(const model_t* model, float orient[4]) +{ + // TODO: add translate parameter + // TODO: add x, y, w, and h as parameters for the drawing area + // TODO: not sure if lines work + + uint16_t w = TFT_WIDTH; + uint16_t h = TFT_HEIGHT; + uint16_t verts_out[model->vertCount * 3]; + char ctsbuffer[1024]; + char *cts = ctsbuffer; + + float plusy[3] = { 0, 1, 0 }; + + // Produce a model matrix from a quaternion. + float plusx_out[3] = { 0.9, 0, 0 }; + float plusy_out[3] = { 0, 0.9, 0 }; + float plusz_out[3] = { 0, 0, 0.9 }; + mathRotateVectorByQuaternion( plusy, orient, plusy ); + mathRotateVectorByQuaternion( plusy_out, orient, plusy_out ); + mathRotateVectorByQuaternion( plusx_out, orient, plusx_out ); + mathRotateVectorByQuaternion( plusz_out, orient, plusz_out ); + + //uint32_t cycStart = getCycleCount(); + + int i, vertices = 0; + for( i = 0; i < model->vertCount; i++ ) + { + // Performing the transform this way is about 700us. + float bx = 1.0 * model->verts[i][0]; + float by = 1.0 * model->verts[i][1]; + float bz = 1.0 * model->verts[i][2]; + + float bunnyvert[3] = { + bx * plusx_out[0] + by * plusx_out[1] + bz * plusx_out[2], + bx * plusy_out[0] + by * plusy_out[1] + bz * plusy_out[2], + bx * plusz_out[0] + by * plusz_out[1] + bz * plusz_out[2] + }; + + verts_out[vertices*3+0] = bunnyvert[0] + w/2; + // Convert from right-handed to left-handed coordinate frame. + verts_out[vertices*3+1] =-bunnyvert[1] + h/2; + verts_out[vertices*3+2] = bunnyvert[2]; + vertices++; + } + + if (model->triCount > 0) + { + // Draw model with shaded triangles + int totalTrisThisFrame = 0; + + // Z, Index, Color + int16_t trimap[model->triCount][3]; + + for( i = 0; i < model->triCount; i++) + { + int tv1 = model->tris[i].verts[0] * 3; + int tv2 = model->tris[i].verts[1] * 3; + int tv3 = model->tris[i].verts[2] * 3; + int col = model->tris[i].color; + + int diff1[3] = { + verts_out[tv3+0] - verts_out[tv1+0], + verts_out[tv3+1] - verts_out[tv1+1], + verts_out[tv3+2] - verts_out[tv1+2] }; + int diff2[3] = { + verts_out[tv2+0] - verts_out[tv1+0], + verts_out[tv2+1] - verts_out[tv1+1], + verts_out[tv2+2] - verts_out[tv1+2] }; + + // If we didn't need the normal, could do cross faster. int crossproduct = diff1[1] * diff2[0] - diff1[0] * diff2[1]; + + int icrp[3]; + intcross( icrp, diff1, diff2 ); + if( icrp[2] < 0 ) continue; + int z = verts_out[tv1+2] + verts_out[tv2+2] + verts_out[tv3+2]; + + int b = col % 6; + int g = ( col / 6 ) % 6; + int r = ( col / 36 ) % 6; + + //float fcrp[3] = { icrp[0], icrp[1], icrp[2] }; + int crpscalar = julery_isqrt( icrp[0] * icrp[0] + icrp[1] * icrp[1] + icrp[2] * icrp[2] ); + icrp[0] = ( 1024 * icrp[0] ) / crpscalar; + icrp[1] = ( 1024 * icrp[1] ) / crpscalar; + icrp[2] = ( 1024 * icrp[2] ) / crpscalar; + + int isum = icrp[0] - icrp[1] + icrp[2]; + + r = ( r * ( ( isum ) + 1200 ) * 100 ) >> 18; + g = ( g * ( ( isum ) + 1200 ) * 100 ) >> 18; + b = ( b * ( ( isum ) + 1200 ) * 100 ) >> 18; + + if( r < 0 ) r = 0; + if( g < 0 ) g = 0; + if( b < 0 ) b = 0; + if( r > 5 ) r = 5; + if( g > 5 ) g = 5; + if( b > 5 ) b = 5; + + trimap[totalTrisThisFrame][0] = z; + trimap[totalTrisThisFrame][1] = i; + trimap[totalTrisThisFrame][2] = r * 36 + g * 6 + b; + totalTrisThisFrame++; + } + + qsort(trimap, totalTrisThisFrame, sizeof( trimap[0] ), (void*)zcompare ); + + for( i = 0; i < totalTrisThisFrame; i++) + { + int j = trimap[i][1]; + int tv1 = model->tris[j].verts[0]*3; + int tv2 = model->tris[j].verts[1]*3; + int tv3 = model->tris[j].verts[2]*3; + int tcol = trimap[i][2]; + + drawTriangleOutlined( + verts_out[tv1+0], verts_out[tv1+1], + verts_out[tv2+0], verts_out[tv2+1], + verts_out[tv3+0], verts_out[tv3+1], + tcol, tcol ); + } + } + else if (model->lineCount > 0) + { + // Draw wireframe with lines + for (i = 0; i < model->lineCount; i++) + { + uint16_t v1 = model->lines[i][0] * 3; + uint16_t v2 = model->lines[i][1] * 3; + + float col = verts_out[v1 + 2] / 2000 + 8; + if (col > 5) + col = 5; + else if (col < 0) + continue; + drawLineFast(verts_out[v1], verts_out[v1 + 1], verts_out[v2], verts_out[v2 + 1], col); + } + } +} diff --git a/main/display/model.h b/main/display/model.h new file mode 100644 index 000000000..ce943cc72 --- /dev/null +++ b/main/display/model.h @@ -0,0 +1,61 @@ +#ifndef _MODEL_H_ +#define _MODEL_H_ + +#include +#include + +#include "palette.h" + +typedef int8_t modelVert_t[3]; +typedef uint16_t modelLine_t[2]; + +/** + * @brief Structure representing a triangle and its color + */ +typedef struct +{ + /// @brief Index of each of the triangle's vertices + uint16_t verts[3]; + + // Triangle color + paletteColor_t color; +} modelTri_t; + +/** + * @brief Structure representing a 3D model + */ +typedef struct +{ + /// @brief The number of vertices in \c verts + uint16_t vertCount; + + /// @brief An array defining the coordinates of all vertices + modelVert_t* verts; + + /// @brief The number of triangles in \c tris + uint16_t triCount; + + /// @brief An array defining the vertices and color of all triangles + modelTri_t* tris; + + /// @brief The number of lines in \c lines + uint16_t lineCount; + + /// @brief An array defining the model's lines + modelLine_t* lines; +} model_t; + +/** + * @brief Render a 3D model to the screen + * + * @param model The 3D model to draw + * @param offset The location within the world + * @param orient A quaternion representing the orientation of the model + * @param x The X coordinate of the left side of the window to draw the model within + * @param y The Y coordinate of the top side of the window to draw the model within + * @param w The width of the window to draw the model within + * @param h The height of the window to draw the model within + */ +void drawModel(const model_t* model, float orient[4]); + +#endif diff --git a/main/modes/accelTest/accelTest.c b/main/modes/accelTest/accelTest.c index 8fa043193..8a01f5ddc 100644 --- a/main/modes/accelTest/accelTest.c +++ b/main/modes/accelTest/accelTest.c @@ -19,7 +19,8 @@ #include "fill.h" #include "linked_list.h" #include "font.h" -#include "bunny.h" +#include "model.h" +#include "spiffs_model.h" //============================================================================== // Defines @@ -72,6 +73,8 @@ typedef struct { font_t ibm; ///< The font used to display text + model_t bunny; ///< The bunny 3D model + uint16_t btnState; ///< The button state int16_t x; ///< The latest X accelerometer reading @@ -158,6 +161,7 @@ static void accelTestEnterMode(void) // Load a font loadFont("ibm_vga8.font", &accelTest->ibm, false); + ESP_LOGI("Model", "loadModel(bunny.mdl) returned %s", loadModel("donut.mdl", &accelTest->bunny, true) ? "true" : "false"); // writeTextlabels doesn't get reset by accelTestReset(), so initialize that here accelTest->writeTextLabels = true; @@ -174,6 +178,9 @@ static void accelTestEnterMode(void) */ static void accelTestExitMode(void) { + // Free the bunny 3D model + freeModel(&accelTest->bunny); + // Free the font freeFont(&accelTest->ibm); free(accelTest); @@ -258,46 +265,9 @@ static void accelTestHandleInput(void) */ static void accelDrawBunny(void) { - // Produce a model matrix from a quaternion. - float plusx_out[3] = {1, 0, 0}; - float plusy_out[3] = {0, 1, 0}; - float plusz_out[3] = {0, 0, 1}; - - mathRotateVectorByQuaternion(plusy_out, LSM6DSL.fqQuat, plusy_out); - mathRotateVectorByQuaternion(plusx_out, LSM6DSL.fqQuat, plusx_out); - mathRotateVectorByQuaternion(plusz_out, LSM6DSL.fqQuat, plusz_out); - - int16_t bunny_verts_out[sizeof(bunny_verts) / 3 / 2 * 3]; - int i, vertices = 0; - for (i = 0; i < sizeof(bunny_verts) / 2; i += 3) - { - // Performingthe transform this way is about 700us. - float bx = bunny_verts[i + 2]; - float by = bunny_verts[i + 1]; - float bz = -bunny_verts[i + 0]; - float bunnyvert[3] = {bx * plusx_out[0] + by * plusx_out[1] + bz * plusx_out[2], - bx * plusy_out[0] + by * plusy_out[1] + bz * plusy_out[2], - bx * plusz_out[0] + by * plusz_out[1] + bz * plusz_out[2]}; - bunny_verts_out[vertices * 3 + 0] = bunnyvert[0] / 250 + 280 / 2; - bunny_verts_out[vertices * 3 + 1] - = -bunnyvert[1] / 250 + 240 / 2; // Convert from right-handed to left-handed coordinate frame. - bunny_verts_out[vertices * 3 + 2] = bunnyvert[2]; - vertices++; - } - - int lines = 0; - for (i = 0; i < sizeof(bunny_lines); i += 2) - { - int v1 = bunny_lines[i] * 3; - int v2 = bunny_lines[i + 1] * 3; - float col = bunny_verts_out[v1 + 2] / 2000 + 8; - if (col > 5) - col = 5; - else if (col < 0) - continue; - drawLineFast(bunny_verts_out[v1], bunny_verts_out[v1 + 1], bunny_verts_out[v2], bunny_verts_out[v2 + 1], col); - lines++; - } + float orient[4]; + memcpy(orient, LSM6DSL.fqQuat, sizeof(orient)); + drawModel(&accelTest->bunny, orient); } /** diff --git a/tools/spiffs_file_preprocessor/src/obj_processor.c b/tools/spiffs_file_preprocessor/src/obj_processor.c new file mode 100644 index 000000000..c1b45e560 --- /dev/null +++ b/tools/spiffs_file_preprocessor/src/obj_processor.c @@ -0,0 +1,295 @@ +#include +#include +#include +#include +#include +#include + +#include "obj_processor.h" +#include "heatshrink_encoder.h" +#include "fileUtils.h" +#include "heatshrink_util.h" + + +#define DEBUG_OBJ +#define BUFLEN_DEFAULT 1024 + +typedef float fvVert_t[6]; +typedef int iv_t[3]; +typedef int ln_t[2]; + +#ifdef DEBUG_OBJ +#define DEBUG_PRINT(...) printf(__VA_ARGS__) +#else +#define DEBUG_PRINT(...) +#endif + +#define DEBUG_SIZE_CHANGE(arr, count, size) DEBUG_PRINT("Increased size of " # arr " to %d because it has %d members\n", size, count) + +#define CHECK_ARR(arr, count, size, elmsize) do \ +{ \ + if (count + 1 >= size) \ + { \ + size *= 2; \ + DEBUG_SIZE_CHANGE(arr, count, size); \ + void* _tmp##arr = realloc(arr, size * elmsize); \ + if (_tmp##arr != NULL) \ + { \ + arr = _tmp##arr; \ + } \ + } \ +} while(0) + +void process_obj(const char* infile, const char* outdir) +{ + /* Determine if the output file already exists */ + char outFilePath[128] = {0}; + strcat(outFilePath, outdir); + strcat(outFilePath, "/"); + strcat(outFilePath, get_filename(infile)); + + /* Change the file extension */ + char* dotptr = strrchr(outFilePath, '.'); + snprintf(&dotptr[1], strlen(dotptr), "mdl"); + + /* Open input file */ + FILE * f = fopen( infile, "r" ); + char buffer[1024]; + char * line; + + /* Min and Max dimensions */ + float minB[3] = { 1e20, 1e20, 1e20 }; + float maxB[3] = {-1e20,-1e20,-1e20 }; + + // Absolute max in any dimension + float maxextent = -1e20; + + // Read verts + int fvSize = BUFLEN_DEFAULT; + fvVert_t* fvVerts = malloc(fvSize * sizeof(fvVert_t)); + int fvc = 0; + + int ivSize = BUFLEN_DEFAULT; + iv_t* ivS = malloc(ivSize * sizeof(iv_t)); + int ivc = 0; + + int lnSize = BUFLEN_DEFAULT; + ln_t* lines = malloc(lnSize * sizeof(ln_t)); + int lnc = 0; + + while (NULL != (line = fgets( buffer, sizeof(buffer)-1, f ))) + { + /* Read vertex line */ + if( line[0] == 'v' ) + { + // Make sure the fvVerts array has room for another one + CHECK_ARR(fvVerts, fvc, fvSize, sizeof(fvVert_t)); + float fv[6]; + sscanf( line + 2, "%f %f %f %f %f %f", fv+0, fv+1, fv+2, fv+3, fv+4, fv+5 ); + + if( fv[0] < minB[0] ) minB[0] = fv[0]; + if( fv[0] > maxB[0] ) maxB[0] = fv[0]; + + if( fv[1] < minB[1] ) minB[1] = fv[1]; + if( fv[1] > maxB[1] ) maxB[1] = fv[1]; + + if( fv[2] < minB[2] ) minB[2] = fv[2]; + if( fv[2] > maxB[2] ) maxB[2] = fv[2]; + + memcpy( &fvVerts[fvc++], fv, sizeof( fv ) ); + } + + /* Read triangle line */ + if( line[0] == 'f' ) + { + // Make sure the ivS array has enough room for another one + CHECK_ARR(ivS, ivc, ivSize, sizeof(iv_t)); + + int vv[3]; + sscanf( line + 2, "%d %d %d", vv+0, vv+1, vv+2 ); + + // read values are 1-indexed, decrement to make them 0-indexed + vv[0]--; + vv[1]--; + vv[2]--; + + memcpy( ivS[ivc++], vv, sizeof( vv ) ); + } + + /* Read line entry */ + if (line[0] == 'l') + { + CHECK_ARR(lines, lnc, lnSize, sizeof(ln_t)); + + ln_t ln; + sscanf( line + 2, "%d %d", &ln[0], &ln[1]); + + // Convert to 0-indexed + ln[0]--; + ln[1]--; + + memcpy(lines[lnc++], ln, sizeof(ln)); + } + /* Ignore comments and also everything else */ + } + + DEBUG_PRINT("Read %d vertices and %d faces from obj\n", fvc, ivc); + + int iAliasedVert[fvc]; + + // the final list of verts + int cvsize = BUFLEN_DEFAULT; + float* compverts = malloc(cvsize * sizeof(float) * 3); + int cvct = 0; + int i, j; + for( i = 0; i < fvc; i++ ) + { + float * fvcr = fvVerts[i]; + + // Look for any previous verts that overlap this one close enough + for( j = 0; j < cvct; j++ ) + { + float dx = fvcr[0] - compverts[j*3 + 0]; + float dy = fvcr[1] - compverts[j*3 + 1]; + float dz = fvcr[2] - compverts[j*3 + 2]; + float diff = sqrtf( dx*dx + dy*dy + dz*dz ); + if( diff < 0.0001 ) + { + // Match found! + break; + } + } + if( j == cvct ) + { + // No match found - new one! + CHECK_ARR(compverts, cvct, cvsize, sizeof(float) * 3); + memcpy( &compverts[3 * cvct++], fvcr, sizeof(float) * 3 ); + /*DEBUG_PRINT("Final vert #%d: (%.2f, %.2f, %.2f) --> (%d, %d, %d)\n", cvct - 1, + fvVerts[j][0], fvVerts[j][1], fvVerts[j][2], + compverts[(cvct - 1) * 3], compverts[(cvct - 1) * 3 + 1], compverts[(cvct - 1) * 3 + 2]);*/ + } + iAliasedVert[i] = j; + } + + DEBUG_PRINT("Combined %d vertices, final number is %d vertices\n", fvc - cvct, cvct); + + if( -minB[0] > maxextent ) maxextent = -minB[0]; + if( -minB[1] > maxextent ) maxextent = -minB[1]; + if( -minB[2] > maxextent ) maxextent = -minB[2]; + if( maxB[0] > maxextent ) maxextent = maxB[0]; + if( maxB[1] > maxextent ) maxextent = maxB[1]; + if( maxB[2] > maxextent ) maxextent = maxB[2]; + + float scale = 127.9 / maxextent; + + // Allocate raw file buffer + // Structure: 2 bytes version + // 2 bytes #verts + // 2 bytes #tris + // 2 bytes #lines + // verts 3B each (int8 x 3) + // triVerts: {2B v0, 2B v1, 2B v2} + // triCols: { 1B Color (uint8 palette) } + // lines: {2B v0, 2B v1} + + // face verts/colors + int ivR[ivc][4]; + + for( i = 0; i < ivc; i++ ) + { + int i0 = ivS[i][0]; + int i1 = ivS[i][1]; + int i2 = ivS[i][2]; + + float * color = &fvVerts[i0][3]; + int fc = ((int)(color[2] * 5.9)) + ((int)(color[1] * 5.9)) * 6 + ((int)(color[0] * 5.9)) * 36; + int * face = ivR[i]; + + face[0] = iAliasedVert[i0]; + face[1] = iAliasedVert[i1]; + face[2] = iAliasedVert[i2]; + face[3] = fc; + } + + int outBufSize = 2 + 2 + 2 + 2 + (cvct * 3) + 3 + ivc * 7 + lnc * 4; + uint8_t* outBuf = malloc(outBufSize); + uint8_t* bp = outBuf; + + // Write version + *bp++ = 0; + *bp++ = 1; + + // Write number of verts + *bp++ = (cvct >> 8) & 0xFF; + *bp++ = cvct & 0xFF; + + // Write number of tris + *bp++ = (ivc >> 8) & 0xFF; + *bp++ = ivc & 0xFF; + + // Write number of lines + *bp++ = (lnc >> 8) & 0xFF; + *bp++ = lnc & 0xFF; + +#ifdef DEBUG_OBJ + printf("\nint8_t verts[] = {\n"); + + for( i = 0; i < cvct; i++ ) + { + printf("\t%d, %d, %d,\n", + (int8_t)(compverts[i*3 + 0]*scale), + (int8_t)(compverts[i*3 + 1]*scale), + (int8_t)(compverts[i*3 + 2]*scale)); + } + printf("};\nuint8_t tris[] = {\n"); + for( i = 0; i < ivc; i++ ) + { + printf("\t%d, %d, %d, %d,\n", ivR[i][0], ivR[i][1], ivR[i][2], ivR[i][3]); + } + printf("};\n" ); +#endif + + // Write verts + for( i = 0; i < cvct; i++ ) + { + int8_t outVert[3]; + + outVert[0] = (int8_t)(compverts[i*3 + 0]*scale); + outVert[1] = (int8_t)(compverts[i*3 + 1]*scale); + outVert[2] = (int8_t)(compverts[i*3 + 2]*scale); + + *bp++ = outVert[0]; + *bp++ = outVert[1]; + *bp++ = outVert[2]; + } + + // Write triangle vertexes + for( i = 0; i < ivc; i++ ) + { + *bp++ = (ivR[i][0] >> 8) & 0xFF; + *bp++ = ivR[i][0] & 0xFF; + *bp++ = (ivR[i][1] >> 8) & 0xFF; + *bp++ = ivR[i][1] & 0xFF; + *bp++ = (ivR[i][2] >> 8) & 0xFF; + *bp++ = ivR[i][2] & 0xFF; + } + + // Write triangle colors + for (i = 0; i < ivc; i++) + { + *bp++ = (uint8_t)(ivR[i][3] & 0xFF); + } + + // Write lines + for (i = 0; i < lnc; i++) + { + *bp++ = (lines[i][0] >> 8) & 0xFF; + *bp++ = lines[i][0] & 0xFF; + *bp++ = (lines[i][1] >> 8) & 0xFF; + *bp++ = lines[i][1] & 0xFF; + } + + printf("Writing compressed model to %s\n", outFilePath); + // Write compressed output file + writeHeatshrinkFile(outBuf, outBufSize, outFilePath); +} \ No newline at end of file diff --git a/tools/spiffs_file_preprocessor/src/obj_processor.h b/tools/spiffs_file_preprocessor/src/obj_processor.h new file mode 100644 index 000000000..b931ea1c7 --- /dev/null +++ b/tools/spiffs_file_preprocessor/src/obj_processor.h @@ -0,0 +1,6 @@ +#ifndef _OBJ_PROCESSOR_H_ +#define _OBJ_PROCESSOR_H_ + +void process_obj(const char* infile, const char* outdir); + +#endif \ No newline at end of file diff --git a/tools/spiffs_file_preprocessor/src/spiffs_file_preprocessor.c b/tools/spiffs_file_preprocessor/src/spiffs_file_preprocessor.c index eb0959789..8da00975a 100644 --- a/tools/spiffs_file_preprocessor/src/spiffs_file_preprocessor.c +++ b/tools/spiffs_file_preprocessor/src/spiffs_file_preprocessor.c @@ -17,6 +17,7 @@ #include "txt_processor.h" #include "midi_processor.h" #include "rmd_processor.h" +#include "obj_processor.h" const char* outDirName = NULL; @@ -91,6 +92,10 @@ static int processFile(const char* fpath, const struct stat* st __attribute__((u { process_rmd(fpath, outDirName); } + else if (endsWith(fpath, ".obj")) + { + process_obj(fpath, outDirName); + } break; } case FTW_D: // directory From 32280d3fa8636ff96202265a86a72754f3a88d09 Mon Sep 17 00:00:00 2001 From: Dylan Whichard Date: Sat, 21 Oct 2023 10:37:31 -0700 Subject: [PATCH 03/11] Add renderer init/deinit functions for allocating buffers --- main/display/model.c | 50 ++++++++++++++++--- main/display/model.h | 28 +++++++++++ main/modes/accelTest/accelTest.c | 30 ++++++++++- .../src/obj_processor.c | 4 +- 4 files changed, 102 insertions(+), 10 deletions(-) diff --git a/main/display/model.c b/main/display/model.c index 5ccdd0125..0b017b92b 100644 --- a/main/display/model.c +++ b/main/display/model.c @@ -12,6 +12,13 @@ #include "shapes.h" #include "palette.h" +// do a funky typedef so we can still define trimap as a 2D array +typedef uint16_t trimap_t[3]; + +// Variables +static uint16_t* verts_out = NULL; +static trimap_t* trimap = NULL; + // Static Function Prototypes static void intcross(int* p, const int* a, const int* b); static int zcompare(const int16_t *a, const int16_t* b); @@ -43,6 +50,43 @@ static unsigned julery_isqrt(unsigned long val) { return g; } +void initRenderer(const model_t* model) +{ + initRendererCustom(model->vertCount, model->triCount); +} + +void initRendererCustom(uint16_t maxVerts, uint16_t maxFaces) +{ + // Free any existing buffers + deinitRenderer(); + + ESP_LOGI("Model", "Allocating %" PRIu64 " bytes for verts and faces", (uint64_t)((maxVerts + maxFaces) * 3 * sizeof(uint16_t))); + + // Allocate the new buffers + verts_out = malloc(maxVerts * 3 * sizeof(uint16_t)); + trimap = malloc(maxFaces * 3 * sizeof(uint16_t)); + + if (verts_out == NULL || trimap == NULL) + { + ESP_LOGI("Model", "Renderer could not allocate the buffers :("); + } +} + +void deinitRenderer(void) +{ + if (NULL != verts_out) + { + free(verts_out); + verts_out = NULL; + } + + if (NULL != trimap) + { + free(trimap); + trimap = NULL; + } +} + void drawModel(const model_t* model, float orient[4]) { // TODO: add translate parameter @@ -51,9 +95,6 @@ void drawModel(const model_t* model, float orient[4]) uint16_t w = TFT_WIDTH; uint16_t h = TFT_HEIGHT; - uint16_t verts_out[model->vertCount * 3]; - char ctsbuffer[1024]; - char *cts = ctsbuffer; float plusy[3] = { 0, 1, 0 }; @@ -94,9 +135,6 @@ void drawModel(const model_t* model, float orient[4]) // Draw model with shaded triangles int totalTrisThisFrame = 0; - // Z, Index, Color - int16_t trimap[model->triCount][3]; - for( i = 0; i < model->triCount; i++) { int tv1 = model->tris[i].verts[0] * 3; diff --git a/main/display/model.h b/main/display/model.h index ce943cc72..f7b712698 100644 --- a/main/display/model.h +++ b/main/display/model.h @@ -45,9 +45,37 @@ typedef struct modelLine_t* lines; } model_t; +/** + * @brief Initializes the renderer, allocating temporary buffers needed to draw efficiently. + * + * Enough space will be allocated for drawing the given model based on its number of elements. + * Other models may be rendered, as long as they do not have more vertices or triangles. If + * multiple models with varying numbers of vertices and faces will be drawn, initRendererCustom() + * should be called with the maximum numbe of vertices and maximum number of faces for any single + * model. + * + */ +void initRenderer(const model_t* model); + +/** + * @brief Initializes the renderer, allocating temporary buffers needed to draw efficiently. + * + * @param maxVerts The maximum number of vertices in a model that will be drawn + * @param maxFaces The maximum number of lines in a model that will be drawn + */ +void initRendererCustom(uint16_t maxVerts, uint16_t maxFaces); + +/** + * @brief Deinitializes the renderer, clearing any temporary buffers that were allocated + * + */ +void deinitRenderer(void); + /** * @brief Render a 3D model to the screen * + * initRenderer() or initRendererCustom() must be called once before rendering anything. + * * @param model The 3D model to draw * @param offset The location within the world * @param orient A quaternion representing the orientation of the model diff --git a/main/modes/accelTest/accelTest.c b/main/modes/accelTest/accelTest.c index 8a01f5ddc..8ccb335aa 100644 --- a/main/modes/accelTest/accelTest.c +++ b/main/modes/accelTest/accelTest.c @@ -74,6 +74,9 @@ typedef struct font_t ibm; ///< The font used to display text model_t bunny; ///< The bunny 3D model + model_t donut; ///< The donut 3D model + + bool drawDonut; uint16_t btnState; ///< The button state @@ -161,7 +164,11 @@ static void accelTestEnterMode(void) // Load a font loadFont("ibm_vga8.font", &accelTest->ibm, false); - ESP_LOGI("Model", "loadModel(bunny.mdl) returned %s", loadModel("donut.mdl", &accelTest->bunny, true) ? "true" : "false"); + ESP_LOGI("Model", "loadModel(bunny.mdl) returned %s", loadModel("bunny.mdl", &accelTest->bunny, true) ? "true" : "false"); + loadModel("donut.mdl", &accelTest->donut, true); + + // Ensure there's sufficient space to draw either model + initRendererCustom(MAX(accelTest->bunny.vertCount, accelTest->donut.vertCount), MAX(accelTest->bunny.triCount, accelTest->donut.triCount)); // writeTextlabels doesn't get reset by accelTestReset(), so initialize that here accelTest->writeTextLabels = true; @@ -178,9 +185,15 @@ static void accelTestEnterMode(void) */ static void accelTestExitMode(void) { + // Free renderer memory + deinitRenderer(); + // Free the bunny 3D model freeModel(&accelTest->bunny); + // Free the king donut 3D model + freeModel(&accelTest->donut); + // Free the font freeFont(&accelTest->ibm); free(accelTest); @@ -210,6 +223,11 @@ static void accelTestMainLoop(int64_t elapsedUs) { accelTest->writeTextLabels = !accelTest->writeTextLabels; } + + if (evt.down && (PB_B == evt.button)) + { + accelTest->drawDonut = !accelTest->drawDonut; + } } // Do update each loop @@ -267,7 +285,15 @@ static void accelDrawBunny(void) { float orient[4]; memcpy(orient, LSM6DSL.fqQuat, sizeof(orient)); - drawModel(&accelTest->bunny, orient); + + if (accelTest->drawDonut) + { + drawModel(&accelTest->donut, orient); + } + else + { + drawModel(&accelTest->bunny, orient); + } } /** diff --git a/tools/spiffs_file_preprocessor/src/obj_processor.c b/tools/spiffs_file_preprocessor/src/obj_processor.c index c1b45e560..fd737db5d 100644 --- a/tools/spiffs_file_preprocessor/src/obj_processor.c +++ b/tools/spiffs_file_preprocessor/src/obj_processor.c @@ -11,7 +11,7 @@ #include "heatshrink_util.h" -#define DEBUG_OBJ +//#define DEBUG_OBJ #define BUFLEN_DEFAULT 1024 typedef float fvVert_t[6]; @@ -99,7 +99,7 @@ void process_obj(const char* infile, const char* outdir) memcpy( &fvVerts[fvc++], fv, sizeof( fv ) ); } - /* Read triangle line */ + /* Read face line */ if( line[0] == 'f' ) { // Make sure the ivS array has enough room for another one From c5844136331fb7507f698145adafd9663e055f18 Mon Sep 17 00:00:00 2001 From: Dylan Whichard Date: Sat, 21 Oct 2023 11:00:13 -0700 Subject: [PATCH 04/11] Don't gitignore anything in assets --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3d157204e..d28fdece8 100644 --- a/.gitignore +++ b/.gitignore @@ -80,4 +80,5 @@ tools/rayMapEditor/autosave.rmd perf.data *.stackdump coverage/ -coverage.info \ No newline at end of file +coverage.info +!/assets/** From 0cd5d37b6a07998f35f7d9ed9703e8cdfd726d1d Mon Sep 17 00:00:00 2001 From: Dylan Whichard Date: Sat, 21 Oct 2023 11:01:11 -0700 Subject: [PATCH 05/11] Add bunny and donut 3D obj assets --- assets/3d/bunny.obj | 947 ++++++++++++++++++++++ assets/3d/donut.obj | 1836 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2783 insertions(+) create mode 100644 assets/3d/bunny.obj create mode 100644 assets/3d/donut.obj diff --git a/assets/3d/bunny.obj b/assets/3d/bunny.obj new file mode 100644 index 000000000..e0f6907d5 --- /dev/null +++ b/assets/3d/bunny.obj @@ -0,0 +1,947 @@ +# Blender v3.0.1 OBJ File: '' +# www.blender.org +mtllib bunny_out.mtl +o bunny_in +v -0.066510 0.040490 0.013845 +v -0.061102 0.012863 0.002506 +v -0.003613 0.029887 0.008373 +v -0.005212 0.022265 0.027687 +v -0.037086 -0.050182 0.037782 +v 0.032529 0.035221 0.017166 +v -0.032844 0.055743 0.030349 +v -0.058157 -0.023425 0.008593 +v -0.062206 -0.015591 0.008836 +v -0.065676 -0.005435 0.017198 +v 0.079356 -0.024382 0.018854 +v 0.085032 -0.028166 0.015824 +v -0.022154 0.072937 -0.007019 +v -0.046338 0.067219 -0.015228 +v -0.037962 0.065307 -0.024828 +v -0.038911 0.073940 -0.048696 +v -0.024158 -0.062746 -0.016193 +v 0.003223 0.001366 -0.027508 +v -0.016062 -0.004910 -0.025392 +v 0.017987 0.033175 0.022493 +v 0.015809 0.032889 -0.001409 +v -0.043712 -0.062792 -0.008789 +v -0.067562 0.020590 0.025463 +v -0.058494 -0.014652 0.028021 +v -0.008146 -0.043884 -0.012506 +v -0.043457 0.019756 -0.012165 +v -0.063958 0.056310 0.017519 +v -0.053921 0.056458 0.030356 +v 0.035090 0.002848 0.046031 +v -0.065298 0.036716 0.002826 +v 0.039313 0.032824 -0.000872 +v 0.040981 -0.002070 -0.027076 +v -0.045943 0.059184 -0.000697 +v -0.052287 0.057296 -0.004362 +v -0.065473 0.003348 0.009420 +v -0.054838 0.077514 -0.048406 +v -0.026349 0.054508 0.010164 +v -0.031425 0.059076 0.009221 +v -0.070704 0.022015 0.015416 +v -0.057710 0.032936 0.050024 +v -0.051488 0.043397 0.047050 +v -0.050505 0.083821 -0.054326 +v -0.041866 0.084627 -0.061256 +v -0.007015 -0.054942 0.049119 +v -0.025819 -0.029341 -0.015747 +v -0.031001 -0.016212 -0.023518 +v -0.021740 -0.019491 -0.021215 +v -0.047355 0.044418 -0.010384 +v -0.039208 0.054894 -0.005883 +v -0.026417 -0.049815 0.015349 +v -0.026552 -0.041368 0.015025 +v -0.047011 0.017807 0.049776 +v 0.006779 -0.010878 -0.041632 +v 0.020206 -0.014643 -0.040244 +v -0.012170 0.054170 -0.002755 +v -0.061787 -0.010350 -0.002779 +v -0.039065 0.045879 -0.009832 +v -0.042408 0.023666 0.050048 +v -0.036618 0.077377 -0.064477 +v 0.001453 0.077585 -0.023513 +v -0.014547 0.061070 -0.014028 +v 0.068507 0.002810 0.001056 +v 0.073500 -0.041653 -0.008778 +v 0.078938 -0.047684 0.001320 +v -0.045746 0.047131 -0.018560 +v 0.021654 0.014308 0.041099 +v -0.025987 0.045907 0.000408 +v -0.044876 -0.008038 0.041157 +v -0.050778 0.009878 0.034079 +v 0.021004 -0.042077 0.052603 +v 0.062632 -0.059812 0.008999 +v 0.067077 -0.007662 -0.009475 +v -0.038206 -0.061847 0.017996 +v -0.039793 0.014838 0.035507 +v 0.033863 -0.008743 0.053435 +v 0.029413 -0.036610 0.053071 +v -0.064990 0.040115 0.026306 +v -0.068516 0.024693 0.039289 +v -0.039087 0.056480 -0.037355 +v 0.013747 -0.049490 0.045873 +v -0.025696 0.045206 0.008830 +v 0.041011 -0.040898 0.047273 +v 0.035145 -0.051850 0.042963 +v 0.085298 -0.034172 0.004185 +v -0.038644 0.065787 -0.061165 +v -0.035444 -0.004484 0.042910 +v 0.043567 0.005747 0.042820 +v -0.038389 0.055472 0.033210 +v -0.034792 -0.020002 0.040621 +v -0.047391 -0.023088 0.033517 +v 0.070878 -0.025195 0.001424 +v 0.040279 -0.018354 0.051141 +v -0.022153 0.059370 0.005909 +v -0.032491 -0.039615 0.003563 +v 0.067866 -0.046449 0.030420 +v 0.015457 0.071982 -0.025766 +v 0.060185 0.015663 0.021879 +v 0.061550 -0.042822 0.029897 +v -0.032720 0.050621 -0.003795 +v 0.045288 -0.061066 -0.004460 +v -0.032289 -0.036391 -0.007118 +v -0.047324 0.077491 -0.055833 +v -0.043348 0.058240 -0.055670 +v -0.027021 0.019984 0.031126 +v -0.050204 0.052885 -0.031130 +v 0.018410 0.005460 0.042164 +v -0.041126 -0.056665 -0.008881 +v -0.021453 -0.024238 0.039030 +v -0.021724 -0.052646 -0.013735 +v -0.031799 -0.054965 0.044296 +v -0.024427 -0.005719 0.043197 +v 0.075185 -0.032191 0.026755 +v 0.068571 -0.027751 0.022850 +v -0.017122 -0.052764 -0.025001 +v -0.021473 0.010420 0.038014 +v 0.020857 -0.023025 0.055799 +v 0.045767 0.022127 0.031570 +v -0.049310 -0.061142 0.002841 +v 0.049737 -0.060324 0.023022 +v -0.024794 -0.046141 0.034123 +v -0.013731 -0.048336 0.037051 +v -0.015918 0.005568 0.038527 +v -0.067326 0.052647 0.013093 +v -0.019597 0.028124 0.022051 +v 0.014165 0.082895 -0.032958 +v 0.053903 -0.006981 -0.023582 +v 0.059248 -0.015722 -0.020193 +v -0.017560 -0.012127 0.040210 +v -0.011850 -0.006527 0.041581 +v -0.012686 0.073963 -0.001303 +v -0.007525 -0.011933 0.040069 +v 0.014204 0.024670 0.033919 +v -0.002153 0.007858 0.039997 +v -0.003328 -0.041714 0.033559 +v -0.002340 0.084250 -0.010061 +v 0.017308 -0.000406 0.052905 +v -0.000782 -0.001005 0.042913 +v 0.080983 -0.025497 0.003033 +v 0.036161 0.027697 0.030294 +v 0.000153 -0.050170 0.050606 +v 0.022838 0.016237 -0.022794 +v 0.005078 -0.045948 0.044458 +v 0.006956 0.091082 -0.022663 +v -0.027967 -0.046374 0.024800 +v -0.012074 -0.013479 -0.024394 +v 0.078003 -0.039212 0.026429 +v -0.010662 -0.062558 -0.033333 +v 0.001101 -0.049004 -0.030567 +v 0.002068 -0.014572 0.054434 +v 0.006998 -0.030898 0.050580 +v -0.056258 0.041262 -0.005511 +v 0.058294 -0.003587 0.038287 +v 0.004580 0.063422 -0.006786 +v -0.014742 -0.060803 0.040749 +v 0.051882 -0.046841 -0.020987 +v 0.044003 -0.051854 -0.024547 +v 0.062317 -0.030602 -0.015112 +v 0.060788 -0.042483 -0.009773 +v 0.045961 -0.030927 0.044748 +v -0.001669 -0.060487 0.052113 +v 0.058224 0.010604 -0.012629 +v -0.033584 -0.047838 0.004559 +v 0.080813 -0.046527 0.018183 +v -0.039032 0.039987 0.035421 +v -0.035923 0.026879 0.040445 +v 0.059895 -0.034755 0.035589 +v 0.067800 -0.002575 0.023064 +v -0.006840 0.014275 -0.021384 +v 0.056199 -0.019528 0.039696 +v 0.003032 0.008424 -0.025497 +v 0.012075 0.077693 -0.023342 +v 0.053921 -0.047613 0.033490 +v 0.041732 -0.060400 0.040858 +v 0.012479 0.066836 -0.016195 +v -0.030357 0.043434 0.027039 +v -0.037564 -0.061242 0.042738 +v 0.061537 -0.056769 -0.003453 +v -0.004239 -0.046552 -0.025916 +v -0.051750 -0.003917 -0.016655 +v 0.038868 -0.060940 -0.023876 +v -0.010514 -0.062025 0.032539 +v -0.060952 0.012554 0.018895 +v -0.063916 0.047079 0.033599 +v -0.065723 0.016193 0.036333 +v 0.029772 0.003333 -0.024764 +v -0.062765 0.024598 -0.004426 +v 0.018851 -0.062430 -0.026380 +v -0.045304 -0.052913 0.003317 +v -0.042820 -0.059850 0.025786 +v -0.000337 -0.005106 -0.037668 +v -0.055468 0.016456 0.045246 +v 0.044995 -0.039212 -0.029498 +v -0.018483 -0.062487 -0.029893 +v 0.033964 -0.062013 -0.017134 +v 0.027984 -0.002618 -0.035477 +v 0.071728 -0.022984 0.012469 +v -0.044940 0.060042 0.019949 +v -0.036954 0.058528 0.001484 +v -0.018416 0.032822 0.010801 +v -0.004150 -0.018637 -0.039351 +v 0.056782 0.020996 0.003312 +v -0.061088 0.002270 0.025815 +v -0.054229 0.065949 -0.030546 +v 0.049470 0.026782 0.020737 +v 0.044071 0.007106 -0.022271 +v -0.031371 -0.048229 -0.007222 +v -0.025371 0.032336 -0.005879 +v -0.031892 -0.001716 -0.023855 +v -0.062699 0.019978 0.045171 +v -0.030960 0.012558 -0.020807 +v -0.001296 -0.035758 -0.034185 +v 0.040557 0.023240 -0.014854 +v -0.047560 0.054076 -0.044965 +v 0.045150 -0.061002 0.006478 +v -0.052424 0.052753 -0.007803 +v -0.055050 -0.021255 -0.007185 +v -0.043816 -0.021671 -0.017756 +v -0.059303 -0.001895 -0.008227 +v -0.007915 0.025225 -0.010174 +v 0.017357 0.028393 -0.011203 +v 0.039197 -0.060764 0.001328 +v -0.019245 0.027393 -0.013295 +v -0.017518 -0.062907 0.024509 +v 0.030301 -0.045846 -0.032149 +v 0.033268 -0.024292 -0.035494 +v 0.028361 -0.053303 -0.027000 +v 0.029498 -0.034153 -0.034902 +v 0.009097 -0.032264 -0.039690 +v 0.016732 -0.047692 -0.033685 +v -0.026872 -0.033532 0.031323 +v 0.037675 -0.062190 0.019002 +v 0.035282 -0.059879 0.033037 +v 0.007906 -0.061763 0.041254 +v 0.046631 -0.059992 0.011549 +v 0.041917 -0.061500 0.019580 +v -0.001945 -0.061917 0.041042 +v -0.046585 -0.034682 0.013941 +v -0.029716 -0.063302 0.012999 +v -0.023206 -0.062235 0.006594 +v -0.011773 -0.062570 -0.023146 +l 2 218 +l 20 4 +l 20 3 +l 47 19 +l 40 52 +l 195 225 +l 63 64 +l 72 196 +l 1 215 +l 181 236 +l 235 119 +l 235 71 +l 72 157 +l 72 91 +l 136 116 +l 89 111 +l 5 120 +l 87 117 +l 140 44 +l 3 199 +l 1 151 +l 132 133 +l 149 116 +l 172 166 +l 172 83 +l 164 7 +l 169 82 +l 169 159 +l 81 55 +l 70 80 +l 117 204 +l 117 139 +l 28 183 +l 70 83 +l 78 40 +l 210 26 +l 210 208 +l 213 102 +l 141 170 +l 205 185 +l 195 190 +l 195 54 +l 231 235 +l 9 24 +l 99 207 +l 21 6 +l 200 53 +l 156 224 +l 52 58 +l 227 229 +l 231 173 +l 231 232 +l 66 139 +l 231 119 +l 70 82 +l 80 83 +l 22 73 +l 4 132 +l 238 239 +l 124 175 +l 106 117 +l 108 120 +l 55 61 +l 122 128 +l 85 16 +l 140 142 +l 29 75 +l 143 135 +l 55 153 +l 112 12 +l 72 161 +l 58 165 +l 112 11 +l 110 176 +l 110 154 +l 145 25 +l 97 152 +l 65 105 +l 171 96 +l 85 59 +l 22 238 +l 160 44 +l 160 154 +l 180 156 +l 8 24 +l 39 182 +l 185 195 +l 185 18 +l 197 33 +l 176 189 +l 32 205 +l 204 31 +l 140 134 +l 45 206 +l 78 209 +l 40 183 +l 32 185 +l 212 205 +l 65 213 +l 123 215 +l 217 46 +l 205 161 +l 181 154 +l 62 196 +l 214 234 +l 214 235 +l 214 71 +l 136 75 +l 157 91 +l 8 237 +l 57 99 +l 106 66 +l 6 20 +l 11 12 +l 198 99 +l 26 222 +l 16 15 +l 63 158 +l 54 228 +l 66 133 +l 124 104 +l 108 128 +l 108 129 +l 66 132 +l 122 133 +l 30 39 +l 30 186 +l 77 183 +l 81 175 +l 171 125 +l 153 174 +l 81 37 +l 152 92 +l 80 173 +l 152 169 +l 154 44 +l 100 214 +l 114 17 +l 145 19 +l 38 198 +l 149 150 +l 110 120 +l 173 232 +l 9 10 +l 68 86 +l 184 209 +l 69 184 +l 116 92 +l 147 226 +l 42 16 +l 215 151 +l 14 15 +l 192 224 +l 192 227 +l 9 56 +l 41 58 +l 225 54 +l 227 228 +l 187 226 +l 113 11 +l 147 148 +l 137 136 +l 58 164 +l 22 118 +l 80 140 +l 217 101 +l 190 145 +l 131 149 +l 78 184 +l 39 186 +l 181 176 +l 147 193 +l 74 115 +l 143 171 +l 143 125 +l 184 191 +l 7 175 +l 55 37 +l 69 202 +l 36 102 +l 200 145 +l 48 215 +l 3 219 +l 196 138 +l 113 196 +l 47 25 +l 161 31 +l 151 30 +l 121 140 +l 44 121 +l 100 71 +l 128 129 +l 93 135 +l 82 159 +l 130 93 +l 20 21 +l 225 228 +l 229 228 +l 60 125 +l 163 119 +l 20 139 +l 160 236 +l 158 91 +l 42 14 +l 196 91 +l 69 191 +l 100 63 +l 60 96 +l 77 1 +l 239 240 +l 81 207 +l 88 28 +l 88 197 +l 136 106 +l 201 97 +l 204 139 +l 179 210 +l 179 26 +l 206 107 +l 211 145 +l 31 212 +l 17 22 +l 32 126 +l 154 176 +l 124 199 +l 64 163 +l 69 23 +l 125 96 +l 222 3 +l 103 65 +l 6 204 +l 123 1 +l 129 133 +l 129 137 +l 55 174 +l 92 76 +l 193 148 +l 149 136 +l 149 137 +l 155 156 +l 92 159 +l 219 21 +l 14 36 +l 28 41 +l 156 192 +l 226 224 +l 60 61 +l 103 79 +l 41 88 +l 237 90 +l 118 107 +l 180 226 +l 33 198 +l 182 202 +l 100 177 +l 198 13 +l 32 195 +l 121 154 +l 193 114 +l 205 141 +l 123 77 +l 123 183 +l 6 139 +l 116 75 +l 133 106 +l 112 146 +l 150 116 +l 162 94 +l 88 164 +l 25 114 +l 104 115 +l 70 116 +l 111 122 +l 140 160 +l 12 138 +l 68 69 +l 73 50 +l 216 237 +l 24 237 +l 73 238 +l 102 103 +l 22 107 +l 101 216 +l 214 221 +l 1 39 +l 186 26 +l 35 10 +l 40 41 +l 50 51 +l 156 226 +l 35 218 +l 224 229 +l 118 73 +l 102 59 +l 212 141 +l 91 138 +l 25 178 +l 212 220 +l 17 193 +l 234 235 +l 13 143 +l 28 197 +l 207 199 +l 33 49 +l 102 43 +l 188 206 +l 60 13 +l 2 182 +l 207 3 +l 50 162 +l 188 162 +l 73 189 +l 167 152 +l 177 63 +l 177 64 +l 73 144 +l 3 124 +l 137 106 +l 194 240 +l 174 61 +l 71 163 +l 115 111 +l 29 106 +l 84 138 +l 232 233 +l 26 48 +l 216 56 +l 162 206 +l 107 188 +l 216 8 +l 168 210 +l 45 46 +l 45 47 +l 46 19 +l 14 49 +l 53 54 +l 200 211 +l 141 168 +l 148 114 +l 105 215 +l 36 34 +l 62 201 +l 99 61 +l 92 75 +l 41 183 +l 156 158 +l 173 119 +l 194 187 +l 167 166 +l 92 169 +l 4 122 +l 101 237 +l 167 113 +l 194 147 +l 156 100 +l 58 74 +l 67 61 +l 157 127 +l 2 186 +l 72 126 +l 50 188 +l 138 63 +l 138 11 +l 7 197 +l 204 201 +l 29 136 +l 94 50 +l 103 59 +l 105 213 +l 218 26 +l 7 38 +l 7 88 +l 40 58 +l 65 79 +l 65 57 +l 69 74 +l 95 112 +l 112 113 +l 70 150 +l 108 121 +l 108 131 +l 137 133 +l 224 227 +l 95 146 +l 142 150 +l 146 163 +l 69 52 +l 165 74 +l 93 171 +l 165 104 +l 93 143 +l 84 163 +l 107 17 +l 100 180 +l 71 177 +l 55 93 +l 23 182 +l 23 184 +l 172 119 +l 53 195 +l 198 197 +l 198 49 +l 208 179 +l 24 202 +l 186 151 +l 102 215 +l 161 212 +l 53 190 +l 217 179 +l 208 46 +l 15 49 +l 14 33 +l 37 93 +l 37 38 +l 46 47 +l 192 225 +l 24 68 +l 68 74 +l 62 167 +l 89 68 +l 89 90 +l 24 90 +l 38 130 +l 17 239 +l 176 73 +l 74 104 +l 107 109 +l 87 29 +l 4 124 +l 173 233 +l 111 128 +l 115 124 +l 61 96 +l 115 4 +l 62 97 +l 76 159 +l 196 167 +l 80 160 +l 126 161 +l 220 31 +l 164 165 +l 194 180 +l 173 172 +l 119 95 +l 126 205 +l 103 213 +l 102 203 +l 182 69 +l 213 215 +l 63 91 +l 94 101 +l 11 196 +l 10 202 +l 229 148 +l 229 211 +l 228 200 +l 228 211 +l 51 94 +l 237 51 +l 237 230 +l 84 12 +l 86 111 +l 207 222 +l 181 223 +l 168 208 +l 30 1 +l 79 57 +l 70 142 +l 4 133 +l 129 131 +l 13 130 +l 130 135 +l 13 135 +l 134 150 +l 10 24 +l 79 15 +l 18 190 +l 157 192 +l 174 96 +l 240 147 +l 18 141 +l 203 215 +l 216 179 +l 216 218 +l 187 147 +l 215 27 +l 190 200 +l 206 101 +l 194 221 +l 63 84 +l 23 77 +l 77 78 +l 233 160 +l 233 236 +l 221 180 +l 94 206 +l 218 56 +l 18 19 +l 18 145 +l 10 218 +l 35 202 +l 35 182 +l 20 132 +l 71 64 +l 38 13 +l 87 152 +l 157 158 +l 146 12 +l 98 119 +l 120 121 +l 38 93 +l 121 134 +l 23 78 +l 131 134 +l 14 34 +l 114 178 +l 201 161 +l 127 192 +l 109 206 +l 14 16 +l 51 230 +l 100 158 +l 34 203 +l 143 60 +l 34 215 +l 195 126 +l 52 74 +l 82 166 +l 82 172 +l 188 73 +l 165 124 +l 98 172 +l 144 189 +l 12 163 +l 152 166 +l 37 175 +l 57 15 +l 115 122 +l 132 139 +l 7 37 +l 76 82 +l 117 152 +l 3 4 +l 67 207 +l 34 27 +l 34 197 +l 222 210 +l 197 27 +l 173 160 +l 186 48 +l 45 217 +l 45 101 +l 225 227 +l 179 46 +l 72 62 +l 71 119 +l 223 238 +l 223 73 +l 151 48 +l 92 87 +l 92 29 +l 38 197 +l 36 203 +l 97 117 +l 26 207 +l 191 40 +l 191 209 +l 188 118 +l 43 59 +l 211 148 +l 215 65 +l 2 35 +l 98 166 +l 19 168 +l 237 94 +l 103 85 +l 164 175 +l 93 174 +l 109 17 +l 19 170 +l 78 183 +l 5 176 +l 114 109 +l 120 144 +l 36 42 +l 144 50 +l 18 195 +l 193 240 +l 98 112 +l 98 113 +l 108 111 +l 87 106 +l 141 185 +l 122 129 +l 121 131 +l 144 51 +l 55 67 +l 65 48 +l 93 153 +l 41 164 +l 9 216 +l 21 220 +l 13 99 +l 67 81 +l 82 83 +l 90 68 +l 74 86 +l 67 99 +l 126 225 +l 86 89 +l 26 57 +l 74 111 +l 42 102 +l 25 211 +l 81 199 +l 108 230 +l 97 204 +l 201 31 +l 61 13 +l 150 131 +l 230 120 +l 178 148 +l 109 25 +l 79 85 +l 79 16 +l 155 192 +l 170 18 +l 72 127 +l 180 187 +l 52 191 +l 83 173 +l 171 174 +l 5 189 +l 168 170 +l 49 57 +l 5 144 +l 219 222 +l 76 116 +l 226 229 +l 31 21 +l 154 236 +l 70 76 +l 117 66 +l 81 124 +l 97 167 +l 90 230 +l 181 73 +l 8 9 +l 168 220 +l 2 39 +l 42 43 +l 126 192 +l 21 3 +l 178 211 +l 216 217 +l 168 21 +l 16 43 +l 144 230 +l 25 45 +l 25 206 +l 39 23 +l 40 209 +l 68 202 +l 19 208 +l 77 39 +l 158 192 +l 141 220 +l 158 155 +l 179 218 +l 27 183 +l 64 84 +l 163 95 +l 166 169 +l 165 175 +l 166 113 +l 16 59 +l 134 142 +l 142 80 +l 27 123 +l 161 62 +l 110 121 +l 126 127 +l 131 137 +l 226 148 +l 54 200 +l 17 238 +l 95 98 +l 17 240 +l 34 33 +l 89 108 +l 5 110 +l 89 230 +l 2 26 +l 100 221 +l 49 99 +l 168 219 +l 27 28 +l 6 31 +l 168 222 +l 145 47 +l 48 57 +l 10 56 +l 207 57 diff --git a/assets/3d/donut.obj b/assets/3d/donut.obj new file mode 100644 index 000000000..626a13a17 --- /dev/null +++ b/assets/3d/donut.obj @@ -0,0 +1,1836 @@ +# Blender 3.6.4 +# www.blender.org +o KingDonut-Body.002 +v -0.709062 1.561661 0.049046 0.0000 0.0000 0.0000 +v -0.627303 1.592906 0.049046 0.0000 0.0000 0.0000 +v -0.819222 1.849922 0.049046 0.0000 0.0000 0.0000 +v -0.705487 1.797495 0.049046 0.0000 0.0000 0.0000 +v -0.431978 1.955380 0.049046 0.0000 0.0000 0.0000 +v -0.510471 1.849038 0.049046 0.0000 0.0000 0.0000 +v -0.464360 1.594421 0.049046 0.0000 0.0000 0.0000 +v -0.384422 1.708523 0.049046 0.0000 0.0000 0.0000 +v -0.219098 1.726008 0.049046 0.0000 0.0000 0.0000 +v -0.110353 1.633271 0.049046 0.0000 0.0000 0.0000 +v -0.225204 1.987604 0.049046 0.0000 0.0000 0.0000 +v -1.336737 0.186328 0.284611 0.7647 0.5530 0.2667 +v -1.883371 0.226736 -0.021286 0.6863 0.5569 0.4196 +v -0.548150 0.143171 0.238963 0.6863 0.5569 0.4196 +v -0.873608 0.178240 -0.483764 0.6863 0.5569 0.4196 +v -0.408081 1.495910 0.002639 0.6863 0.5569 0.4196 +v -0.245577 0.912701 -0.500168 0.6863 0.5569 0.4196 +v -0.361672 1.337784 -0.357899 0.6863 0.5569 0.4196 +v -1.081273 1.135520 -0.001882 0.6863 0.5569 0.4196 +v -0.648720 0.720775 -0.483617 0.6863 0.5569 0.4196 +v -0.958993 1.018711 -0.347098 0.6863 0.5569 0.4196 +v -0.861948 -0.145380 -0.483765 0.6863 0.5569 0.4196 +v -1.264879 -0.272602 -0.351883 0.6863 0.5569 0.4196 +v -1.197443 -0.781043 -0.001882 0.6863 0.5569 0.4196 +v -0.733756 -0.423388 -0.483765 0.6863 0.5569 0.4196 +v -1.072958 -0.687550 -0.348651 0.6863 0.5569 0.4196 +v -0.829016 -1.138370 -0.001882 0.6863 0.5569 0.4196 +v -0.512521 -0.643158 -0.483765 0.6863 0.5569 0.4196 +v -0.743150 -1.007688 -0.348875 0.6863 0.5569 0.4196 +v -0.328733 -1.348132 -0.001882 0.6863 0.5569 0.4196 +v -0.205626 -0.773612 -0.483765 0.6863 0.5569 0.4196 +v -0.294489 -1.196195 -0.348768 0.6863 0.5569 0.4196 +v -0.301905 -1.228287 0.292899 0.7647 0.5412 0.2627 +v -0.735667 -0.996442 0.327327 0.7647 0.5412 0.2627 +v -1.131959 -0.714433 0.262372 0.7647 0.5412 0.2627 +v -1.266555 -0.272971 0.305163 0.7647 0.5412 0.2627 +v -0.988921 1.056686 0.321924 0.7647 0.5490 0.2667 +v -0.360465 1.341580 0.328657 0.6863 0.5569 0.4196 +v -1.328137 0.724623 -0.001882 0.6863 0.5569 0.4196 +v -1.333987 0.535838 -0.234163 0.6863 0.5569 0.4196 +v 0.116973 1.886512 0.049046 0.0000 0.0000 0.0000 +v -1.369341 0.473302 0.159961 0.6863 0.5569 0.4196 +v -1.634900 0.610777 -0.018517 0.6863 0.5569 0.4196 +v -1.668647 -0.210301 -0.018074 0.6863 0.5569 0.4196 +v -1.389469 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v -0.150019 0.426291 0.296947 0.6863 0.5569 0.4196 +v -0.396349 0.379424 0.274974 0.7372 0.5490 0.3333 +v -0.542670 -0.036022 0.220516 0.6863 0.5569 0.4196 +v -0.465885 -0.215053 0.214114 0.6863 0.5569 0.4196 +v -0.331149 -0.358998 0.222609 0.7647 0.5412 0.2627 +v 1.689659 0.223271 -0.170425 0.6863 0.5569 0.4196 +v 1.400959 0.227422 0.157540 0.6863 0.5569 0.4196 +v -0.137027 -0.445499 0.233027 0.7647 0.5412 0.2627 +v -0.257571 -1.640068 -0.152551 0.1333 0.5098 0.5921 +v -0.750656 -1.640068 -0.437233 0.1333 0.5098 0.5921 +v -0.810476 -1.697196 0.774344 0.1333 0.5098 0.5921 +v -1.276918 -1.697196 0.505043 0.1333 0.5098 0.5921 +v -0.465518 -1.606527 -0.361742 0.1333 0.5098 0.5921 +v 1.353531 0.259211 -0.220091 0.6863 0.5569 0.4196 +v 1.708056 0.227065 0.099796 0.6863 0.5569 0.4196 +v 1.208511 0.208195 -0.425643 0.6863 0.5569 0.4196 +v -1.102982 -1.692053 0.742378 0.1333 0.5098 0.5921 +v -0.228822 -1.989715 -0.162474 0.1490 0.3255 0.4275 +v -0.756437 -1.989715 -0.467092 0.1333 0.5098 0.5921 +v -1.306086 -1.989715 0.499234 0.1333 0.5098 0.5921 +v -1.134901 -1.989715 0.797664 0.1333 0.5098 0.5921 +v -0.430607 -1.989715 -0.422209 0.1333 0.5098 0.5921 +v -0.790860 -1.989715 0.796699 0.1490 0.3255 0.4275 +v -0.492579 0.479193 0.632659 0.0000 0.0000 0.0000 +v -0.505703 0.808722 0.632659 0.0000 0.0000 0.0000 +v -0.836623 0.466526 0.632659 0.0000 0.0000 0.0000 +v -0.849747 0.796055 0.632659 0.0000 0.0000 0.0000 +v -0.453445 0.444475 0.528738 0.7647 0.5412 0.2627 +v -0.461445 0.645345 0.655432 0.0000 0.0000 0.0000 +v -0.469445 0.846216 0.528737 0.7647 0.5412 0.2627 +v -0.872881 0.429032 0.528738 0.7647 0.5412 0.2627 +v -0.888881 0.830773 0.528737 0.7647 0.5412 0.2627 +v -0.880881 0.629903 0.655432 0.0000 0.0000 0.0000 +v -0.663163 0.436754 0.655432 0.0000 0.0000 0.0000 +v -0.679163 0.838495 0.655432 0.0000 0.0000 0.0000 +v -0.382336 0.648258 0.528738 0.0000 0.0000 0.0000 +v -0.959990 0.626990 0.528738 0.0000 0.0000 0.0000 +v -0.671163 0.637624 0.703223 0.0000 0.0000 0.0000 +v -0.660145 0.360982 0.528738 0.7647 0.5412 0.2627 +v -0.682181 0.914266 0.528737 0.0000 0.0000 0.0000 +v -1.208558 0.208195 -0.425643 0.6863 0.5569 0.4196 +v -1.708103 0.227065 0.099796 0.6863 0.5569 0.4196 +v -1.353578 0.259211 -0.220091 0.6863 0.5569 0.4196 +v -1.401006 0.227422 0.157540 0.6863 0.5569 0.4196 +v -1.689707 0.223271 -0.170425 0.6863 0.5569 0.4196 +v -0.117021 1.886512 0.049046 0.0000 0.0000 0.0000 +v 0.682133 0.914266 0.528737 0.0000 0.0000 0.0000 +v 0.660098 0.360982 0.528738 0.0000 0.0000 0.0000 +v 0.671115 0.637624 0.703223 0.0000 0.0000 0.0000 +v 0.959942 0.626990 0.528738 0.0000 0.0000 0.0000 +v 0.382288 0.648258 0.528738 0.0000 0.0000 0.0000 +v 0.679115 0.838495 0.655432 0.0000 0.0000 0.0000 +v 0.663116 0.436754 0.655432 0.0000 0.0000 0.0000 +v 0.880834 0.629903 0.655432 0.0000 0.0000 0.0000 +v 0.888833 0.830773 0.528737 0.0000 0.0000 0.0000 +v 0.872834 0.429032 0.528738 0.7647 0.5412 0.2627 +v 0.469397 0.846216 0.528737 0.0000 0.0000 0.0000 +v 0.461397 0.645345 0.655432 0.0000 0.0000 0.0000 +v 0.453397 0.444475 0.528738 0.0000 0.0000 0.0000 +v 0.849699 0.796055 0.632659 0.0000 0.0000 0.0000 +v 0.836575 0.466526 0.632659 0.0000 0.0000 0.0000 +v 0.505655 0.808722 0.632659 0.0000 0.0000 0.0000 +v 0.492531 0.479193 0.632659 0.0000 0.0000 0.0000 +v 0.790813 -1.989715 0.796699 0.1490 0.3255 0.4275 +v 0.430559 -1.989715 -0.422209 0.1333 0.5098 0.5921 +v 1.134854 -1.989715 0.797664 0.1333 0.5098 0.5921 +v 1.306039 -1.989715 0.499234 0.1490 0.3255 0.4275 +v 0.756389 -1.989715 -0.467092 0.1490 0.3255 0.4275 +v 0.228774 -1.989715 -0.162474 0.1490 0.3255 0.4275 +v 1.102934 -1.692053 0.742378 0.1333 0.5098 0.5921 +v 0.465470 -1.606527 -0.361742 0.1333 0.5098 0.5921 +v 1.276870 -1.697196 0.505043 0.1333 0.5098 0.5921 +v 0.810428 -1.697196 0.774344 0.1333 0.5098 0.5921 +v 0.750608 -1.640068 -0.437233 0.1333 0.5098 0.5921 +v 0.257524 -1.640068 -0.152551 0.1333 0.5098 0.5921 +v 0.136979 -0.445499 0.233027 0.7647 0.5412 0.2627 +v 0.331101 -0.358998 0.222609 0.6863 0.5569 0.4196 +v 0.465838 -0.215053 0.214114 0.7647 0.5412 0.2627 +v 0.542622 -0.036022 0.220516 0.7647 0.5412 0.2627 +v 0.396301 0.379424 0.274974 0.7647 0.5412 0.2627 +v 0.149972 0.426291 0.296947 0.7647 0.5412 0.2627 +v 1.668600 -0.210301 -0.018074 0.6863 0.5569 0.4196 +v 1.634852 0.610777 -0.018517 0.6863 0.5569 0.4196 +v 1.389421 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v 1.369293 0.473302 0.159961 0.6863 0.5569 0.4196 +v 1.333939 0.535838 -0.234163 0.6863 0.5569 0.4196 +v 1.328090 0.724623 -0.001882 0.6863 0.5569 0.4196 +v 0.360417 1.341580 0.328657 0.7647 0.5412 0.2627 +v 0.988873 1.056686 0.321924 0.7647 0.5451 0.2627 +v 1.266507 -0.272971 0.305163 0.6863 0.5569 0.4196 +v 1.131911 -0.714433 0.262372 0.7647 0.5412 0.2627 +v 0.735619 -0.996442 0.327327 0.6863 0.5569 0.4196 +v 0.301858 -1.228287 0.292899 0.7647 0.5412 0.2627 +v 0.294441 -1.196195 -0.348768 0.6863 0.5569 0.4196 +v 0.205578 -0.773612 -0.483765 0.6863 0.5569 0.4196 +v 0.328686 -1.348132 -0.001882 0.6863 0.5569 0.4196 +v 0.743102 -1.007688 -0.348875 0.6863 0.5569 0.4196 +v 0.512474 -0.643158 -0.483765 0.6863 0.5569 0.4196 +v 0.828968 -1.138370 -0.001882 0.6863 0.5569 0.4196 +v 1.072911 -0.687550 -0.348651 0.6863 0.5569 0.4196 +v 0.733709 -0.423388 -0.483765 0.6863 0.5569 0.4196 +v 1.197396 -0.781043 -0.001882 0.6863 0.5569 0.4196 +v 1.264831 -0.272602 -0.351883 0.6863 0.5569 0.4196 +v 0.861900 -0.145380 -0.483765 0.6863 0.5569 0.4196 +v 0.958945 1.018711 -0.347098 0.6863 0.5569 0.4196 +v 0.648673 0.720775 -0.483617 0.6863 0.5569 0.4196 +v 1.081225 1.135520 -0.001882 0.6863 0.5569 0.4196 +v 0.361624 1.337784 -0.357899 0.6863 0.5569 0.4196 +v 0.245530 0.912701 -0.500168 0.6863 0.5569 0.4196 +v 0.408033 1.495910 0.002639 0.6863 0.5569 0.4196 +v 0.873560 0.178240 -0.483764 0.6863 0.5569 0.4196 +v 0.548103 0.143171 0.238963 0.7647 0.5412 0.2627 +v 1.883324 0.226736 -0.021286 0.6863 0.5569 0.4196 +v 1.336690 0.186328 0.284611 0.6863 0.5569 0.4196 +v 0.225157 1.987604 0.049046 0.0000 0.0000 0.0000 +v 0.110305 1.633271 0.049046 0.0000 0.0000 0.0000 +v 0.219050 1.726008 0.049046 0.0000 0.0000 0.0000 +v 0.384375 1.708523 0.049046 0.0000 0.0000 0.0000 +v 0.464312 1.594421 0.049046 0.0000 0.0000 0.0000 +v 0.510423 1.849038 0.049046 0.0000 0.0000 0.0000 +v 0.431930 1.955380 0.049046 0.0000 0.0000 0.0000 +v 0.705440 1.797495 0.049046 0.0000 0.0000 0.0000 +v 0.819174 1.849922 0.049046 0.0000 0.0000 0.0000 +v 0.627256 1.592906 0.049046 0.0000 0.0000 0.0000 +v 0.709015 1.561661 0.049046 0.0000 0.0000 0.0000 +v -0.329807 -1.453215 0.099725 0.1333 0.5098 0.5921 +v -0.509203 -1.499851 0.441965 0.1333 0.5098 0.5921 +v -1.139706 -1.499852 0.077944 0.1333 0.5098 0.5921 +v -0.933016 -1.453215 -0.248537 0.1333 0.5098 0.5921 +v -0.847438 -1.386274 0.299763 0.1333 0.5098 0.5921 +v -0.656507 -1.342822 -0.030939 0.1333 0.5098 0.5921 +v -1.201975 -1.989715 0.026602 0.1333 0.5098 0.5921 +v -0.993590 -1.989715 -0.291854 0.1333 0.5098 0.5921 +v -0.262006 -1.989715 0.130526 0.1490 0.3255 0.4275 +v -0.433605 -1.989715 0.470221 0.1490 0.3255 0.4275 +v 0.261959 -1.989715 0.130526 0.1490 0.3255 0.4275 +v 0.433557 -1.989715 0.470221 0.1490 0.3255 0.4275 +v 1.201928 -1.989715 0.026602 0.1333 0.5098 0.5921 +v 0.993542 -1.989715 -0.291854 0.1490 0.3255 0.4275 +v 0.847390 -1.386274 0.299763 0.1333 0.5098 0.5921 +v 0.656459 -1.342822 -0.030939 0.1333 0.5098 0.5921 +v 0.932968 -1.453215 -0.248537 0.1333 0.5098 0.5921 +v 1.139658 -1.499852 0.077944 0.1333 0.5098 0.5921 +v 0.509156 -1.499851 0.441965 0.1333 0.5098 0.5921 +v 0.329759 -1.453215 0.099725 0.1333 0.5098 0.5921 +v -0.917141 0.217841 0.506885 0.7647 0.5412 0.2627 +v -0.898540 -0.132377 0.533835 1.0000 0.8666 0.2432 +v 0.784262 -0.449848 0.504895 0.7647 0.5412 0.2627 +v -0.784309 -0.449848 0.504895 0.7647 0.5412 0.2627 +v 0.169304 -0.781843 0.538509 1.0000 1.0000 1.0000 +v 0.911546 -0.146931 0.508725 0.7647 0.5412 0.2627 +v 0.921092 0.233138 0.528393 1.0000 0.4078 0.9882 +v -0.537471 -0.676284 0.510709 0.7647 0.5412 0.2627 +v -0.550304 -0.050190 -0.268081 0.6863 0.5569 0.4196 +v -0.333329 -0.376174 -0.259143 0.6863 0.5569 0.4196 +v -0.136310 -0.462810 -0.255886 0.6863 0.5569 0.4196 +v -0.471258 -0.231320 -0.264451 0.6863 0.5569 0.4196 +v -0.155226 0.486399 -0.250189 0.6863 0.5569 0.4196 +v -0.406476 0.417073 -0.251665 0.6863 0.5569 0.4196 +v -0.556686 0.140539 -0.266073 0.6863 0.5569 0.4196 +v 0.155178 0.486399 -0.250189 0.6863 0.5569 0.4196 +v 0.471210 -0.231320 -0.264451 0.6863 0.5569 0.4196 +v 0.333281 -0.376174 -0.259143 0.6863 0.5569 0.4196 +v 0.136263 -0.462810 -0.255886 0.6863 0.5569 0.4196 +v 0.406428 0.417073 -0.251665 0.6863 0.5569 0.4196 +v 0.550257 -0.050190 -0.268081 0.6863 0.5569 0.4196 +v 0.556639 0.140539 -0.266073 0.6863 0.5569 0.4196 +v 0.951506 0.308656 0.519839 0.7647 0.5412 0.2627 +v 1.192262 0.207553 0.483259 1.0000 0.4078 0.9882 +v 1.161848 0.132033 0.491813 1.0000 0.4078 0.9882 +v 0.787644 -0.206789 0.530810 0.7647 0.5412 0.2627 +v 0.931584 -0.427672 0.526893 1.0000 1.0000 1.0000 +v 0.719056 -0.251470 0.530017 1.0000 1.0000 1.0000 +v 0.862996 -0.472354 0.526101 1.0000 1.0000 1.0000 +v 0.256867 0.776367 0.570285 0.7647 0.5412 0.2627 +v 0.122991 1.001520 0.540177 1.0000 0.8666 0.2432 +v 0.326653 0.818699 0.576548 0.7647 0.5412 0.2627 +v 0.192777 1.043853 0.546439 1.0000 0.8666 0.2432 +v -1.053355 0.096116 0.526872 0.7647 0.5412 0.2627 +v -0.847422 -0.068449 0.532664 1.0000 0.8666 0.2432 +v -1.104474 0.032188 0.528043 1.0000 0.8666 0.2432 +v -0.427348 1.007432 0.524742 0.7647 0.5412 0.2627 +v -0.216225 1.156508 0.472525 1.0000 0.6432 0.2941 +v -0.378309 0.945370 0.545834 1.0000 0.6432 0.2941 +v -0.167186 1.094447 0.493616 1.0000 0.6432 0.2941 +v 0.047981 -1.029588 0.527199 0.7647 0.5412 0.2627 +v 0.089289 -0.770295 0.551372 1.0000 1.0000 1.0000 +v 0.127997 -1.041135 0.514337 1.0000 1.0000 1.0000 +v -0.812201 -0.611882 0.489972 0.7647 0.5412 0.2627 +v -0.594493 -0.469400 0.532697 0.7647 0.5412 0.2627 +v -0.769058 -0.680753 0.499805 1.0000 0.4078 0.9882 +v -0.551349 -0.538272 0.542530 1.0000 0.4078 0.9882 +v 0.413451 -0.612636 0.572124 0.7647 0.5412 0.2627 +v 0.671917 -0.663051 0.558821 0.7647 0.1059 0.5373 +v 0.397272 -0.689505 0.549089 0.7647 0.1059 0.5373 +v 0.655738 -0.739920 0.535785 0.7647 0.1059 0.5373 +v -0.251563 -0.888049 0.548096 0.7647 0.5412 0.2627 +v -0.389159 -0.663137 0.545764 1.0000 0.6432 0.2941 +v -0.181736 -0.845343 0.546784 1.0000 0.6432 0.2941 +v -0.319332 -0.620431 0.544451 1.0000 0.6432 0.2941 +v -0.000024 0.946691 0.510828 0.7647 0.5412 0.2627 +v -1.208558 0.208195 -0.425643 0.6863 0.5569 0.4196 +v -1.208558 0.208195 -0.425643 0.6863 0.5569 0.4196 +v -1.208558 0.208195 -0.425643 0.6863 0.5569 0.4196 +v -1.208558 0.208195 -0.425643 0.6863 0.5569 0.4196 +v -1.208558 0.208195 -0.425643 0.6863 0.5569 0.4196 +v -1.208558 0.208195 -0.425643 0.6863 0.5569 0.4196 +v -1.208558 0.208195 -0.425643 0.6863 0.5569 0.4196 +v -1.389469 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v -1.389469 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v -1.389469 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v -1.389469 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v -1.389469 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v -1.389469 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v -1.389469 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v -1.389469 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v -1.389469 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v -1.389469 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v -1.353578 0.259211 -0.220091 0.6863 0.5569 0.4196 +v -1.353578 0.259211 -0.220091 0.6863 0.5569 0.4196 +v -1.353578 0.259211 -0.220091 0.6863 0.5569 0.4196 +v -0.219098 1.726008 0.049046 0.0000 0.0000 0.0000 +v -0.219098 1.726008 0.049046 0.0000 0.0000 0.0000 +v -0.219098 1.726008 0.049046 0.0000 0.0000 0.0000 +v -0.384422 1.708523 0.049046 0.0000 0.0000 0.0000 +v -0.384422 1.708523 0.049046 0.0000 0.0000 0.0000 +v -0.464360 1.594421 0.049046 0.0000 0.0000 0.0000 +v -0.464360 1.594421 0.049046 0.0000 0.0000 0.0000 +v -0.110353 1.633271 0.049046 0.0000 0.0000 0.0000 +v 0.360417 1.341580 0.328657 0.6863 0.5569 0.4196 +v 0.360417 1.341580 0.328657 0.6863 0.5569 0.4196 +v 0.360417 1.341580 0.328657 0.7647 0.5412 0.2627 +v 0.360417 1.341580 0.328657 0.7647 0.5412 0.2627 +v 0.360417 1.341580 0.328657 0.7647 0.5412 0.2627 +v 0.360417 1.341580 0.328657 0.7647 0.5412 0.2627 +v 0.408033 1.495910 0.002639 0.6863 0.5569 0.4196 +v 0.408033 1.495910 0.002639 0.6863 0.5569 0.4196 +v 0.408033 1.495910 0.002639 0.6863 0.5569 0.4196 +v 0.408033 1.495910 0.002639 0.6863 0.5569 0.4196 +v 0.408033 1.495910 0.002639 0.6863 0.5569 0.4196 +v 0.408033 1.495910 0.002639 0.6863 0.5569 0.4196 +v 0.408033 1.495910 0.002639 0.6863 0.5569 0.4196 +v -0.408081 1.495910 0.002639 0.6863 0.5569 0.4196 +v -0.408081 1.495910 0.002639 0.6863 0.5569 0.4196 +v -0.408081 1.495910 0.002639 0.6863 0.5569 0.4196 +v -0.408081 1.495910 0.002639 0.6863 0.5569 0.4196 +v -0.408081 1.495910 0.002639 0.6863 0.5569 0.4196 +v -0.360465 1.341580 0.328657 0.6863 0.5569 0.4196 +v -0.360465 1.341580 0.328657 0.6863 0.5569 0.4196 +v -0.360465 1.341580 0.328657 0.7647 0.5412 0.2627 +v -0.360465 1.341580 0.328657 0.7647 0.5412 0.2627 +v -0.360465 1.341580 0.328657 0.7647 0.5412 0.2627 +v -0.988921 1.056686 0.321924 0.7647 0.5490 0.2667 +v -0.988921 1.056686 0.321924 0.7647 0.5490 0.2667 +v -0.988921 1.056686 0.321924 0.6863 0.5569 0.4196 +v -0.988921 1.056686 0.321924 0.6863 0.5569 0.4196 +v -0.988921 1.056686 0.321924 0.7647 0.5490 0.2667 +v -0.988921 1.056686 0.321924 0.6863 0.5569 0.4196 +v -0.988921 1.056686 0.321924 0.7647 0.5490 0.2667 +v -0.988921 1.056686 0.321924 0.6863 0.5569 0.4196 +v -0.427348 1.007432 0.524742 0.7647 0.5412 0.2627 +v -0.427348 1.007432 0.524742 0.7647 0.5412 0.2627 +v -0.427348 1.007432 0.524742 1.0000 0.6432 0.2941 +v -0.427348 1.007432 0.524742 0.7647 0.5412 0.2627 +v -0.427348 1.007432 0.524742 0.7647 0.5412 0.2627 +v -1.197443 -0.781043 -0.001882 0.6863 0.5569 0.4196 +v -1.197443 -0.781043 -0.001882 0.6863 0.5569 0.4196 +v -1.197443 -0.781043 -0.001882 0.6863 0.5569 0.4196 +v -1.197443 -0.781043 -0.001882 0.6863 0.5569 0.4196 +v -1.072958 -0.687550 -0.348651 0.6863 0.5569 0.4196 +v -1.072958 -0.687550 -0.348651 0.6863 0.5569 0.4196 +v -1.072958 -0.687550 -0.348651 0.6863 0.5569 0.4196 +v -1.072958 -0.687550 -0.348651 0.6863 0.5569 0.4196 +v -1.072958 -0.687550 -0.348651 0.6863 0.5569 0.4196 +v -0.743150 -1.007688 -0.348875 0.6863 0.5569 0.4196 +v -0.743150 -1.007688 -0.348875 0.6863 0.5569 0.4196 +v -0.743150 -1.007688 -0.348875 0.6863 0.5569 0.4196 +v -0.743150 -1.007688 -0.348875 0.6863 0.5569 0.4196 +v -0.743150 -1.007688 -0.348875 0.6863 0.5569 0.4196 +v -0.743150 -1.007688 -0.348875 0.6863 0.5569 0.4196 +v -0.829016 -1.138370 -0.001882 0.6863 0.5569 0.4196 +v -0.829016 -1.138370 -0.001882 0.6863 0.5569 0.4196 +v -0.829016 -1.138370 -0.001882 0.6863 0.5569 0.4196 +v -0.829016 -1.138370 -0.001882 0.6863 0.5569 0.4196 +v -0.829016 -1.138370 -0.001882 0.6863 0.5569 0.4196 +v -1.401006 0.227422 0.157540 0.6863 0.5569 0.4196 +v -1.401006 0.227422 0.157540 0.6863 0.5569 0.4196 +v -1.401006 0.227422 0.157540 0.6863 0.5569 0.4196 +v -1.401006 0.227422 0.157540 0.6863 0.5569 0.4196 +v -1.336737 0.186328 0.284611 0.6863 0.5569 0.4196 +v -1.336737 0.186328 0.284611 0.6863 0.5569 0.4196 +v -1.336737 0.186328 0.284611 0.6863 0.5569 0.4196 +v -1.336737 0.186328 0.284611 0.7647 0.5530 0.2667 +v -1.336737 0.186328 0.284611 0.7647 0.5530 0.2667 +v -1.336737 0.186328 0.284611 0.7647 0.5530 0.2667 +v -1.336737 0.186328 0.284611 0.7647 0.5530 0.2667 +v -1.336737 0.186328 0.284611 0.7647 0.5530 0.2667 +v -1.369341 0.473302 0.159961 0.6863 0.5569 0.4196 +v -1.369341 0.473302 0.159961 0.6863 0.5569 0.4196 +v -1.369341 0.473302 0.159961 0.6863 0.5569 0.4196 +v -1.369341 0.473302 0.159961 0.6863 0.5569 0.4196 +v -1.369341 0.473302 0.159961 0.6863 0.5569 0.4196 +v -1.369341 0.473302 0.159961 0.6863 0.5569 0.4196 +v -1.266555 -0.272971 0.305163 0.6863 0.5569 0.4196 +v -1.266555 -0.272971 0.305163 0.6863 0.5569 0.4196 +v -1.266555 -0.272971 0.305163 0.6863 0.5569 0.4196 +v -1.266555 -0.272971 0.305163 0.7647 0.5412 0.2627 +v -1.266555 -0.272971 0.305163 0.7647 0.5412 0.2627 +v -1.266555 -0.272971 0.305163 0.7647 0.5412 0.2627 +v -0.958993 1.018711 -0.347098 0.6863 0.5569 0.4196 +v -0.958993 1.018711 -0.347098 0.6863 0.5569 0.4196 +v -0.958993 1.018711 -0.347098 0.6863 0.5569 0.4196 +v -0.958993 1.018711 -0.347098 0.6863 0.5569 0.4196 +v -0.958993 1.018711 -0.347098 0.6863 0.5569 0.4196 +v -0.958993 1.018711 -0.347098 0.6863 0.5569 0.4196 +v -1.333987 0.535838 -0.234163 0.6863 0.5569 0.4196 +v -1.333987 0.535838 -0.234163 0.6863 0.5569 0.4196 +v -1.333987 0.535838 -0.234163 0.6863 0.5569 0.4196 +v -1.333987 0.535838 -0.234163 0.6863 0.5569 0.4196 +v -1.333987 0.535838 -0.234163 0.6863 0.5569 0.4196 +v -1.328137 0.724623 -0.001882 0.6863 0.5569 0.4196 +v -1.328137 0.724623 -0.001882 0.6863 0.5569 0.4196 +v -1.328137 0.724623 -0.001882 0.6863 0.5569 0.4196 +v -1.328137 0.724623 -0.001882 0.6863 0.5569 0.4196 +v -1.081273 1.135520 -0.001882 0.6863 0.5569 0.4196 +v -1.081273 1.135520 -0.001882 0.6863 0.5569 0.4196 +v -1.081273 1.135520 -0.001882 0.6863 0.5569 0.4196 +v -1.081273 1.135520 -0.001882 0.6863 0.5569 0.4196 +v -0.861948 -0.145380 -0.483765 0.6863 0.5569 0.4196 +v -0.861948 -0.145380 -0.483765 0.6863 0.5569 0.4196 +v -0.861948 -0.145380 -0.483765 0.6863 0.5569 0.4196 +v -0.861948 -0.145380 -0.483765 0.6863 0.5569 0.4196 +v -0.861948 -0.145380 -0.483765 0.6863 0.5569 0.4196 +v -0.873608 0.178240 -0.483764 0.6863 0.5569 0.4196 +v -0.873608 0.178240 -0.483764 0.6863 0.5569 0.4196 +v -0.873608 0.178240 -0.483764 0.6863 0.5569 0.4196 +v -0.873608 0.178240 -0.483764 0.6863 0.5569 0.4196 +v -0.873608 0.178240 -0.483764 0.6863 0.5569 0.4196 +v -0.556686 0.140539 -0.266073 0.6863 0.5569 0.4196 +v -0.556686 0.140539 -0.266073 0.6863 0.5569 0.4196 +v -0.556686 0.140539 -0.266073 0.6863 0.5569 0.4196 +v -0.556686 0.140539 -0.266073 0.6863 0.5569 0.4196 +v -0.550304 -0.050190 -0.268081 0.6863 0.5569 0.4196 +v -0.550304 -0.050190 -0.268081 0.6863 0.5569 0.4196 +v -0.550304 -0.050190 -0.268081 0.6863 0.5569 0.4196 +v -0.550304 -0.050190 -0.268081 0.6863 0.5569 0.4196 +v -0.550304 -0.050190 -0.268081 0.6863 0.5569 0.4196 +v 0.550257 -0.050190 -0.268081 0.6863 0.5569 0.4196 +v 0.550257 -0.050190 -0.268081 0.6863 0.5569 0.4196 +v 0.550257 -0.050190 -0.268081 0.6863 0.5569 0.4196 +v 0.550257 -0.050190 -0.268081 0.6863 0.5569 0.4196 +v 0.550257 -0.050190 -0.268081 0.6863 0.5569 0.4196 +v 0.542622 -0.036022 0.220516 0.6863 0.5569 0.4196 +v 0.542622 -0.036022 0.220516 0.6863 0.5569 0.4196 +v 0.542622 -0.036022 0.220516 0.7647 0.5412 0.2627 +v 0.542622 -0.036022 0.220516 0.7647 0.5412 0.2627 +v 0.542622 -0.036022 0.220516 0.6863 0.5569 0.4196 +v 0.542622 -0.036022 0.220516 0.7647 0.5412 0.2627 +v 0.548103 0.143171 0.238963 0.6863 0.5569 0.4196 +v 0.548103 0.143171 0.238963 0.6863 0.5569 0.4196 +v 0.548103 0.143171 0.238963 0.7647 0.5412 0.2627 +v 0.548103 0.143171 0.238963 0.7647 0.5412 0.2627 +v 0.548103 0.143171 0.238963 0.7647 0.5412 0.2627 +v 0.548103 0.143171 0.238963 0.7647 0.5412 0.2627 +v 0.548103 0.143171 0.238963 0.6863 0.5569 0.4196 +v 0.556639 0.140539 -0.266073 0.6863 0.5569 0.4196 +v 0.556639 0.140539 -0.266073 0.6863 0.5569 0.4196 +v 0.556639 0.140539 -0.266073 0.6863 0.5569 0.4196 +v 0.556639 0.140539 -0.266073 0.6863 0.5569 0.4196 +v -0.155226 0.486399 -0.250189 0.6863 0.5569 0.4196 +v -0.155226 0.486399 -0.250189 0.6863 0.5569 0.4196 +v -0.155226 0.486399 -0.250189 0.6863 0.5569 0.4196 +v -0.155226 0.486399 -0.250189 0.6863 0.5569 0.4196 +v -0.155226 0.486399 -0.250189 0.6863 0.5569 0.4196 +v -0.155226 0.486399 -0.250189 0.6863 0.5569 0.4196 +v 0.155178 0.486399 -0.250189 0.6863 0.5569 0.4196 +v 0.155178 0.486399 -0.250189 0.6863 0.5569 0.4196 +v 0.155178 0.486399 -0.250189 0.6863 0.5569 0.4196 +v 0.155178 0.486399 -0.250189 0.6863 0.5569 0.4196 +v 0.149972 0.426291 0.296947 0.6863 0.5569 0.4196 +v 0.149972 0.426291 0.296947 0.6863 0.5569 0.4196 +v 0.149972 0.426291 0.296947 0.7647 0.5412 0.2627 +v 0.149972 0.426291 0.296947 0.6863 0.5569 0.4196 +v 0.149972 0.426291 0.296947 0.7647 0.5412 0.2627 +v -0.150019 0.426291 0.296947 0.6863 0.5569 0.4196 +v -0.150019 0.426291 0.296947 0.7647 0.5412 0.2627 +v -0.150019 0.426291 0.296947 0.7647 0.5412 0.2627 +v -0.150019 0.426291 0.296947 0.7647 0.5412 0.2627 +v -0.150019 0.426291 0.296947 0.7647 0.5412 0.2627 +v -0.150019 0.426291 0.296947 0.7647 0.5412 0.2627 +v 0.361624 1.337784 -0.357899 0.6863 0.5569 0.4196 +v 0.361624 1.337784 -0.357899 0.6863 0.5569 0.4196 +v 0.361624 1.337784 -0.357899 0.6863 0.5569 0.4196 +v 0.361624 1.337784 -0.357899 0.6863 0.5569 0.4196 +v 0.361624 1.337784 -0.357899 0.6863 0.5569 0.4196 +v -0.361672 1.337784 -0.357899 0.6863 0.5569 0.4196 +v -0.361672 1.337784 -0.357899 0.6863 0.5569 0.4196 +v -0.361672 1.337784 -0.357899 0.6863 0.5569 0.4196 +v -0.361672 1.337784 -0.357899 0.6863 0.5569 0.4196 +v -0.361672 1.337784 -0.357899 0.6863 0.5569 0.4196 +v -0.396349 0.379424 0.274974 0.7372 0.5490 0.3333 +v -0.396349 0.379424 0.274974 0.6863 0.5569 0.4196 +v -0.396349 0.379424 0.274974 0.6863 0.5569 0.4196 +v -0.396349 0.379424 0.274974 0.7372 0.5490 0.3333 +v -0.396349 0.379424 0.274974 0.6863 0.5569 0.4196 +v -0.406476 0.417073 -0.251665 0.6863 0.5569 0.4196 +v -0.406476 0.417073 -0.251665 0.6863 0.5569 0.4196 +v -0.406476 0.417073 -0.251665 0.6863 0.5569 0.4196 +v -0.406476 0.417073 -0.251665 0.6863 0.5569 0.4196 +v -0.406476 0.417073 -0.251665 0.6863 0.5569 0.4196 +v -0.406476 0.417073 -0.251665 0.6863 0.5569 0.4196 +v -0.245577 0.912701 -0.500168 0.6863 0.5569 0.4196 +v -0.245577 0.912701 -0.500168 0.6863 0.5569 0.4196 +v -0.245577 0.912701 -0.500168 0.6863 0.5569 0.4196 +v -0.245577 0.912701 -0.500168 0.6863 0.5569 0.4196 +v -0.245577 0.912701 -0.500168 0.6863 0.5569 0.4196 +v 0.245530 0.912701 -0.500168 0.6863 0.5569 0.4196 +v 0.245530 0.912701 -0.500168 0.6863 0.5569 0.4196 +v 0.245530 0.912701 -0.500168 0.6863 0.5569 0.4196 +v 0.245530 0.912701 -0.500168 0.6863 0.5569 0.4196 +v 0.245530 0.912701 -0.500168 0.6863 0.5569 0.4196 +v -1.668647 -0.210301 -0.018074 0.6863 0.5569 0.4196 +v -1.668647 -0.210301 -0.018074 0.6863 0.5569 0.4196 +v -1.668647 -0.210301 -0.018074 0.6863 0.5569 0.4196 +v -1.708103 0.227065 0.099796 0.6863 0.5569 0.4196 +v -1.708103 0.227065 0.099796 0.6863 0.5569 0.4196 +v -1.708103 0.227065 0.099796 0.6863 0.5569 0.4196 +v -1.708103 0.227065 0.099796 0.6863 0.5569 0.4196 +v -1.708103 0.227065 0.099796 0.6863 0.5569 0.4196 +v -1.883371 0.226736 -0.021286 0.6863 0.5569 0.4196 +v -1.883371 0.226736 -0.021286 0.6863 0.5569 0.4196 +v -1.883371 0.226736 -0.021286 0.6863 0.5569 0.4196 +v -1.689707 0.223271 -0.170425 0.6863 0.5569 0.4196 +v -1.689707 0.223271 -0.170425 0.6863 0.5569 0.4196 +v -1.689707 0.223271 -0.170425 0.6863 0.5569 0.4196 +v -1.689707 0.223271 -0.170425 0.6863 0.5569 0.4196 +v -1.689707 0.223271 -0.170425 0.6863 0.5569 0.4196 +v 0.136979 -0.445499 0.233027 0.6863 0.5569 0.4196 +v 0.136979 -0.445499 0.233027 0.6863 0.5569 0.4196 +v 0.136979 -0.445499 0.233027 0.7647 0.5412 0.2627 +v 0.136979 -0.445499 0.233027 0.7647 0.5412 0.2627 +v 0.136979 -0.445499 0.233027 0.7647 0.5412 0.2627 +v 0.136263 -0.462810 -0.255886 0.6863 0.5569 0.4196 +v 0.136263 -0.462810 -0.255886 0.6863 0.5569 0.4196 +v 0.136263 -0.462810 -0.255886 0.6863 0.5569 0.4196 +v 0.136263 -0.462810 -0.255886 0.6863 0.5569 0.4196 +v 0.136263 -0.462810 -0.255886 0.6863 0.5569 0.4196 +v 0.136263 -0.462810 -0.255886 0.6863 0.5569 0.4196 +v -0.136310 -0.462810 -0.255886 0.6863 0.5569 0.4196 +v -0.136310 -0.462810 -0.255886 0.6863 0.5569 0.4196 +v -0.136310 -0.462810 -0.255886 0.6863 0.5569 0.4196 +v -0.136310 -0.462810 -0.255886 0.6863 0.5569 0.4196 +v -0.137027 -0.445499 0.233027 0.6863 0.5569 0.4196 +v -0.137027 -0.445499 0.233027 0.6863 0.5569 0.4196 +v -0.137027 -0.445499 0.233027 0.7647 0.5412 0.2627 +v -0.137027 -0.445499 0.233027 0.7647 0.5412 0.2627 +v -0.137027 -0.445499 0.233027 0.7647 0.5412 0.2627 +v -0.137027 -0.445499 0.233027 0.6863 0.5569 0.4196 +v -0.682181 0.914266 0.528737 0.7647 0.5412 0.2627 +v -0.682181 0.914266 0.528737 0.0000 0.0000 0.0000 +v -0.682181 0.914266 0.528737 0.0000 0.0000 0.0000 +v -0.682181 0.914266 0.528737 0.7647 0.5412 0.2627 +v -0.682181 0.914266 0.528737 0.0000 0.0000 0.0000 +v -0.682181 0.914266 0.528737 0.7647 0.5412 0.2627 +v -0.888881 0.830773 0.528737 0.7647 0.5412 0.2627 +v -0.888881 0.830773 0.528737 0.0000 0.0000 0.0000 +v -0.888881 0.830773 0.528737 0.0000 0.0000 0.0000 +v -0.328733 -1.348132 -0.001882 0.6863 0.5569 0.4196 +v -0.328733 -1.348132 -0.001882 0.6863 0.5569 0.4196 +v -0.328733 -1.348132 -0.001882 0.6863 0.5569 0.4196 +v -0.328733 -1.348132 -0.001882 0.6863 0.5569 0.4196 +v -0.328733 -1.348132 -0.001882 0.6863 0.5569 0.4196 +v -0.301905 -1.228287 0.292899 0.6863 0.5569 0.4196 +v -0.301905 -1.228287 0.292899 0.6863 0.5569 0.4196 +v -0.301905 -1.228287 0.292899 0.6863 0.5569 0.4196 +v -0.301905 -1.228287 0.292899 0.7647 0.5412 0.2627 +v -0.301905 -1.228287 0.292899 0.7647 0.5412 0.2627 +v -0.301905 -1.228287 0.292899 0.7647 0.5412 0.2627 +v -0.301905 -1.228287 0.292899 0.6863 0.5569 0.4196 +v -0.301905 -1.228287 0.292899 0.7647 0.5412 0.2627 +v -0.735667 -0.996442 0.327327 0.6863 0.5569 0.4196 +v -0.735667 -0.996442 0.327327 0.7647 0.5412 0.2627 +v -0.735667 -0.996442 0.327327 0.7647 0.5412 0.2627 +v -0.735667 -0.996442 0.327327 0.7647 0.5412 0.2627 +v -0.735667 -0.996442 0.327327 0.7647 0.5412 0.2627 +v -0.735667 -0.996442 0.327327 0.6863 0.5569 0.4196 +v -0.471258 -0.231320 -0.264451 0.6863 0.5569 0.4196 +v -0.471258 -0.231320 -0.264451 0.6863 0.5569 0.4196 +v -0.471258 -0.231320 -0.264451 0.6863 0.5569 0.4196 +v -0.471258 -0.231320 -0.264451 0.6863 0.5569 0.4196 +v -0.733756 -0.423388 -0.483765 0.6863 0.5569 0.4196 +v -0.733756 -0.423388 -0.483765 0.6863 0.5569 0.4196 +v -0.733756 -0.423388 -0.483765 0.6863 0.5569 0.4196 +v -0.733756 -0.423388 -0.483765 0.6863 0.5569 0.4196 +v -0.733756 -0.423388 -0.483765 0.6863 0.5569 0.4196 +v -0.465518 -1.606527 -0.361742 0.1333 0.5098 0.5921 +v -0.465518 -1.606527 -0.361742 0.1333 0.5098 0.5921 +v -0.465518 -1.606527 -0.361742 0.1333 0.5098 0.5921 +v -0.656507 -1.342822 -0.030939 0.1333 0.5098 0.5921 +v -0.656507 -1.342822 -0.030939 0.1333 0.5098 0.5921 +v -0.656507 -1.342822 -0.030939 0.1333 0.5098 0.5921 +v -0.656507 -1.342822 -0.030939 0.1333 0.5098 0.5921 +v -0.656507 -1.342822 -0.030939 0.1333 0.5098 0.5921 +v -0.656507 -1.342822 -0.030939 0.1333 0.5098 0.5921 +v -0.656507 -1.342822 -0.030939 0.1333 0.5098 0.5921 +v -0.329807 -1.453215 0.099725 0.1333 0.5098 0.5921 +v -0.329807 -1.453215 0.099725 0.1333 0.5098 0.5921 +v -0.329807 -1.453215 0.099725 0.1333 0.5098 0.5921 +v -0.257571 -1.640068 -0.152551 0.1333 0.5098 0.5921 +v -0.257571 -1.640068 -0.152551 0.1333 0.5098 0.5921 +v -0.257571 -1.640068 -0.152551 0.1333 0.5098 0.5921 +v -0.257571 -1.640068 -0.152551 0.1333 0.5098 0.5921 +v -0.257571 -1.640068 -0.152551 0.1333 0.5098 0.5921 +v -1.264879 -0.272602 -0.351883 0.6863 0.5569 0.4196 +v -1.264879 -0.272602 -0.351883 0.6863 0.5569 0.4196 +v -1.264879 -0.272602 -0.351883 0.6863 0.5569 0.4196 +v -1.264879 -0.272602 -0.351883 0.6863 0.5569 0.4196 +v -0.648720 0.720775 -0.483617 0.6863 0.5569 0.4196 +v -0.648720 0.720775 -0.483617 0.6863 0.5569 0.4196 +v -0.648720 0.720775 -0.483617 0.6863 0.5569 0.4196 +v -0.648720 0.720775 -0.483617 0.6863 0.5569 0.4196 +v -0.648720 0.720775 -0.483617 0.6863 0.5569 0.4196 +v -0.810476 -1.697196 0.774344 0.1333 0.5098 0.5921 +v -0.810476 -1.697196 0.774344 0.1333 0.5098 0.5921 +v -0.810476 -1.697196 0.774344 0.1333 0.5098 0.5921 +v -0.810476 -1.697196 0.774344 0.1333 0.5098 0.5921 +v -0.790860 -1.989715 0.796699 0.1333 0.5098 0.5921 +v -0.790860 -1.989715 0.796699 0.1490 0.3255 0.4275 +v -0.790860 -1.989715 0.796699 0.1490 0.3255 0.4275 +v -0.790860 -1.989715 0.796699 0.1333 0.5098 0.5921 +v -0.790860 -1.989715 0.796699 0.1333 0.5098 0.5921 +v -0.433605 -1.989715 0.470221 0.1333 0.5098 0.5921 +v -0.433605 -1.989715 0.470221 0.1333 0.5098 0.5921 +v -0.433605 -1.989715 0.470221 0.1490 0.3255 0.4275 +v -0.433605 -1.989715 0.470221 0.1333 0.5098 0.5921 +v -0.433605 -1.989715 0.470221 0.1490 0.3255 0.4275 +v -0.509203 -1.499851 0.441965 0.1333 0.5098 0.5921 +v -0.509203 -1.499851 0.441965 0.1333 0.5098 0.5921 +v -0.509203 -1.499851 0.441965 0.1333 0.5098 0.5921 +v -0.509203 -1.499851 0.441965 0.1333 0.5098 0.5921 +v -0.509203 -1.499851 0.441965 0.1333 0.5098 0.5921 +v -0.382336 0.648258 0.528738 0.0000 0.0000 0.0000 +v -0.382336 0.648258 0.528738 0.0000 0.0000 0.0000 +v -0.382336 0.648258 0.528738 0.0000 0.0000 0.0000 +v -0.382336 0.648258 0.528738 0.7647 0.5412 0.2627 +v -0.382336 0.648258 0.528738 0.7647 0.5412 0.2627 +v -0.382336 0.648258 0.528738 0.7647 0.5412 0.2627 +v -0.461445 0.645345 0.655432 0.0000 0.0000 0.0000 +v -0.461445 0.645345 0.655432 0.0000 0.0000 0.0000 +v -0.461445 0.645345 0.655432 0.0000 0.0000 0.0000 +v -0.492579 0.479193 0.632659 0.0000 0.0000 0.0000 +v -0.492579 0.479193 0.632659 0.0000 0.0000 0.0000 +v -0.492579 0.479193 0.632659 0.0000 0.0000 0.0000 +v -0.492579 0.479193 0.632659 0.0000 0.0000 0.0000 +v -0.492579 0.479193 0.632659 0.0000 0.0000 0.0000 +v -0.453445 0.444475 0.528738 0.0000 0.0000 0.0000 +v -0.453445 0.444475 0.528738 0.0000 0.0000 0.0000 +v -0.453445 0.444475 0.528738 0.7647 0.5412 0.2627 +v -0.453445 0.444475 0.528738 0.7647 0.5412 0.2627 +v -0.542670 -0.036022 0.220516 0.6863 0.5569 0.4196 +v -0.542670 -0.036022 0.220516 0.7647 0.5451 0.2627 +v -0.542670 -0.036022 0.220516 0.7647 0.5451 0.2627 +v -0.542670 -0.036022 0.220516 0.7647 0.5451 0.2627 +v -0.542670 -0.036022 0.220516 0.6863 0.5569 0.4196 +v -0.465885 -0.215053 0.214114 0.7647 0.5412 0.2627 +v -0.465885 -0.215053 0.214114 0.6863 0.5569 0.4196 +v -0.465885 -0.215053 0.214114 0.7647 0.5412 0.2627 +v -0.465885 -0.215053 0.214114 0.7647 0.5412 0.2627 +v -0.465885 -0.215053 0.214114 0.6863 0.5569 0.4196 +v -0.465885 -0.215053 0.214114 0.6863 0.5569 0.4196 +v -0.465885 -0.215053 0.214114 0.7647 0.5412 0.2627 +v 0.301858 -1.228287 0.292899 0.6863 0.5569 0.4196 +v 0.301858 -1.228287 0.292899 0.7647 0.5412 0.2627 +v 0.301858 -1.228287 0.292899 0.7647 0.5412 0.2627 +v 0.301858 -1.228287 0.292899 0.7647 0.5412 0.2627 +v 0.301858 -1.228287 0.292899 0.7647 0.5412 0.2627 +v 0.301858 -1.228287 0.292899 0.6863 0.5569 0.4196 +v 0.301858 -1.228287 0.292899 0.6863 0.5569 0.4196 +v 0.328686 -1.348132 -0.001882 0.6863 0.5569 0.4196 +v 0.328686 -1.348132 -0.001882 0.6863 0.5569 0.4196 +v 0.328686 -1.348132 -0.001882 0.6863 0.5569 0.4196 +v 0.328686 -1.348132 -0.001882 0.6863 0.5569 0.4196 +v 0.328686 -1.348132 -0.001882 0.6863 0.5569 0.4196 +v 1.102934 -1.692053 0.742378 0.1333 0.5098 0.5921 +v 1.102934 -1.692053 0.742378 0.1333 0.5098 0.5921 +v 1.102934 -1.692053 0.742378 0.1333 0.5098 0.5921 +v 1.102934 -1.692053 0.742378 0.1333 0.5098 0.5921 +v 1.102934 -1.692053 0.742378 0.1333 0.5098 0.5921 +v 0.847390 -1.386274 0.299763 0.1333 0.5098 0.5921 +v 0.847390 -1.386274 0.299763 0.1333 0.5098 0.5921 +v 0.847390 -1.386274 0.299763 0.1333 0.5098 0.5921 +v 0.847390 -1.386274 0.299763 0.1333 0.5098 0.5921 +v 0.847390 -1.386274 0.299763 0.1333 0.5098 0.5921 +v 0.509156 -1.499851 0.441965 0.1333 0.5098 0.5921 +v 0.509156 -1.499851 0.441965 0.1333 0.5098 0.5921 +v 0.509156 -1.499851 0.441965 0.1333 0.5098 0.5921 +v 0.509156 -1.499851 0.441965 0.1333 0.5098 0.5921 +v 0.509156 -1.499851 0.441965 0.1333 0.5098 0.5921 +v 0.810428 -1.697196 0.774344 0.1333 0.5098 0.5921 +v 0.810428 -1.697196 0.774344 0.1333 0.5098 0.5921 +v 0.810428 -1.697196 0.774344 0.1333 0.5098 0.5921 +v 0.810428 -1.697196 0.774344 0.1333 0.5098 0.5921 +v -0.993590 -1.989715 -0.291854 0.1333 0.5098 0.5921 +v -0.993590 -1.989715 -0.291854 0.1490 0.3255 0.4275 +v -0.993590 -1.989715 -0.291854 0.1333 0.5098 0.5921 +v -0.993590 -1.989715 -0.291854 0.1490 0.3255 0.4275 +v -0.993590 -1.989715 -0.291854 0.1490 0.3255 0.4275 +v -0.993590 -1.989715 -0.291854 0.1490 0.3255 0.4275 +v -0.993590 -1.989715 -0.291854 0.1333 0.5098 0.5921 +v -0.756437 -1.989715 -0.467092 0.1333 0.5098 0.5921 +v -0.756437 -1.989715 -0.467092 0.1490 0.3255 0.4275 +v -0.756437 -1.989715 -0.467092 0.1490 0.3255 0.4275 +v -0.228822 -1.989715 -0.162474 0.1490 0.3255 0.4275 +v -0.228822 -1.989715 -0.162474 0.1490 0.3255 0.4275 +v -0.228822 -1.989715 -0.162474 0.1333 0.5098 0.5921 +v -0.228822 -1.989715 -0.162474 0.1333 0.5098 0.5921 +v -0.262006 -1.989715 0.130526 0.1490 0.3255 0.4275 +v -0.262006 -1.989715 0.130526 0.1333 0.5098 0.5921 +v -0.262006 -1.989715 0.130526 0.1333 0.5098 0.5921 +v -0.262006 -1.989715 0.130526 0.1333 0.5098 0.5921 +v -0.262006 -1.989715 0.130526 0.1333 0.5098 0.5921 +v -0.225204 1.987604 0.049046 0.0000 0.0000 0.0000 +v -0.117021 1.886512 0.049046 0.0000 0.0000 0.0000 +v -0.117021 1.886512 0.049046 0.0000 0.0000 0.0000 +v -0.117021 1.886512 0.049046 0.0000 0.0000 0.0000 +v -1.634900 0.610777 -0.018517 0.6863 0.5569 0.4196 +v -1.634900 0.610777 -0.018517 0.6863 0.5569 0.4196 +v -1.634900 0.610777 -0.018517 0.6863 0.5569 0.4196 +v -1.634900 0.610777 -0.018517 0.6863 0.5569 0.4196 +v -1.634900 0.610777 -0.018517 0.6863 0.5569 0.4196 +v -0.378309 0.945370 0.545834 0.7647 0.5412 0.2627 +v -0.378309 0.945370 0.545834 0.7647 0.5412 0.2627 +v -0.378309 0.945370 0.545834 1.0000 0.6432 0.2941 +v -0.378309 0.945370 0.545834 0.7647 0.5412 0.2627 +v -0.378309 0.945370 0.545834 0.7647 0.5412 0.2627 +v -0.378309 0.945370 0.545834 0.7647 0.5412 0.2627 +v -0.000024 0.946691 0.510828 0.7647 0.5412 0.2627 +v -0.000024 0.946691 0.510828 0.7647 0.5412 0.2627 +v -0.000024 0.946691 0.510828 0.7647 0.5412 0.2627 +v -0.000024 0.946691 0.510828 0.7647 0.5412 0.2627 +v -0.000024 0.946691 0.510828 0.7647 0.5412 0.2627 +v -0.167186 1.094447 0.493616 0.7647 0.5412 0.2627 +v -0.167186 1.094447 0.493616 0.7647 0.5412 0.2627 +v -0.167186 1.094447 0.493616 0.7647 0.5412 0.2627 +v -0.167186 1.094447 0.493616 0.7647 0.5412 0.2627 +v 0.331101 -0.358998 0.222609 0.6863 0.5569 0.4196 +v 0.331101 -0.358998 0.222609 0.6863 0.5569 0.4196 +v 0.331101 -0.358998 0.222609 0.7647 0.5412 0.2627 +v 0.331101 -0.358998 0.222609 0.7647 0.5412 0.2627 +v 0.333281 -0.376174 -0.259143 0.6863 0.5569 0.4196 +v 0.333281 -0.376174 -0.259143 0.6863 0.5569 0.4196 +v 0.333281 -0.376174 -0.259143 0.6863 0.5569 0.4196 +v 0.333281 -0.376174 -0.259143 0.6863 0.5569 0.4196 +v 0.333281 -0.376174 -0.259143 0.6863 0.5569 0.4196 +v 0.333281 -0.376174 -0.259143 0.6863 0.5569 0.4196 +v -1.306086 -1.989715 0.499234 0.1490 0.3255 0.4275 +v -1.306086 -1.989715 0.499234 0.1333 0.5098 0.5921 +v -1.306086 -1.989715 0.499234 0.1490 0.3255 0.4275 +v -1.306086 -1.989715 0.499234 0.1333 0.5098 0.5921 +v -1.134901 -1.989715 0.797664 0.1490 0.3255 0.4275 +v -1.134901 -1.989715 0.797664 0.1333 0.5098 0.5921 +v -1.102982 -1.692053 0.742378 0.1333 0.5098 0.5921 +v -1.102982 -1.692053 0.742378 0.1333 0.5098 0.5921 +v -1.102982 -1.692053 0.742378 0.1333 0.5098 0.5921 +v -1.102982 -1.692053 0.742378 0.1333 0.5098 0.5921 +v -1.102982 -1.692053 0.742378 0.1333 0.5098 0.5921 +v -1.276918 -1.697196 0.505043 0.1333 0.5098 0.5921 +v -1.276918 -1.697196 0.505043 0.1333 0.5098 0.5921 +v -1.276918 -1.697196 0.505043 0.1333 0.5098 0.5921 +v -1.276918 -1.697196 0.505043 0.1333 0.5098 0.5921 +v -0.551349 -0.538272 0.542530 0.7647 0.5412 0.2627 +v -0.551349 -0.538272 0.542530 0.7647 0.5412 0.2627 +v -0.551349 -0.538272 0.542530 0.7647 0.5412 0.2627 +v -0.331149 -0.358998 0.222609 0.7647 0.5412 0.2627 +v -0.331149 -0.358998 0.222609 0.7647 0.5412 0.2627 +v -0.331149 -0.358998 0.222609 0.6863 0.5569 0.4196 +v -0.331149 -0.358998 0.222609 0.7647 0.5412 0.2627 +v -0.331149 -0.358998 0.222609 0.7647 0.5412 0.2627 +v -0.331149 -0.358998 0.222609 0.7647 0.5412 0.2627 +v -0.331149 -0.358998 0.222609 0.6863 0.5569 0.4196 +v -0.331149 -0.358998 0.222609 0.6863 0.5569 0.4196 +v -0.594493 -0.469400 0.532697 0.7647 0.5412 0.2627 +v -0.594493 -0.469400 0.532697 0.7647 0.5412 0.2627 +v -0.594493 -0.469400 0.532697 1.0000 0.4078 0.9882 +v -0.594493 -0.469400 0.532697 0.7647 0.5412 0.2627 +v -0.594493 -0.469400 0.532697 1.0000 0.4078 0.9882 +v 0.873560 0.178240 -0.483764 0.6863 0.5569 0.4196 +v 0.873560 0.178240 -0.483764 0.6863 0.5569 0.4196 +v 0.873560 0.178240 -0.483764 0.6863 0.5569 0.4196 +v 0.873560 0.178240 -0.483764 0.6863 0.5569 0.4196 +v 0.873560 0.178240 -0.483764 0.6863 0.5569 0.4196 +v 0.648673 0.720775 -0.483617 0.6863 0.5569 0.4196 +v 0.648673 0.720775 -0.483617 0.6863 0.5569 0.4196 +v 0.648673 0.720775 -0.483617 0.6863 0.5569 0.4196 +v 0.648673 0.720775 -0.483617 0.6863 0.5569 0.4196 +v 0.648673 0.720775 -0.483617 0.6863 0.5569 0.4196 +v 0.958945 1.018711 -0.347098 0.6863 0.5569 0.4196 +v 0.958945 1.018711 -0.347098 0.6863 0.5569 0.4196 +v 0.958945 1.018711 -0.347098 0.6863 0.5569 0.4196 +v 0.958945 1.018711 -0.347098 0.6863 0.5569 0.4196 +v 0.958945 1.018711 -0.347098 0.6863 0.5569 0.4196 +v 0.958945 1.018711 -0.347098 0.6863 0.5569 0.4196 +v 1.208511 0.208195 -0.425643 0.6863 0.5569 0.4196 +v 1.208511 0.208195 -0.425643 0.6863 0.5569 0.4196 +v 1.208511 0.208195 -0.425643 0.6863 0.5569 0.4196 +v 1.208511 0.208195 -0.425643 0.6863 0.5569 0.4196 +v 1.208511 0.208195 -0.425643 0.6863 0.5569 0.4196 +v 1.208511 0.208195 -0.425643 0.6863 0.5569 0.4196 +v 1.208511 0.208195 -0.425643 0.6863 0.5569 0.4196 +v -0.847438 -1.386274 0.299763 0.1333 0.5098 0.5921 +v -0.847438 -1.386274 0.299763 0.1333 0.5098 0.5921 +v -0.847438 -1.386274 0.299763 0.1333 0.5098 0.5921 +v -0.847438 -1.386274 0.299763 0.1333 0.5098 0.5921 +v -0.847438 -1.386274 0.299763 0.1333 0.5098 0.5921 +v -0.898540 -0.132377 0.533835 0.7647 0.5412 0.2627 +v -0.898540 -0.132377 0.533835 0.7647 0.5412 0.2627 +v -0.898540 -0.132377 0.533835 0.7647 0.5412 0.2627 +v -0.898540 -0.132377 0.533835 0.7647 0.5412 0.2627 +v -0.898540 -0.132377 0.533835 0.7647 0.5412 0.2627 +v -0.784309 -0.449848 0.504895 0.7647 0.5412 0.2627 +v -0.784309 -0.449848 0.504895 0.7647 0.5412 0.2627 +v -0.784309 -0.449848 0.504895 0.7647 0.5412 0.2627 +v -0.784309 -0.449848 0.504895 0.7647 0.5412 0.2627 +v -0.784309 -0.449848 0.504895 0.7647 0.5412 0.2627 +v -0.836623 0.466526 0.632659 0.0000 0.0000 0.0000 +v -0.836623 0.466526 0.632659 0.0000 0.0000 0.0000 +v -0.836623 0.466526 0.632659 0.0000 0.0000 0.0000 +v -0.836623 0.466526 0.632659 0.0000 0.0000 0.0000 +v -0.836623 0.466526 0.632659 0.0000 0.0000 0.0000 +v -0.880881 0.629903 0.655432 0.0000 0.0000 0.0000 +v -0.880881 0.629903 0.655432 0.0000 0.0000 0.0000 +v -0.880881 0.629903 0.655432 0.0000 0.0000 0.0000 +v -0.959990 0.626990 0.528738 0.0000 0.0000 0.0000 +v -0.959990 0.626990 0.528738 0.0000 0.0000 0.0000 +v -0.959990 0.626990 0.528738 0.0000 0.0000 0.0000 +v -0.959990 0.626990 0.528738 0.7647 0.5412 0.2627 +v -0.959990 0.626990 0.528738 0.7647 0.5412 0.2627 +v -0.959990 0.626990 0.528738 0.7647 0.5412 0.2627 +v -0.872881 0.429032 0.528738 0.0000 0.0000 0.0000 +v -0.872881 0.429032 0.528738 0.0000 0.0000 0.0000 +v -0.872881 0.429032 0.528738 0.7647 0.5412 0.2627 +v -0.872881 0.429032 0.528738 0.7647 0.5412 0.2627 +v 0.787644 -0.206789 0.530810 0.7647 0.5412 0.2627 +v 0.787644 -0.206789 0.530810 1.0000 1.0000 1.0000 +v 0.787644 -0.206789 0.530810 0.7647 0.5412 0.2627 +v 0.911546 -0.146931 0.508725 0.7647 0.5412 0.2627 +v 0.911546 -0.146931 0.508725 0.7647 0.5412 0.2627 +v 0.911546 -0.146931 0.508725 0.7647 0.5412 0.2627 +v 0.911546 -0.146931 0.508725 0.7647 0.5412 0.2627 +v 0.911546 -0.146931 0.508725 0.7647 0.5412 0.2627 +v 0.911546 -0.146931 0.508725 0.7647 0.5412 0.2627 +v 0.256867 0.776367 0.570285 0.7647 0.5412 0.2627 +v 0.256867 0.776367 0.570285 0.7647 0.5412 0.2627 +v 0.256867 0.776367 0.570285 1.0000 0.8666 0.2432 +v 0.256867 0.776367 0.570285 0.7647 0.5412 0.2627 +v -0.430607 -1.989715 -0.422209 0.1490 0.3255 0.4275 +v -0.430607 -1.989715 -0.422209 0.1333 0.5098 0.5921 +v -0.430607 -1.989715 -0.422209 0.1333 0.5098 0.5921 +v -0.430607 -1.989715 -0.422209 0.1333 0.5098 0.5921 +v 0.413451 -0.612636 0.572124 0.7647 0.5412 0.2627 +v 0.413451 -0.612636 0.572124 0.7647 0.5412 0.2627 +v 0.413451 -0.612636 0.572124 0.7647 0.5412 0.2627 +v 0.413451 -0.612636 0.572124 0.7647 0.1059 0.5373 +v 0.413451 -0.612636 0.572124 0.7647 0.5412 0.2627 +v 0.465838 -0.215053 0.214114 0.7647 0.5412 0.2627 +v 0.465838 -0.215053 0.214114 0.7647 0.5412 0.2627 +v 0.465838 -0.215053 0.214114 0.6863 0.5569 0.4196 +v 0.465838 -0.215053 0.214114 0.7647 0.5412 0.2627 +v 0.465838 -0.215053 0.214114 0.7647 0.5412 0.2627 +v 0.465838 -0.215053 0.214114 0.6863 0.5569 0.4196 +v 0.465838 -0.215053 0.214114 0.6863 0.5569 0.4196 +v 0.465838 -0.215053 0.214114 0.6863 0.5569 0.4196 +v 1.306039 -1.989715 0.499234 0.1490 0.3255 0.4275 +v 1.306039 -1.989715 0.499234 0.1333 0.5098 0.5921 +v 1.306039 -1.989715 0.499234 0.1333 0.5098 0.5921 +v 1.306039 -1.989715 0.499234 0.1333 0.5098 0.5921 +v 1.134854 -1.989715 0.797664 0.1490 0.3255 0.4275 +v 1.134854 -1.989715 0.797664 0.1333 0.5098 0.5921 +v 0.790813 -1.989715 0.796699 0.1490 0.3255 0.4275 +v 0.790813 -1.989715 0.796699 0.1333 0.5098 0.5921 +v 0.790813 -1.989715 0.796699 0.1490 0.3255 0.4275 +v 0.790813 -1.989715 0.796699 0.1333 0.5098 0.5921 +v 0.790813 -1.989715 0.796699 0.1333 0.5098 0.5921 +v 0.406428 0.417073 -0.251665 0.6863 0.5569 0.4196 +v 0.406428 0.417073 -0.251665 0.6863 0.5569 0.4196 +v 0.406428 0.417073 -0.251665 0.6863 0.5569 0.4196 +v 0.406428 0.417073 -0.251665 0.6863 0.5569 0.4196 +v 0.406428 0.417073 -0.251665 0.6863 0.5569 0.4196 +v 0.406428 0.417073 -0.251665 0.6863 0.5569 0.4196 +v -0.333329 -0.376174 -0.259143 0.6863 0.5569 0.4196 +v -0.333329 -0.376174 -0.259143 0.6863 0.5569 0.4196 +v -0.333329 -0.376174 -0.259143 0.6863 0.5569 0.4196 +v -0.333329 -0.376174 -0.259143 0.6863 0.5569 0.4196 +v -0.333329 -0.376174 -0.259143 0.6863 0.5569 0.4196 +v -0.333329 -0.376174 -0.259143 0.6863 0.5569 0.4196 +v -0.294489 -1.196195 -0.348768 0.6863 0.5569 0.4196 +v -0.294489 -1.196195 -0.348768 0.6863 0.5569 0.4196 +v -0.294489 -1.196195 -0.348768 0.6863 0.5569 0.4196 +v -0.294489 -1.196195 -0.348768 0.6863 0.5569 0.4196 +v 0.469397 0.846216 0.528737 0.7647 0.5412 0.2627 +v 0.469397 0.846216 0.528737 0.7647 0.5412 0.2627 +v 0.469397 0.846216 0.528737 0.0000 0.0000 0.0000 +v 0.469397 0.846216 0.528737 0.7647 0.5412 0.2627 +v 0.988873 1.056686 0.321924 0.7647 0.5451 0.2627 +v 0.988873 1.056686 0.321924 0.7647 0.5451 0.2627 +v 0.988873 1.056686 0.321924 0.6863 0.5569 0.4196 +v 0.988873 1.056686 0.321924 0.6863 0.5569 0.4196 +v 0.988873 1.056686 0.321924 0.6863 0.5569 0.4196 +v 0.988873 1.056686 0.321924 0.7647 0.5451 0.2627 +v 0.988873 1.056686 0.321924 0.7647 0.5451 0.2627 +v 0.988873 1.056686 0.321924 0.7647 0.5451 0.2627 +v 0.988873 1.056686 0.321924 0.6863 0.5569 0.4196 +v 0.988873 1.056686 0.321924 0.7647 0.5451 0.2627 +v 0.326653 0.818699 0.576548 0.7647 0.5412 0.2627 +v 0.326653 0.818699 0.576548 1.0000 0.8666 0.2432 +v 0.326653 0.818699 0.576548 0.7647 0.5412 0.2627 +v 0.326653 0.818699 0.576548 0.7647 0.5412 0.2627 +v 0.326653 0.818699 0.576548 0.7647 0.5412 0.2627 +v 0.326653 0.818699 0.576548 1.0000 0.8666 0.2432 +v 0.205578 -0.773612 -0.483765 0.6863 0.5569 0.4196 +v 0.205578 -0.773612 -0.483765 0.6863 0.5569 0.4196 +v 0.205578 -0.773612 -0.483765 0.6863 0.5569 0.4196 +v 0.205578 -0.773612 -0.483765 0.6863 0.5569 0.4196 +v 0.205578 -0.773612 -0.483765 0.6863 0.5569 0.4196 +v 0.205578 -0.773612 -0.483765 0.6863 0.5569 0.4196 +v -0.205626 -0.773612 -0.483765 0.6863 0.5569 0.4196 +v -0.205626 -0.773612 -0.483765 0.6863 0.5569 0.4196 +v -0.205626 -0.773612 -0.483765 0.6863 0.5569 0.4196 +v -0.205626 -0.773612 -0.483765 0.6863 0.5569 0.4196 +v -0.205626 -0.773612 -0.483765 0.6863 0.5569 0.4196 +v -0.205626 -0.773612 -0.483765 0.6863 0.5569 0.4196 +v -0.663163 0.436754 0.655432 0.0000 0.0000 0.0000 +v -0.663163 0.436754 0.655432 0.0000 0.0000 0.0000 +v -0.663163 0.436754 0.655432 0.0000 0.0000 0.0000 +v -0.671163 0.637624 0.703223 0.0000 0.0000 0.0000 +v -0.671163 0.637624 0.703223 0.0000 0.0000 0.0000 +v -0.671163 0.637624 0.703223 0.0000 0.0000 0.0000 +v -0.671163 0.637624 0.703223 0.0000 0.0000 0.0000 +v -0.671163 0.637624 0.703223 0.0000 0.0000 0.0000 +v -0.671163 0.637624 0.703223 0.0000 0.0000 0.0000 +v -0.671163 0.637624 0.703223 0.0000 0.0000 0.0000 +v -0.849747 0.796055 0.632659 0.0000 0.0000 0.0000 +v -0.849747 0.796055 0.632659 0.0000 0.0000 0.0000 +v -0.849747 0.796055 0.632659 0.0000 0.0000 0.0000 +v -0.849747 0.796055 0.632659 0.0000 0.0000 0.0000 +v -0.849747 0.796055 0.632659 0.0000 0.0000 0.0000 +v -0.679163 0.838495 0.655432 0.0000 0.0000 0.0000 +v -0.679163 0.838495 0.655432 0.0000 0.0000 0.0000 +v -0.679163 0.838495 0.655432 0.0000 0.0000 0.0000 +v -1.201975 -1.989715 0.026602 0.1490 0.3255 0.4275 +v -1.201975 -1.989715 0.026602 0.1333 0.5098 0.5921 +v -1.201975 -1.989715 0.026602 0.1490 0.3255 0.4275 +v -1.201975 -1.989715 0.026602 0.1490 0.3255 0.4275 +v -1.201975 -1.989715 0.026602 0.1333 0.5098 0.5921 +v -1.139706 -1.499852 0.077944 0.1333 0.5098 0.5921 +v -1.139706 -1.499852 0.077944 0.1333 0.5098 0.5921 +v -1.139706 -1.499852 0.077944 0.1333 0.5098 0.5921 +v -1.139706 -1.499852 0.077944 0.1333 0.5098 0.5921 +v -1.139706 -1.499852 0.077944 0.1333 0.5098 0.5921 +v 0.471210 -0.231320 -0.264451 0.6863 0.5569 0.4196 +v 0.471210 -0.231320 -0.264451 0.6863 0.5569 0.4196 +v 0.471210 -0.231320 -0.264451 0.6863 0.5569 0.4196 +v 0.471210 -0.231320 -0.264451 0.6863 0.5569 0.4196 +v 0.169304 -0.781843 0.538509 0.7647 0.5412 0.2627 +v 0.169304 -0.781843 0.538509 0.7647 0.5412 0.2627 +v 0.169304 -0.781843 0.538509 0.7647 0.5412 0.2627 +v 0.169304 -0.781843 0.538509 0.7647 0.5412 0.2627 +v 0.169304 -0.781843 0.538509 0.7647 0.5412 0.2627 +v 0.089289 -0.770295 0.551372 0.7647 0.5412 0.2627 +v 0.089289 -0.770295 0.551372 1.0000 1.0000 1.0000 +v 0.089289 -0.770295 0.551372 0.7647 0.5412 0.2627 +v 0.089289 -0.770295 0.551372 0.7647 0.5412 0.2627 +v 0.089289 -0.770295 0.551372 0.7647 0.5412 0.2627 +v -1.131959 -0.714433 0.262372 0.6863 0.5569 0.4196 +v -1.131959 -0.714433 0.262372 0.6863 0.5569 0.4196 +v -1.131959 -0.714433 0.262372 0.7647 0.5412 0.2627 +v -1.131959 -0.714433 0.262372 0.7647 0.5412 0.2627 +v -1.131959 -0.714433 0.262372 0.6863 0.5569 0.4196 +v -1.131959 -0.714433 0.262372 0.6863 0.5569 0.4196 +v -0.660145 0.360982 0.528738 0.0000 0.0000 0.0000 +v -0.660145 0.360982 0.528738 0.0000 0.0000 0.0000 +v -0.660145 0.360982 0.528738 0.0000 0.0000 0.0000 +v -0.660145 0.360982 0.528738 0.7647 0.5412 0.2627 +v -0.660145 0.360982 0.528738 0.7647 0.5412 0.2627 +v -0.660145 0.360982 0.528738 0.7647 0.5412 0.2627 +v -0.660145 0.360982 0.528738 0.0000 0.0000 0.0000 +v -0.750656 -1.640068 -0.437233 0.1333 0.5098 0.5921 +v -0.750656 -1.640068 -0.437233 0.1333 0.5098 0.5921 +v -0.750656 -1.640068 -0.437233 0.1333 0.5098 0.5921 +v -0.750656 -1.640068 -0.437233 0.1333 0.5098 0.5921 +v -0.750656 -1.640068 -0.437233 0.1333 0.5098 0.5921 +v -0.933016 -1.453215 -0.248537 0.1333 0.5098 0.5921 +v -0.933016 -1.453215 -0.248537 0.1333 0.5098 0.5921 +v -0.933016 -1.453215 -0.248537 0.1333 0.5098 0.5921 +v -0.505703 0.808722 0.632659 0.0000 0.0000 0.0000 +v -0.505703 0.808722 0.632659 0.0000 0.0000 0.0000 +v -0.505703 0.808722 0.632659 0.0000 0.0000 0.0000 +v -0.505703 0.808722 0.632659 0.0000 0.0000 0.0000 +v -0.505703 0.808722 0.632659 0.0000 0.0000 0.0000 +v -0.469445 0.846216 0.528737 0.0000 0.0000 0.0000 +v -0.469445 0.846216 0.528737 0.0000 0.0000 0.0000 +v -0.469445 0.846216 0.528737 0.7647 0.5412 0.2627 +v -0.469445 0.846216 0.528737 0.7647 0.5412 0.2627 +v -0.512521 -0.643158 -0.483765 0.6863 0.5569 0.4196 +v -0.512521 -0.643158 -0.483765 0.6863 0.5569 0.4196 +v -0.512521 -0.643158 -0.483765 0.6863 0.5569 0.4196 +v -0.512521 -0.643158 -0.483765 0.6863 0.5569 0.4196 +v -0.847422 -0.068449 0.532664 0.7647 0.5412 0.2627 +v -0.847422 -0.068449 0.532664 1.0000 0.8666 0.2432 +v -0.847422 -0.068449 0.532664 0.7647 0.5412 0.2627 +v -0.847422 -0.068449 0.532664 0.7647 0.5412 0.2627 +v -0.847422 -0.068449 0.532664 0.7647 0.5412 0.2627 +v 0.294441 -1.196195 -0.348768 0.6863 0.5569 0.4196 +v 0.294441 -1.196195 -0.348768 0.6863 0.5569 0.4196 +v 0.294441 -1.196195 -0.348768 0.6863 0.5569 0.4196 +v 0.294441 -1.196195 -0.348768 0.6863 0.5569 0.4196 +v 1.328090 0.724623 -0.001882 0.6863 0.5569 0.4196 +v 1.328090 0.724623 -0.001882 0.6863 0.5569 0.4196 +v 1.328090 0.724623 -0.001882 0.6863 0.5569 0.4196 +v 1.328090 0.724623 -0.001882 0.6863 0.5569 0.4196 +v 1.634852 0.610777 -0.018517 0.6863 0.5569 0.4196 +v 1.634852 0.610777 -0.018517 0.6863 0.5569 0.4196 +v 1.634852 0.610777 -0.018517 0.6863 0.5569 0.4196 +v 1.634852 0.610777 -0.018517 0.6863 0.5569 0.4196 +v 1.634852 0.610777 -0.018517 0.6863 0.5569 0.4196 +v 1.333939 0.535838 -0.234163 0.6863 0.5569 0.4196 +v 1.333939 0.535838 -0.234163 0.6863 0.5569 0.4196 +v 1.333939 0.535838 -0.234163 0.6863 0.5569 0.4196 +v 1.333939 0.535838 -0.234163 0.6863 0.5569 0.4196 +v 1.333939 0.535838 -0.234163 0.6863 0.5569 0.4196 +v -0.819222 1.849922 0.049046 0.0000 0.0000 0.0000 +v -0.819222 1.849922 0.049046 0.0000 0.0000 0.0000 +v -0.709062 1.561661 0.049046 0.0000 0.0000 0.0000 +v -0.705487 1.797495 0.049046 0.0000 0.0000 0.0000 +v -0.705487 1.797495 0.049046 0.0000 0.0000 0.0000 +v 0.663116 0.436754 0.655432 0.0000 0.0000 0.0000 +v 0.663116 0.436754 0.655432 0.0000 0.0000 0.0000 +v 0.663116 0.436754 0.655432 0.0000 0.0000 0.0000 +v 0.836575 0.466526 0.632659 0.0000 0.0000 0.0000 +v 0.836575 0.466526 0.632659 0.0000 0.0000 0.0000 +v 0.836575 0.466526 0.632659 0.0000 0.0000 0.0000 +v 0.836575 0.466526 0.632659 0.0000 0.0000 0.0000 +v 0.836575 0.466526 0.632659 0.0000 0.0000 0.0000 +v 0.880834 0.629903 0.655432 0.0000 0.0000 0.0000 +v 0.880834 0.629903 0.655432 0.0000 0.0000 0.0000 +v 0.880834 0.629903 0.655432 0.0000 0.0000 0.0000 +v 0.671115 0.637624 0.703223 0.0000 0.0000 0.0000 +v 0.671115 0.637624 0.703223 0.0000 0.0000 0.0000 +v 0.671115 0.637624 0.703223 0.0000 0.0000 0.0000 +v 0.671115 0.637624 0.703223 0.0000 0.0000 0.0000 +v 0.671115 0.637624 0.703223 0.0000 0.0000 0.0000 +v 0.671115 0.637624 0.703223 0.0000 0.0000 0.0000 +v 0.671115 0.637624 0.703223 0.0000 0.0000 0.0000 +v 0.682133 0.914266 0.528737 0.7647 0.5412 0.2627 +v 0.682133 0.914266 0.528737 0.0000 0.0000 0.0000 +v 0.682133 0.914266 0.528737 0.0000 0.0000 0.0000 +v 0.682133 0.914266 0.528737 0.0000 0.0000 0.0000 +v 0.682133 0.914266 0.528737 0.7647 0.5412 0.2627 +v 1.197396 -0.781043 -0.001882 0.6863 0.5569 0.4196 +v 1.197396 -0.781043 -0.001882 0.6863 0.5569 0.4196 +v 1.197396 -0.781043 -0.001882 0.6863 0.5569 0.4196 +v 1.197396 -0.781043 -0.001882 0.6863 0.5569 0.4196 +v 1.131911 -0.714433 0.262372 0.6863 0.5569 0.4196 +v 1.131911 -0.714433 0.262372 0.7647 0.5412 0.2627 +v 1.131911 -0.714433 0.262372 0.7647 0.5412 0.2627 +v 1.131911 -0.714433 0.262372 0.7647 0.5412 0.2627 +v 1.131911 -0.714433 0.262372 0.7647 0.5412 0.2627 +v 1.131911 -0.714433 0.262372 0.7647 0.5412 0.2627 +v 1.131911 -0.714433 0.262372 0.6863 0.5569 0.4196 +v 1.131911 -0.714433 0.262372 0.6863 0.5569 0.4196 +v 1.131911 -0.714433 0.262372 0.6863 0.5569 0.4196 +v 0.735619 -0.996442 0.327327 0.7647 0.5412 0.2627 +v 0.735619 -0.996442 0.327327 0.6863 0.5569 0.4196 +v 0.735619 -0.996442 0.327327 0.7647 0.5412 0.2627 +v 0.828968 -1.138370 -0.001882 0.6863 0.5569 0.4196 +v 0.828968 -1.138370 -0.001882 0.6863 0.5569 0.4196 +v 0.828968 -1.138370 -0.001882 0.6863 0.5569 0.4196 +v 0.828968 -1.138370 -0.001882 0.6863 0.5569 0.4196 +v 0.828968 -1.138370 -0.001882 0.6863 0.5569 0.4196 +v 0.819174 1.849922 0.049046 0.0000 0.0000 0.0000 +v 0.819174 1.849922 0.049046 0.0000 0.0000 0.0000 +v 0.705440 1.797495 0.049046 0.0000 0.0000 0.0000 +v 0.705440 1.797495 0.049046 0.0000 0.0000 0.0000 +v 0.709015 1.561661 0.049046 0.0000 0.0000 0.0000 +v 0.396301 0.379424 0.274974 0.6863 0.5569 0.4196 +v 0.396301 0.379424 0.274974 0.6863 0.5569 0.4196 +v 0.396301 0.379424 0.274974 0.7647 0.5412 0.2627 +v 0.396301 0.379424 0.274974 0.7647 0.5412 0.2627 +v 0.396301 0.379424 0.274974 0.7647 0.5412 0.2627 +v 0.396301 0.379424 0.274974 0.7647 0.5412 0.2627 +v 0.396301 0.379424 0.274974 0.6863 0.5569 0.4196 +v 0.505655 0.808722 0.632659 0.0000 0.0000 0.0000 +v 0.505655 0.808722 0.632659 0.0000 0.0000 0.0000 +v 0.505655 0.808722 0.632659 0.0000 0.0000 0.0000 +v 0.505655 0.808722 0.632659 0.0000 0.0000 0.0000 +v 0.505655 0.808722 0.632659 0.0000 0.0000 0.0000 +v 0.382288 0.648258 0.528738 0.7647 0.5412 0.2627 +v 0.382288 0.648258 0.528738 0.0000 0.0000 0.0000 +v 0.382288 0.648258 0.528738 0.7647 0.5412 0.2627 +v 0.382288 0.648258 0.528738 0.0000 0.0000 0.0000 +v 0.382288 0.648258 0.528738 0.0000 0.0000 0.0000 +v 0.382288 0.648258 0.528738 0.7647 0.5412 0.2627 +v 0.461397 0.645345 0.655432 0.0000 0.0000 0.0000 +v 0.461397 0.645345 0.655432 0.0000 0.0000 0.0000 +v 0.461397 0.645345 0.655432 0.0000 0.0000 0.0000 +v 0.384375 1.708523 0.049046 0.0000 0.0000 0.0000 +v 0.384375 1.708523 0.049046 0.0000 0.0000 0.0000 +v 0.464312 1.594421 0.049046 0.0000 0.0000 0.0000 +v 0.464312 1.594421 0.049046 0.0000 0.0000 0.0000 +v 0.510423 1.849038 0.049046 0.0000 0.0000 0.0000 +v 0.510423 1.849038 0.049046 0.0000 0.0000 0.0000 +v 0.510423 1.849038 0.049046 0.0000 0.0000 0.0000 +v 0.431930 1.955380 0.049046 0.0000 0.0000 0.0000 +v 1.201928 -1.989715 0.026602 0.1333 0.5098 0.5921 +v 1.201928 -1.989715 0.026602 0.1333 0.5098 0.5921 +v 1.201928 -1.989715 0.026602 0.1490 0.3255 0.4275 +v 1.201928 -1.989715 0.026602 0.1490 0.3255 0.4275 +v 1.201928 -1.989715 0.026602 0.1490 0.3255 0.4275 +v 1.139658 -1.499852 0.077944 0.1333 0.5098 0.5921 +v 1.139658 -1.499852 0.077944 0.1333 0.5098 0.5921 +v 1.139658 -1.499852 0.077944 0.1333 0.5098 0.5921 +v 1.139658 -1.499852 0.077944 0.1333 0.5098 0.5921 +v 1.139658 -1.499852 0.077944 0.1333 0.5098 0.5921 +v 1.276870 -1.697196 0.505043 0.1333 0.5098 0.5921 +v 1.276870 -1.697196 0.505043 0.1333 0.5098 0.5921 +v 1.276870 -1.697196 0.505043 0.1333 0.5098 0.5921 +v 1.276870 -1.697196 0.505043 0.1333 0.5098 0.5921 +v 1.708056 0.227065 0.099796 0.6863 0.5569 0.4196 +v 1.708056 0.227065 0.099796 0.6863 0.5569 0.4196 +v 1.708056 0.227065 0.099796 0.6863 0.5569 0.4196 +v 1.708056 0.227065 0.099796 0.6863 0.5569 0.4196 +v 1.708056 0.227065 0.099796 0.6863 0.5569 0.4196 +v 1.883324 0.226736 -0.021286 0.6863 0.5569 0.4196 +v 1.883324 0.226736 -0.021286 0.6863 0.5569 0.4196 +v 1.883324 0.226736 -0.021286 0.6863 0.5569 0.4196 +v 0.849699 0.796055 0.632659 0.0000 0.0000 0.0000 +v 0.849699 0.796055 0.632659 0.0000 0.0000 0.0000 +v 0.849699 0.796055 0.632659 0.0000 0.0000 0.0000 +v 0.849699 0.796055 0.632659 0.0000 0.0000 0.0000 +v 0.849699 0.796055 0.632659 0.0000 0.0000 0.0000 +v 0.679115 0.838495 0.655432 0.0000 0.0000 0.0000 +v 0.679115 0.838495 0.655432 0.0000 0.0000 0.0000 +v 0.679115 0.838495 0.655432 0.0000 0.0000 0.0000 +v 0.228774 -1.989715 -0.162474 0.1333 0.5098 0.5921 +v 0.228774 -1.989715 -0.162474 0.1490 0.3255 0.4275 +v 0.228774 -1.989715 -0.162474 0.1333 0.5098 0.5921 +v 0.257524 -1.640068 -0.152551 0.1333 0.5098 0.5921 +v 0.257524 -1.640068 -0.152551 0.1333 0.5098 0.5921 +v 0.257524 -1.640068 -0.152551 0.1333 0.5098 0.5921 +v 0.257524 -1.640068 -0.152551 0.1333 0.5098 0.5921 +v 0.257524 -1.640068 -0.152551 0.1333 0.5098 0.5921 +v 0.465470 -1.606527 -0.361742 0.1333 0.5098 0.5921 +v 0.465470 -1.606527 -0.361742 0.1333 0.5098 0.5921 +v 0.465470 -1.606527 -0.361742 0.1333 0.5098 0.5921 +v 0.430559 -1.989715 -0.422209 0.1333 0.5098 0.5921 +v 0.430559 -1.989715 -0.422209 0.1333 0.5098 0.5921 +v 0.430559 -1.989715 -0.422209 0.1333 0.5098 0.5921 +v 0.430559 -1.989715 -0.422209 0.1490 0.3255 0.4275 +v 0.660098 0.360982 0.528738 0.7647 0.5412 0.2627 +v 0.660098 0.360982 0.528738 0.0000 0.0000 0.0000 +v 0.660098 0.360982 0.528738 0.0000 0.0000 0.0000 +v 0.660098 0.360982 0.528738 0.7647 0.5412 0.2627 +v 0.660098 0.360982 0.528738 0.7647 0.5412 0.2627 +v 0.660098 0.360982 0.528738 0.0000 0.0000 0.0000 +v 0.872834 0.429032 0.528738 0.7647 0.5412 0.2627 +v 0.872834 0.429032 0.528738 0.0000 0.0000 0.0000 +v 0.872834 0.429032 0.528738 0.7647 0.5412 0.2627 +v 0.872834 0.429032 0.528738 0.7647 0.5412 0.2627 +v 0.872834 0.429032 0.528738 0.0000 0.0000 0.0000 +v 1.072911 -0.687550 -0.348651 0.6863 0.5569 0.4196 +v 1.072911 -0.687550 -0.348651 0.6863 0.5569 0.4196 +v 1.072911 -0.687550 -0.348651 0.6863 0.5569 0.4196 +v 1.072911 -0.687550 -0.348651 0.6863 0.5569 0.4196 +v 1.072911 -0.687550 -0.348651 0.6863 0.5569 0.4196 +v 0.743102 -1.007688 -0.348875 0.6863 0.5569 0.4196 +v 0.743102 -1.007688 -0.348875 0.6863 0.5569 0.4196 +v 0.743102 -1.007688 -0.348875 0.6863 0.5569 0.4196 +v 0.743102 -1.007688 -0.348875 0.6863 0.5569 0.4196 +v 0.743102 -1.007688 -0.348875 0.6863 0.5569 0.4196 +v 0.743102 -1.007688 -0.348875 0.6863 0.5569 0.4196 +v 0.512474 -0.643158 -0.483765 0.6863 0.5569 0.4196 +v 0.512474 -0.643158 -0.483765 0.6863 0.5569 0.4196 +v 0.512474 -0.643158 -0.483765 0.6863 0.5569 0.4196 +v 0.512474 -0.643158 -0.483765 0.6863 0.5569 0.4196 +v 0.733709 -0.423388 -0.483765 0.6863 0.5569 0.4196 +v 0.733709 -0.423388 -0.483765 0.6863 0.5569 0.4196 +v 0.733709 -0.423388 -0.483765 0.6863 0.5569 0.4196 +v 0.733709 -0.423388 -0.483765 0.6863 0.5569 0.4196 +v 0.733709 -0.423388 -0.483765 0.6863 0.5569 0.4196 +v 0.750608 -1.640068 -0.437233 0.1333 0.5098 0.5921 +v 0.750608 -1.640068 -0.437233 0.1333 0.5098 0.5921 +v 0.750608 -1.640068 -0.437233 0.1333 0.5098 0.5921 +v 0.750608 -1.640068 -0.437233 0.1333 0.5098 0.5921 +v 0.750608 -1.640068 -0.437233 0.1333 0.5098 0.5921 +v 0.656459 -1.342822 -0.030939 0.1333 0.5098 0.5921 +v 0.656459 -1.342822 -0.030939 0.1333 0.5098 0.5921 +v 0.656459 -1.342822 -0.030939 0.1333 0.5098 0.5921 +v 0.656459 -1.342822 -0.030939 0.1333 0.5098 0.5921 +v 0.656459 -1.342822 -0.030939 0.1333 0.5098 0.5921 +v 0.656459 -1.342822 -0.030939 0.1333 0.5098 0.5921 +v 0.656459 -1.342822 -0.030939 0.1333 0.5098 0.5921 +v 0.932968 -1.453215 -0.248537 0.1333 0.5098 0.5921 +v 0.932968 -1.453215 -0.248537 0.1333 0.5098 0.5921 +v 0.932968 -1.453215 -0.248537 0.1333 0.5098 0.5921 +v 0.756389 -1.989715 -0.467092 0.1333 0.5098 0.5921 +v 0.756389 -1.989715 -0.467092 0.1490 0.3255 0.4275 +v 0.756389 -1.989715 -0.467092 0.1333 0.5098 0.5921 +v 0.756389 -1.989715 -0.467092 0.1490 0.3255 0.4275 +v 0.453397 0.444475 0.528738 0.0000 0.0000 0.0000 +v 0.453397 0.444475 0.528738 0.7647 0.5412 0.2627 +v 0.453397 0.444475 0.528738 0.7647 0.5412 0.2627 +v 0.453397 0.444475 0.528738 0.7647 0.5412 0.2627 +v 0.492531 0.479193 0.632659 0.0000 0.0000 0.0000 +v 0.492531 0.479193 0.632659 0.0000 0.0000 0.0000 +v 0.492531 0.479193 0.632659 0.0000 0.0000 0.0000 +v 0.492531 0.479193 0.632659 0.0000 0.0000 0.0000 +v 0.492531 0.479193 0.632659 0.0000 0.0000 0.0000 +v 1.369293 0.473302 0.159961 0.6863 0.5569 0.4196 +v 1.369293 0.473302 0.159961 0.6863 0.5569 0.4196 +v 1.369293 0.473302 0.159961 0.6863 0.5569 0.4196 +v 1.369293 0.473302 0.159961 0.6863 0.5569 0.4196 +v 1.369293 0.473302 0.159961 0.6863 0.5569 0.4196 +v 1.369293 0.473302 0.159961 0.6863 0.5569 0.4196 +v 1.389421 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v 1.389421 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v 1.389421 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v 1.389421 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v 1.389421 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v 1.389421 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v 1.389421 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v 1.389421 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v 1.389421 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v 1.389421 -0.309882 -0.017359 0.6863 0.5569 0.4196 +v 1.266507 -0.272971 0.305163 0.6863 0.5569 0.4196 +v 1.266507 -0.272971 0.305163 0.7647 0.5530 0.2667 +v 1.266507 -0.272971 0.305163 0.7647 0.5530 0.2667 +v 1.266507 -0.272971 0.305163 0.7647 0.5530 0.2667 +v 1.266507 -0.272971 0.305163 0.7647 0.5530 0.2667 +v 1.266507 -0.272971 0.305163 0.6863 0.5569 0.4196 +v 0.993542 -1.989715 -0.291854 0.1333 0.5098 0.5921 +v 0.993542 -1.989715 -0.291854 0.1333 0.5098 0.5921 +v 0.993542 -1.989715 -0.291854 0.1490 0.3255 0.4275 +v 0.993542 -1.989715 -0.291854 0.1490 0.3255 0.4275 +v 0.993542 -1.989715 -0.291854 0.1333 0.5098 0.5921 +v 0.993542 -1.989715 -0.291854 0.1333 0.5098 0.5921 +v 0.671917 -0.663051 0.558821 0.7647 0.5412 0.2627 +v 0.671917 -0.663051 0.558821 0.7647 0.5412 0.2627 +v 0.671917 -0.663051 0.558821 0.7647 0.5412 0.2627 +v 0.671917 -0.663051 0.558821 0.7647 0.1059 0.5373 +v 0.671917 -0.663051 0.558821 0.7647 0.5412 0.2627 +v 0.888833 0.830773 0.528737 0.0000 0.0000 0.0000 +v 0.888833 0.830773 0.528737 0.7647 0.5412 0.2627 +v 0.888833 0.830773 0.528737 0.7647 0.5412 0.2627 +v 0.861900 -0.145380 -0.483765 0.6863 0.5569 0.4196 +v 0.861900 -0.145380 -0.483765 0.6863 0.5569 0.4196 +v 0.861900 -0.145380 -0.483765 0.6863 0.5569 0.4196 +v 0.861900 -0.145380 -0.483765 0.6863 0.5569 0.4196 +v 0.861900 -0.145380 -0.483765 0.6863 0.5569 0.4196 +v 1.264831 -0.272602 -0.351883 0.6863 0.5569 0.4196 +v 1.264831 -0.272602 -0.351883 0.6863 0.5569 0.4196 +v 1.264831 -0.272602 -0.351883 0.6863 0.5569 0.4196 +v 1.264831 -0.272602 -0.351883 0.6863 0.5569 0.4196 +v 1.353531 0.259211 -0.220091 0.6863 0.5569 0.4196 +v 1.353531 0.259211 -0.220091 0.6863 0.5569 0.4196 +v 1.353531 0.259211 -0.220091 0.6863 0.5569 0.4196 +v 0.219050 1.726008 0.049046 0.0000 0.0000 0.0000 +v 0.219050 1.726008 0.049046 0.0000 0.0000 0.0000 +v 0.219050 1.726008 0.049046 0.0000 0.0000 0.0000 +v 0.110305 1.633271 0.049046 0.0000 0.0000 0.0000 +v 1.689659 0.223271 -0.170425 0.6863 0.5569 0.4196 +v 1.689659 0.223271 -0.170425 0.6863 0.5569 0.4196 +v 1.689659 0.223271 -0.170425 0.6863 0.5569 0.4196 +v 1.689659 0.223271 -0.170425 0.6863 0.5569 0.4196 +v 1.689659 0.223271 -0.170425 0.6863 0.5569 0.4196 +v 1.081225 1.135520 -0.001882 0.6863 0.5569 0.4196 +v 1.081225 1.135520 -0.001882 0.6863 0.5569 0.4196 +v 1.081225 1.135520 -0.001882 0.6863 0.5569 0.4196 +v 1.081225 1.135520 -0.001882 0.6863 0.5569 0.4196 +v 1.400959 0.227422 0.157540 0.6863 0.5569 0.4196 +v 1.400959 0.227422 0.157540 0.6863 0.5569 0.4196 +v 1.400959 0.227422 0.157540 0.6863 0.5569 0.4196 +v 1.400959 0.227422 0.157540 0.6863 0.5569 0.4196 +v 1.336690 0.186328 0.284611 0.6863 0.5569 0.4196 +v 1.336690 0.186328 0.284611 0.6863 0.5569 0.4196 +v 1.336690 0.186328 0.284611 0.7529 0.6276 0.3019 +v 1.336690 0.186328 0.284611 0.7529 0.6276 0.3019 +v 1.336690 0.186328 0.284611 0.7529 0.6276 0.3019 +v 1.336690 0.186328 0.284611 0.7529 0.6276 0.3019 +v 1.336690 0.186328 0.284611 0.7529 0.6276 0.3019 +v 1.336690 0.186328 0.284611 0.7529 0.6276 0.3019 +v 0.433557 -1.989715 0.470221 0.1333 0.5098 0.5921 +v 0.433557 -1.989715 0.470221 0.1490 0.3255 0.4275 +v 0.433557 -1.989715 0.470221 0.1333 0.5098 0.5921 +v 0.433557 -1.989715 0.470221 0.1333 0.5098 0.5921 +v 0.433557 -1.989715 0.470221 0.1490 0.3255 0.4275 +v 0.784262 -0.449848 0.504895 0.7647 0.5412 0.2627 +v 0.784262 -0.449848 0.504895 0.7647 0.5412 0.2627 +v 0.784262 -0.449848 0.504895 0.7647 0.5412 0.2627 +v 0.784262 -0.449848 0.504895 0.7647 0.5412 0.2627 +v 0.261959 -1.989715 0.130526 0.1490 0.3255 0.4275 +v 0.261959 -1.989715 0.130526 0.1333 0.5098 0.5921 +v 0.261959 -1.989715 0.130526 0.1333 0.5098 0.5921 +v 0.261959 -1.989715 0.130526 0.1333 0.5098 0.5921 +v 0.261959 -1.989715 0.130526 0.1333 0.5098 0.5921 +v 0.261959 -1.989715 0.130526 0.1490 0.3255 0.4275 +v 0.959942 0.626990 0.528738 0.7647 0.5647 0.2706 +v 0.959942 0.626990 0.528738 0.0000 0.0000 0.0000 +v 0.959942 0.626990 0.528738 0.7647 0.5647 0.2706 +v 0.959942 0.626990 0.528738 0.7647 0.5647 0.2706 +v 0.959942 0.626990 0.528738 0.0000 0.0000 0.0000 +v 0.959942 0.626990 0.528738 0.0000 0.0000 0.0000 +v 1.668600 -0.210301 -0.018074 0.6863 0.5569 0.4196 +v 1.668600 -0.210301 -0.018074 0.6863 0.5569 0.4196 +v 1.668600 -0.210301 -0.018074 0.6863 0.5569 0.4196 +v 0.225157 1.987604 0.049046 0.0000 0.0000 0.0000 +v 0.225157 1.987604 0.049046 0.0000 0.0000 0.0000 +v 0.116973 1.886512 0.049046 0.0000 0.0000 0.0000 +v 0.116973 1.886512 0.049046 0.0000 0.0000 0.0000 +v 0.329759 -1.453215 0.099725 0.1333 0.5098 0.5921 +v 0.329759 -1.453215 0.099725 0.1333 0.5098 0.5921 +v 0.329759 -1.453215 0.099725 0.1333 0.5098 0.5921 +v -0.431978 1.955380 0.049046 0.0000 0.0000 0.0000 +v -0.510471 1.849038 0.049046 0.0000 0.0000 0.0000 +v -0.510471 1.849038 0.049046 0.0000 0.0000 0.0000 +v -0.510471 1.849038 0.049046 0.0000 0.0000 0.0000 +v -0.181736 -0.845343 0.546784 0.7647 0.5412 0.2627 +v -0.181736 -0.845343 0.546784 1.0000 0.6432 0.2941 +v -0.181736 -0.845343 0.546784 0.7647 0.5412 0.2627 +v -0.181736 -0.845343 0.546784 0.7647 0.5412 0.2627 +v -0.181736 -0.845343 0.546784 0.7647 0.5412 0.2627 +v -0.181736 -0.845343 0.546784 0.7647 0.5412 0.2627 +v 0.047981 -1.029588 0.527199 0.7647 0.5412 0.2627 +v 0.047981 -1.029588 0.527199 1.0000 1.0000 1.0000 +v 0.047981 -1.029588 0.527199 0.7647 0.5412 0.2627 +v 0.921092 0.233138 0.528393 0.7647 0.5412 0.2627 +v 0.921092 0.233138 0.528393 1.0000 0.4078 0.9882 +v 0.921092 0.233138 0.528393 0.7647 0.5412 0.2627 +v 0.921092 0.233138 0.528393 0.7647 0.5412 0.2627 +v 0.921092 0.233138 0.528393 0.7647 0.5412 0.2627 +v 0.921092 0.233138 0.528393 0.7647 0.5412 0.2627 +v 0.122991 1.001520 0.540177 0.7647 0.5412 0.2627 +v 0.122991 1.001520 0.540177 0.7647 0.5412 0.2627 +v 0.122991 1.001520 0.540177 0.7647 0.5412 0.2627 +v 0.122991 1.001520 0.540177 1.0000 0.8666 0.2432 +v 0.122991 1.001520 0.540177 0.7647 0.5412 0.2627 +v -0.251563 -0.888049 0.548096 0.7647 0.5412 0.2627 +v -0.251563 -0.888049 0.548096 1.0000 0.6432 0.2941 +v -0.251563 -0.888049 0.548096 0.7647 0.5412 0.2627 +v -0.251563 -0.888049 0.548096 0.7647 0.5412 0.2627 +v -0.548150 0.143171 0.238963 0.6863 0.5569 0.4196 +v -0.548150 0.143171 0.238963 0.7647 0.5451 0.2627 +v -0.548150 0.143171 0.238963 0.6863 0.5569 0.4196 +v -0.548150 0.143171 0.238963 0.7647 0.5451 0.2627 +v -0.548150 0.143171 0.238963 0.7647 0.5451 0.2627 +v -0.548150 0.143171 0.238963 0.7647 0.5451 0.2627 +v 0.951506 0.308656 0.519839 1.0000 0.4078 0.9882 +v 0.951506 0.308656 0.519839 0.7647 0.5412 0.2627 +v 0.951506 0.308656 0.519839 0.7647 0.5412 0.2627 +v 1.161848 0.132033 0.491813 0.7647 0.5412 0.2627 +v 1.161848 0.132033 0.491813 0.7647 0.5412 0.2627 +v 1.161848 0.132033 0.491813 0.7647 0.5412 0.2627 +v 1.161848 0.132033 0.491813 0.7647 0.5412 0.2627 +v 1.192262 0.207553 0.483259 0.7647 0.5412 0.2627 +v 1.192262 0.207553 0.483259 1.0000 0.4078 0.9882 +v 1.192262 0.207553 0.483259 0.7647 0.5412 0.2627 +v 0.719056 -0.251470 0.530017 1.0000 1.0000 1.0000 +v 0.719056 -0.251470 0.530017 0.7647 0.5412 0.2627 +v 0.719056 -0.251470 0.530017 0.7647 0.5412 0.2627 +v 0.719056 -0.251470 0.530017 0.7647 0.5412 0.2627 +v 0.719056 -0.251470 0.530017 0.7647 0.5412 0.2627 +v 0.862996 -0.472354 0.526101 0.7647 0.5412 0.2627 +v 0.862996 -0.472354 0.526101 0.7647 0.5412 0.2627 +v 0.862996 -0.472354 0.526101 0.7647 0.5412 0.2627 +v 0.931584 -0.427672 0.526893 0.7647 0.5412 0.2627 +v 0.931584 -0.427672 0.526893 1.0000 1.0000 1.0000 +v 0.931584 -0.427672 0.526893 0.7647 0.5412 0.2627 +v 0.931584 -0.427672 0.526893 0.7647 0.5412 0.2627 +v 0.931584 -0.427672 0.526893 0.7647 0.5412 0.2627 +v 0.192777 1.043853 0.546439 0.7647 0.5412 0.2627 +v 0.192777 1.043853 0.546439 0.7647 0.5412 0.2627 +v 0.192777 1.043853 0.546439 0.7647 0.5412 0.2627 +v -1.053355 0.096116 0.526872 1.0000 0.8666 0.2432 +v -1.053355 0.096116 0.526872 0.7647 0.5412 0.2627 +v -1.053355 0.096116 0.526872 0.7647 0.5412 0.2627 +v -1.104474 0.032188 0.528043 1.0000 0.8666 0.2432 +v -1.104474 0.032188 0.528043 0.7647 0.5412 0.2627 +v -1.104474 0.032188 0.528043 0.7647 0.5412 0.2627 +v -1.104474 0.032188 0.528043 0.7647 0.5412 0.2627 +v -0.216225 1.156508 0.472525 0.7647 0.5412 0.2627 +v -0.216225 1.156508 0.472525 1.0000 0.6432 0.2941 +v -0.216225 1.156508 0.472525 0.7647 0.5412 0.2627 +v -0.216225 1.156508 0.472525 0.7647 0.5412 0.2627 +v 0.127997 -1.041135 0.514337 1.0000 1.0000 1.0000 +v 0.127997 -1.041135 0.514337 0.7647 0.5412 0.2627 +v 0.127997 -1.041135 0.514337 0.7647 0.5412 0.2627 +v 0.127997 -1.041135 0.514337 0.7647 0.5412 0.2627 +v -0.812201 -0.611882 0.489972 1.0000 0.4078 0.9882 +v -0.812201 -0.611882 0.489972 0.7647 0.5412 0.2627 +v -0.812201 -0.611882 0.489972 0.7647 0.5412 0.2627 +v -0.812201 -0.611882 0.489972 0.7647 0.5412 0.2627 +v -0.769058 -0.680753 0.499805 1.0000 0.4078 0.9882 +v -0.769058 -0.680753 0.499805 0.7647 0.5412 0.2627 +v -0.769058 -0.680753 0.499805 0.7647 0.5412 0.2627 +v -0.769058 -0.680753 0.499805 0.7647 0.5412 0.2627 +v 0.397272 -0.689505 0.549089 0.7647 0.1059 0.5373 +v 0.397272 -0.689505 0.549089 0.7647 0.5412 0.2627 +v 0.397272 -0.689505 0.549089 0.7647 0.5412 0.2627 +v 0.397272 -0.689505 0.549089 0.7647 0.5412 0.2627 +v 0.655738 -0.739920 0.535785 0.7647 0.5412 0.2627 +v 0.655738 -0.739920 0.535785 0.7647 0.5412 0.2627 +v 0.655738 -0.739920 0.535785 0.7647 0.5412 0.2627 +v 0.655738 -0.739920 0.535785 0.7647 0.5412 0.2627 +v -0.319332 -0.620431 0.544451 0.7647 0.5412 0.2627 +v -0.319332 -0.620431 0.544451 0.7647 0.5412 0.2627 +v -0.319332 -0.620431 0.544451 0.7647 0.5412 0.2627 +v -0.389159 -0.663137 0.545764 0.7647 0.5412 0.2627 +v -0.389159 -0.663137 0.545764 1.0000 0.6432 0.2941 +v -0.389159 -0.663137 0.545764 0.7647 0.5412 0.2627 +v -0.389159 -0.663137 0.545764 0.7647 0.5412 0.2627 +v -0.917141 0.217841 0.506885 0.7647 0.5412 0.2627 +v -0.917141 0.217841 0.506885 0.7647 0.5412 0.2627 +v -0.917141 0.217841 0.506885 0.7647 0.5412 0.2627 +v -0.917141 0.217841 0.506885 0.7647 0.5412 0.2627 +v -0.917141 0.217841 0.506885 0.7647 0.5412 0.2627 +v -0.537471 -0.676284 0.510709 0.7647 0.5412 0.2627 +v -0.537471 -0.676284 0.510709 0.7647 0.5412 0.2627 +v -0.537471 -0.676284 0.510709 0.7647 0.5412 0.2627 +v -0.537471 -0.676284 0.510709 0.7647 0.5412 0.2627 +v -0.537471 -0.676284 0.510709 0.7647 0.5412 0.2627 +s 1 +f 247 254 264 +f 268 273 274 +f 281 294 275 +f 298 306 295 +f 312 321 326 +f 331 335 343 +f 333 350 336 +f 356 367 370 +f 379 389 374 +f 398 412 393 +f 416 426 430 +f 441 283 436 +f 417 447 451 +f 415 463 421 +f 467 470 475 +f 255 332 471 +f 363 248 265 +f 478 257 468 +f 488 499 483 +f 504 299 510 +f 328 519 526 +f 300 290 371 +f 375 533 536 +f 291 358 373 +f 544 555 541 +f 560 537 317 +f 266 261 479 +f 443 564 357 +f 569 578 582 +f 588 597 601 +f 390 611 532 +f 368 344 372 +f 520 625 617 +f 634 645 629 +f 649 659 662 +f 337 301 345 +f 269 669 667 +f 671 364 480 +f 676 682 687 +f 259 315 311 +f 691 492 484 +f 702 708 712 +f 716 719 727 +f 380 453 384 +f 458 437 462 +f 737 749 732 +f 570 756 709 +f 760 610 606 +f 771 779 784 +f 672 472 346 +f 400 788 791 +f 89 348 474 +f 797 683 427 +f 656 801 658 +f 805 810 693 +f 818 822 824 +f 735 830 739 +f 614 836 534 +f 323 513 327 +f 845 849 859 +f 489 872 494 +f 598 881 877 +f 377 250 382 +f 887 508 511 +f 896 713 900 +f 812 394 905 +f 482 365 88 +f 909 485 914 +f 561 258 249 +f 919 260 313 +f 599 926 602 +f 802 933 542 +f 648 932 655 +f 882 941 893 +f 506 942 945 +f 322 874 841 +f 673 42 369 +f 607 953 762 +f 251 361 355 +f 316 949 320 +f 803 556 660 +f 674 476 87 +f 538 837 951 +f 758 714 62 +f 895 573 703 +f 515 959 624 +f 927 773 785 +f 962 966 971 +f 978 980 976 +f 684 432 429 +f 984 993 981 +f 843 866 958 +f 850 846 999 +f 677 433 686 +f 884 772 879 +f 366 362 675 +f 329 923 24 +f 43 481 477 +f 701 574 705 +f 252 565 381 +f 935 548 543 +f 1008 1021 1004 +f 1027 170 1025 +f 422 1031 425 +f 1038 1043 1048 +f 1052 1056 1058 +f 1060 1070 819 +f 967 1073 1078 +f 1081 992 990 +f 748 743 972 +f 1092 1101 1089 +f 1105 987 982 +f 1116 1127 1130 +f 1039 994 1087 +f 1136 1141 1147 +f 1102 1137 1150 +f 1000 1040 1088 +f 1106 1159 1154 +f 165 1026 166 +f 968 1163 1074 +f 1169 1014 1005 +f 1151 1090 1103 +f 1138 1186 1152 +f 806 1191 813 +f 626 1123 1022 +f 867 696 1128 +f 833 464 740 +f 1001 1083 1196 +f 698 1133 1129 +f 1200 750 1204 +f 996 1158 983 +f 751 1208 1171 +f 832 405 1030 +f 1212 1053 1051 +f 1006 1120 1115 +f 1215 1209 973 +f 746 964 974 +f 1224 1164 1228 +f 838 873 950 +f 694 486 807 +f 826 1062 112 +f 1241 814 1192 +f 1245 1153 1187 +f 630 827 823 +f 1252 1084 991 +f 1165 1222 851 +f 1079 1257 1216 +f 820 632 111 +f 1172 1117 1205 +f 1262 1213 1260 +f 59 1217 1173 +f 1225 1075 130 +f 1229 1167 852 +f 1045 1160 1050 +f 439 741 154 +f 646 1236 825 +f 985 1255 989 +f 963 1221 1166 +f 969 1218 131 +f 721 496 835 +f 128 1080 1219 +f 1071 637 631 +f 1206 1132 1201 +f 285 745 438 +f 1121 868 1126 +f 1093 1140 1097 +f 970 132 1168 +f 853 286 276 +f 977 1269 1267 +f 975 1210 754 +f 943 589 946 +f 271 1270 272 +f 1023 622 628 +f 1207 61 1176 +f 51 1258 1174 +f 883 889 776 +f 1076 1226 1175 +f 1227 1179 1170 +f 1259 158 1077 +f 720 613 728 +f 780 890 512 +f 1246 1095 1091 +f 575 707 706 +f 13 90 44 +f 347 305 19 +f 651 579 897 +f 650 902 937 +f 903 546 939 +f 1066 1185 1148 +f 641 1248 1238 +f 1143 639 635 +f 1237 1188 1061 +f 1144 1067 1149 +f 663 585 580 +f 583 547 755 +f 664 554 552 +f 469 263 473 +f 127 60 129 +f 1271 521 1277 +f 406 792 1280 +f 685 798 1286 +f 304 507 307 +f 352 765 761 +f 528 522 1291 +f 907 1202 1131 +f 385 605 388 +f 697 815 906 +f 460 452 563 +f 395 734 1199 +f 1297 454 448 +f 1281 1309 1301 +f 1311 1320 789 +f 860 1289 799 +f 1330 954 1327 +f 678 1335 308 +f 1338 915 1278 +f 1346 729 1342 +f 1350 1194 808 +f 160 670 41 +f 1272 1362 1292 +f 310 1336 296 +f 297 1337 277 +f 1334 688 278 +f 246 1288 689 +f 279 1287 1325 +f 690 1290 133 +f 280 1326 854 +f 1324 861 858 +f 77 302 781 +f 338 1365 786 +f 339 787 782 +f 342 783 37 +f 126 1032 800 +f 862 220 1033 +f 1042 848 863 +f 1003 1198 855 +f 1197 1251 856 +f 134 1254 1231 +f 1253 1112 1232 +f 1283 1302 1113 +f 1110 1104 1284 +f 1285 1107 407 +f 1108 1156 408 +f 157 1157 1034 +f 1155 1044 1035 +f 222 125 1047 +f 509 947 309 +f 227 948 679 +f 75 590 680 +f 681 591 434 +f 592 603 435 +f 431 604 446 +f 73 928 449 +f 47 929 1298 +f 76 1366 930 +f 1367 1299 84 +f 811 1313 401 +f 124 1314 790 +f 1321 1182 793 +f 1323 796 216 +f 1180 1322 1010 +f 1319 1317 1011 +f 1012 1318 1242 +f 1316 1312 1243 +f 1244 1315 123 +f 121 911 809 +f 238 912 1352 +f 913 619 1353 +f 1351 620 1354 +f 618 1019 1356 +f 1009 1357 1017 +f 1355 1013 1193 +f 193 1195 136 +f 487 501 916 +f 1293 1370 529 +f 1274 231 917 +f 33 1276 1294 +f 1279 523 1340 +f 525 621 1341 +f 910 1339 138 +f 242 1363 1371 +f 1372 1364 723 +f 1361 1359 724 +f 722 1360 500 +f 1358 1273 502 +f 53 1275 918 +f 612 766 730 +f 235 768 1343 +f 767 922 1344 +f 527 1345 921 +f 234 530 1348 +f 34 1373 1349 +f 1347 1374 717 +f 50 718 198 +f 763 1331 353 +f 354 1332 340 +f 1333 1328 341 +f 12 1329 1368 +f 224 955 1369 +f 191 956 1300 +f 957 608 1296 +f 1233 101 1303 +f 213 1310 1234 +f 1308 1305 1235 +f 1230 1306 1181 +f 794 1183 1307 +f 1304 1282 196 +f 267 270 7 +f 282 288 293 +f 314 319 324 +f 334 256 349 +f 21 40 39 +f 383 387 392 +f 399 404 411 +f 419 424 428 +f 442 289 287 +f 420 46 450 +f 418 457 465 +f 493 495 498 +f 330 514 518 +f 303 38 292 +f 22 391 535 +f 16 445 360 +f 545 551 558 +f 559 376 540 +f 444 459 20 +f 568 572 577 +f 587 593 596 +f 199 48 615 +f 524 517 627 +f 638 640 644 +f 653 657 63 +f 9 10 668 +f 45 23 318 +f 692 695 490 +f 704 66 711 +f 15 567 455 +f 17 18 440 +f 738 742 753 +f 56 172 175 +f 764 194 616 +f 770 775 778 +f 733 413 829 +f 49 726 200 +f 325 842 516 +f 491 865 871 +f 600 594 880 +f 378 562 253 +f 888 892 505 +f 177 65 715 +f 816 402 396 +f 920 351 262 +f 69 878 925 +f 67 64 55 +f 654 938 934 +f 885 595 940 +f 85 894 944 +f 29 28 875 +f 26 539 952 +f 804 58 557 +f 25 202 840 +f 757 901 57 +f 898 581 68 +f 30 844 961 +f 931 79 71 +f 1 2 979 +f 988 99 997 +f 32 31 870 +f 886 777 774 +f 27 531 924 +f 86 359 566 +f 936 174 550 +f 1015 1018 1020 +f 1028 169 1029 +f 423 831 1036 +f 1037 847 1046 +f 163 1054 1055 +f 1059 1064 1069 +f 1082 1086 998 +f 1096 1098 1100 +f 93 1111 986 +f 1119 142 143 +f 107 1049 995 +f 1135 1099 186 +f 110 116 1139 +f 1002 102 1041 +f 1109 98 1161 +f 1057 167 168 +f 1178 1184 1016 +f 119 187 1190 +f 141 960 1122 +f 869 209 699 +f 210 206 466 +f 92 97 1085 +f 208 207 1134 +f 149 156 752 +f 94 103 1162 +f 834 212 410 +f 1211 1214 164 +f 1007 144 1125 +f 744 1220 965 +f 839 201 876 +f 109 1240 1063 +f 1250 114 113 +f 633 647 828 +f 95 100 105 +f 821 1072 115 +f 1177 147 1118 +f 1263 161 162 +f 96 104 108 +f 153 150 151 +f 118 643 1239 +f 106 1114 1256 +f 725 503 497 +f 117 1065 636 +f 148 145 146 +f 284 1223 747 +f 1124 139 140 +f 1094 1264 1142 +f 857 152 155 +f 3 4 1268 +f 70 74 81 +f 8 5 6 +f 1024 137 623 +f 83 80 72 +f 52 159 135 +f 82 78 891 +f 1247 1265 120 +f 576 571 710 +f 652 179 180 +f 178 899 173 +f 904 759 176 +f 188 183 1189 +f 642 1266 1249 +f 1146 190 189 +f 182 181 184 +f 1145 185 1068 +f 665 553 584 +f 586 171 549 +f 666 661 54 +f 409 403 795 +f 36 35 769 +f 908 211 1203 +f 386 1295 609 +f 700 122 817 +f 461 203 204 +f 397 414 736 +f 14 205 456 +f 197 215 214 +f 218 219 217 +f 864 223 221 +f 226 192 225 +f 229 230 228 +f 233 195 232 +f 236 237 731 +f 240 241 239 +f 1261 11 91 +f 244 245 243 From ef507153d7793f64273066f8e00777f29a064581 Mon Sep 17 00:00:00 2001 From: Dylan Whichard Date: Sat, 21 Oct 2023 11:53:42 -0700 Subject: [PATCH 06/11] Add translation and scaling parameters to drawModel() --- main/display/model.c | 31 ++++++--------- main/display/model.h | 4 +- main/modes/accelTest/accelTest.c | 67 +++++++++++++++++++++++++++----- 3 files changed, 71 insertions(+), 31 deletions(-) diff --git a/main/display/model.c b/main/display/model.c index 0b017b92b..68b49c098 100644 --- a/main/display/model.c +++ b/main/display/model.c @@ -87,46 +87,37 @@ void deinitRenderer(void) } } -void drawModel(const model_t* model, float orient[4]) +void drawModel(const model_t* model, float orient[4], float scale, float translate[3], uint16_t x, uint16_t y, uint16_t w, uint16_t h) { - // TODO: add translate parameter - // TODO: add x, y, w, and h as parameters for the drawing area - // TODO: not sure if lines work - - uint16_t w = TFT_WIDTH; - uint16_t h = TFT_HEIGHT; - float plusy[3] = { 0, 1, 0 }; // Produce a model matrix from a quaternion. - float plusx_out[3] = { 0.9, 0, 0 }; - float plusy_out[3] = { 0, 0.9, 0 }; - float plusz_out[3] = { 0, 0, 0.9 }; + float plusx_out[3] = { 0.9 * scale, 0, 0 }; + float plusy_out[3] = { 0, 0.9 * scale, 0 }; + float plusz_out[3] = { 0, 0, 0.9 * scale }; mathRotateVectorByQuaternion( plusy, orient, plusy ); mathRotateVectorByQuaternion( plusy_out, orient, plusy_out ); mathRotateVectorByQuaternion( plusx_out, orient, plusx_out ); mathRotateVectorByQuaternion( plusz_out, orient, plusz_out ); - //uint32_t cycStart = getCycleCount(); - int i, vertices = 0; for( i = 0; i < model->vertCount; i++ ) { // Performing the transform this way is about 700us. - float bx = 1.0 * model->verts[i][0]; - float by = 1.0 * model->verts[i][1]; - float bz = 1.0 * model->verts[i][2]; + float bx = 1.0 * model->verts[i][0] + translate[0]; + float by = 1.0 * model->verts[i][1] + translate[1]; + float bz = 1.0 * model->verts[i][2] + translate[2]; - float bunnyvert[3] = { + float xlvert[3] = { bx * plusx_out[0] + by * plusx_out[1] + bz * plusx_out[2], bx * plusy_out[0] + by * plusy_out[1] + bz * plusy_out[2], bx * plusz_out[0] + by * plusz_out[1] + bz * plusz_out[2] }; - verts_out[vertices*3+0] = bunnyvert[0] + w/2; + verts_out[vertices*3+0] = x + xlvert[0] + w/2; // Convert from right-handed to left-handed coordinate frame. - verts_out[vertices*3+1] =-bunnyvert[1] + h/2; - verts_out[vertices*3+2] = bunnyvert[2]; + verts_out[vertices*3+1] = y - xlvert[1] + h/2; + verts_out[vertices*3+2] = xlvert[2]; vertices++; } diff --git a/main/display/model.h b/main/display/model.h index f7b712698..4250d63d1 100644 --- a/main/display/model.h +++ b/main/display/model.h @@ -79,11 +79,13 @@ void deinitRenderer(void); * @param model The 3D model to draw * @param offset The location within the world * @param orient A quaternion representing the orientation of the model + * @param scale The scale factor to apply to the model + * @param translate A vector representing the x, y, and z translation of the model * @param x The X coordinate of the left side of the window to draw the model within * @param y The Y coordinate of the top side of the window to draw the model within * @param w The width of the window to draw the model within * @param h The height of the window to draw the model within */ -void drawModel(const model_t* model, float orient[4]); +void drawModel(const model_t* model, float orient[4], float scale, float translate[3], uint16_t x, uint16_t y, uint16_t w, uint16_t h); #endif diff --git a/main/modes/accelTest/accelTest.c b/main/modes/accelTest/accelTest.c index 8ccb335aa..044200eae 100644 --- a/main/modes/accelTest/accelTest.c +++ b/main/modes/accelTest/accelTest.c @@ -76,7 +76,9 @@ typedef struct model_t bunny; ///< The bunny 3D model model_t donut; ///< The donut 3D model - bool drawDonut; + bool translateY; + float scale; + float translate[3]; uint16_t btnState; ///< The button state @@ -167,6 +169,11 @@ static void accelTestEnterMode(void) ESP_LOGI("Model", "loadModel(bunny.mdl) returned %s", loadModel("bunny.mdl", &accelTest->bunny, true) ? "true" : "false"); loadModel("donut.mdl", &accelTest->donut, true); + accelTest->scale = 1.0; + accelTest->translate[0] = 0.0; + accelTest->translate[1] = 0.0; + accelTest->translate[2] = 0.0; + // Ensure there's sufficient space to draw either model initRendererCustom(MAX(accelTest->bunny.vertCount, accelTest->donut.vertCount), MAX(accelTest->bunny.triCount, accelTest->donut.triCount)); @@ -226,8 +233,47 @@ static void accelTestMainLoop(int64_t elapsedUs) if (evt.down && (PB_B == evt.button)) { - accelTest->drawDonut = !accelTest->drawDonut; + accelTest->translateY = !accelTest->translateY; + } + + if (evt.down && (PB_UP == evt.button)) + { + accelTest->scale += .1; + } + + if (evt.down && (PB_DOWN == evt.button)) + { + if (accelTest->scale > .15) + { + accelTest->scale -= .1; + } + } + + if (evt.down && (PB_LEFT == evt.button)) + { + if (accelTest->translateY) + { + accelTest->translate[1] -= 5.0; + } + else + { + accelTest->translate[0] -= 5.0; + } } + + if (evt.down && (PB_RIGHT == evt.button)) + { + if (accelTest->translateY) + { + accelTest->translate[1] += 5.0; + } + else + { + accelTest->translate[0] += 5.0; + } + } + + ESP_LOGI("Accel", "Scale: %f", accelTest->scale); } // Do update each loop @@ -283,17 +329,12 @@ static void accelTestHandleInput(void) */ static void accelDrawBunny(void) { + // Get the orientation from the accelerometer float orient[4]; memcpy(orient, LSM6DSL.fqQuat, sizeof(orient)); - if (accelTest->drawDonut) - { - drawModel(&accelTest->donut, orient); - } - else - { - drawModel(&accelTest->bunny, orient); - } + drawModel(&accelTest->donut, orient, accelTest->scale / 2, accelTest->translate, 0, TFT_HEIGHT / 2, TFT_WIDTH / 2, TFT_HEIGHT / 2); + drawModel(&accelTest->bunny, orient, accelTest->scale / 2, accelTest->translate, TFT_WIDTH / 2, TFT_HEIGHT / 2, TFT_WIDTH / 2, TFT_HEIGHT / 2); } /** @@ -317,6 +358,12 @@ static void accelTestReset(void) accelTest->max.x = 1; accelTest->max.y = 1; accelTest->max.z = 1; + + accelTest->scale = 1.0; + + accelTest->translate[0] = 0.0; + accelTest->translate[1] = 0.0; + accelTest->translate[2] = 0.0; } /** From 0f35c20bd5b0658aeae76dc422555c0df1a4eef0 Mon Sep 17 00:00:00 2001 From: Dylan Whichard Date: Sat, 21 Oct 2023 11:54:11 -0700 Subject: [PATCH 07/11] Patch a renderer div-by-zero crash --- main/display/model.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/main/display/model.c b/main/display/model.c index 68b49c098..2ae98d1a5 100644 --- a/main/display/model.c +++ b/main/display/model.c @@ -155,6 +155,13 @@ void drawModel(const model_t* model, float orient[4], float scale, float transla //float fcrp[3] = { icrp[0], icrp[1], icrp[2] }; int crpscalar = julery_isqrt( icrp[0] * icrp[0] + icrp[1] * icrp[1] + icrp[2] * icrp[2] ); + + // TODO: This is probably not the root cause of the issue + if (crpscalar == 0) + { + crpscalar = 1; + } + icrp[0] = ( 1024 * icrp[0] ) / crpscalar; icrp[1] = ( 1024 * icrp[1] ) / crpscalar; icrp[2] = ( 1024 * icrp[2] ) / crpscalar; From 02df4b0581fcdd3a5cd2e68a9d3ea0e10a632d22 Mon Sep 17 00:00:00 2001 From: Dylan Whichard Date: Sat, 21 Oct 2023 17:03:14 -0700 Subject: [PATCH 08/11] Fix undefined functions in emulator hdw-imu --- components/hdw-imu/hdw-imu.c | 9 -- emulator/src/components/hdw-imu/hdw-imu.c | 152 ++++++++++++++++++++-- 2 files changed, 142 insertions(+), 19 deletions(-) diff --git a/components/hdw-imu/hdw-imu.c b/components/hdw-imu/hdw-imu.c index 593a15075..92462bb08 100644 --- a/components/hdw-imu/hdw-imu.c +++ b/components/hdw-imu/hdw-imu.c @@ -97,15 +97,6 @@ LSM6DSLData LSM6DSL; // Utility Prototypes //============================================================================== -float rsqrtf(float x); -float mathsqrtf(float x); -void mathEulerToQuat(float* q, const float* euler); -void mathQuatApply(float* qout, const float* q1, const float* q2); -void mathQuatNormalize(float* qout, const float* qin); -void mathCrossProduct(float* p, const float* a, const float* b); -void mathRotateVectorByInverseOfQuaternion(float* pout, const float* q, const float* p); -void mathRotateVectorByQuaternion(float* pout, const float* q, const float* p); - static inline uint32_t getCycleCount(); esp_err_t GeneralSet(int dev, int reg, int val); diff --git a/emulator/src/components/hdw-imu/hdw-imu.c b/emulator/src/components/hdw-imu/hdw-imu.c index b63d1d2cf..25f16e027 100644 --- a/emulator/src/components/hdw-imu/hdw-imu.c +++ b/emulator/src/components/hdw-imu/hdw-imu.c @@ -8,6 +8,7 @@ #include "esp_random.h" #include "emu_args.h" #include "macros.h" +#include "math.h" #define ONE_G 256 @@ -164,6 +165,130 @@ esp_err_t accelIntegrate() { // Do nothing (is stub function) return ESP_OK; +}//============================================================================== +// Utility Functions +//============================================================================== + +/** + * @brief Perform a fast, approximate reciprocal square root + * + * @param x The number to take a recriprocal square root of. + * @return approximately 1/sqrt(x) + */ +float rsqrtf(float x) +{ + typedef union + { + int32_t i; + float f; + } fiunion; + const float xhalf = 0.5f * x; + fiunion i = {.f = x}; + i.i = 0x5f375a86 - (i.i >> 1); + x = i.f; + x = x * (1.5f - xhalf * x * x); + x = x * (1.5f - xhalf * x * x); + return x; +} + +/** + * @brief Perform a fast, approximate square root + * + * @param x The number to take a square root of. + * @return approximately sqrt(x) (but is much faster) + */ +float mathsqrtf(float x) +{ + // Trick to do approximate, fast square roots. (Though it is surprisingly fast) + int sign = x < 0; + if (sign) + x = -x; + if (x < 0.0000001) + return 0.0001; + float o = x; + o = (o + x / o) / 2; + o = (o + x / o) / 2; + o = (o + x / o) / 2; + o = (o + x / o) / 2; + if (sign) + return -o; + else + return o; +} + +/** + * @brief convert euler angles (in radians) to a quaternion. + * + * @param q Pointer to the wxyz quat (float[4]) to be written. + * @param euler Pointer to a float[3] of euler angles. + */ +void mathEulerToQuat(float* q, const float* euler) +{ + float pitch = euler[0]; + float yaw = euler[1]; + float roll = euler[2]; + float cr = cosf(pitch * 0.5); + float sr = sinf(pitch * 0.5); // Pitch: About X + float cp = cosf(yaw * 0.5); + float sp = sinf(yaw * 0.5); // Yaw: About Y + float cy = cosf(roll * 0.5); + float sy = sinf(roll * 0.5); // Roll: About Z + q[0] = cr * cp * cy + sr * sp * sy; + q[1] = sr * cp * cy - cr * sp * sy; + q[2] = cr * sp * cy + sr * cp * sy; + q[3] = cr * cp * sy - sr * sp * cy; +} + +/** + * @brief Rotate one quaternion by another (and do not normalize) + * + * @param qout Pointer to the wxyz quat (float[4]) to be written. + * @param q1 First quaternion to be rotated. + * @param q2 Quaternion to rotate q1 by. + */ +void mathQuatApply(float* qout, const float* q1, const float* q2) +{ + // NOTE: Does not normalize - you will need to normalize eventually. + float tmpw, tmpx, tmpy; + tmpw = (q1[0] * q2[0]) - (q1[1] * q2[1]) - (q1[2] * q2[2]) - (q1[3] * q2[3]); + tmpx = (q1[0] * q2[1]) + (q1[1] * q2[0]) + (q1[2] * q2[3]) - (q1[3] * q2[2]); + tmpy = (q1[0] * q2[2]) - (q1[1] * q2[3]) + (q1[2] * q2[0]) + (q1[3] * q2[1]); + qout[3] = (q1[0] * q2[3]) + (q1[1] * q2[2]) - (q1[2] * q2[1]) + (q1[3] * q2[0]); + qout[2] = tmpy; + qout[1] = tmpx; + qout[0] = tmpw; +} + +/** + * @brief Normalize a quaternion + * + * @param qout Pointer to the wxyz quat (float[4]) to be written. + * @param qin Pointer to the quaterion to normalize. + */ +void mathQuatNormalize(float* qout, const float* qin) +{ + float qmag = qin[0] * qin[0] + qin[1] * qin[1] + qin[2] * qin[2] + qin[3] * qin[3]; + qmag = rsqrtf(qmag); + qout[0] = qin[0] * qmag; + qout[1] = qin[1] * qmag; + qout[2] = qin[2] * qmag; + qout[3] = qin[3] * qmag; +} + +/** + * @brief Perform a 3D cross product + * + * @param p Pointer to the float[3] output of the cross product (p = a x b) + * @param a Pointer to the float[3] of the cross product a vector. + * @param b Pointer to the float[3] of the cross product b vector. + */ +void mathCrossProduct(float* p, const float* a, const float* b) +{ + float tx = a[1] * b[2] - a[2] * b[1]; + float ty = a[2] * b[0] - a[0] * b[2]; + p[2] = a[0] * b[1] - a[1] * b[0]; + p[1] = ty; + p[0] = tx; } /** @@ -189,19 +314,26 @@ void mathRotateVectorByQuaternion(float* pout, const float* q, const float* p) } /** - * @brief Perform a 3D cross product + * @brief Rotate a 3D vector by the inverse of a quaternion * - * @param p Pointer to the float[3] output of the cross product (p = a x b) - * @param a Pointer to the float[3] of the cross product a vector. - * @param a Pointer to the float[3] of the cross product b vector. + * @param pout Pointer to the float[3] output of the antirotation. + * @param q Pointer to the wxyz quaternion (float[4]) opposite of the rotation. + * @param p Pointer to the float[3] of the vector to antirotates. */ -void mathCrossProduct(float* p, const float* a, const float* b) +void mathRotateVectorByInverseOfQuaternion(float* pout, const float* q, const float* p) { - float tx = a[1] * b[2] - a[2] * b[1]; - float ty = a[2] * b[0] - a[0] * b[2]; - p[2] = a[0] * b[1] - a[1] * b[0]; - p[1] = ty; - p[0] = tx; + // General note: Performing a transform this way can be about 20-30% slower than a well formed 3x3 matrix. + // return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v); + float iqo[3]; + mathCrossProduct(iqo, p, q + 1 /*.xyz*/); + iqo[0] += q[0] * p[0]; + iqo[1] += q[0] * p[1]; + iqo[2] += q[0] * p[2]; + float ret[3]; + mathCrossProduct(ret, iqo, q + 1 /*.xyz*/); + pout[0] = ret[0] * 2.0 + p[0]; + pout[1] = ret[1] * 2.0 + p[1]; + pout[2] = ret[2] * 2.0 + p[2]; } // stub From 9d17714476424e4f8520ec0c51bcbe748bd74e7e Mon Sep 17 00:00:00 2001 From: Dylan Whichard Date: Sat, 21 Oct 2023 17:04:16 -0700 Subject: [PATCH 09/11] Add missing include guard --- main/asset_loaders/spiffs_model.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/main/asset_loaders/spiffs_model.h b/main/asset_loaders/spiffs_model.h index f2d963eb1..b46eaad8c 100644 --- a/main/asset_loaders/spiffs_model.h +++ b/main/asset_loaders/spiffs_model.h @@ -1,6 +1,11 @@ +#ifndef _SPIFFS_MODEL_H_ +#define _SPIFFS_MODEL_H_ + #include "model.h" #include bool loadModel(const char* name, model_t* model, bool useSpiRam); -void freeModel(model_t* model); \ No newline at end of file +void freeModel(model_t* model); + +#endif From 183eda61d58ec0f0bc7cf245cde778c4bfd8c302 Mon Sep 17 00:00:00 2001 From: Dylan Whichard Date: Sat, 21 Oct 2023 17:05:27 -0700 Subject: [PATCH 10/11] Add scenes that sorta work --- main/display/model.c | 342 ++++++++++++++++++++++++++++--------------- main/display/model.h | 133 ++++++++++++++++- 2 files changed, 351 insertions(+), 124 deletions(-) diff --git a/main/display/model.c b/main/display/model.c index 2ae98d1a5..00a637d0a 100644 --- a/main/display/model.c +++ b/main/display/model.c @@ -12,17 +12,23 @@ #include "shapes.h" #include "palette.h" +// If defined, the stack will be used to allocate vert/tri buffers, otherwise heap is used +//#define MODEL_USE_STACK + // do a funky typedef so we can still define trimap as a 2D array typedef uint16_t trimap_t[3]; // Variables -static uint16_t* verts_out = NULL; +#ifndef MODEL_USE_STACK +static int16_t* verts_out = NULL; static trimap_t* trimap = NULL; +#endif // Static Function Prototypes static void intcross(int* p, const int* a, const int* b); static int zcompare(const int16_t *a, const int16_t* b); static unsigned julery_isqrt(unsigned long val); +static void countScene(const scene_t* scene, uint16_t* verts, uint16_t* faces); // Function Definitions static void intcross(int* p, const int* a, const int* b) @@ -36,7 +42,7 @@ static void intcross(int* p, const int* a, const int* b) static int zcompare(const int16_t *a, const int16_t* b) { - return a[0] - b[0]; + return (a[0] - b[0]) ? (a[0] - b[0]) : ((a[2] >> 8) - (b[2] >> 8)); } static unsigned julery_isqrt(unsigned long val) { @@ -50,6 +56,45 @@ static unsigned julery_isqrt(unsigned long val) { return g; } +/** + * @brief Count and return the total number of vertices and faces in a scene + * + * @param scene The scene to count + * @param[out] verts A pointer to a uint16_t to be set to the total number of vertices + * @param[out] faces A pointer to a uint16_t to be set to the total number of faces + */ +static void countScene(const scene_t* scene, uint16_t* verts, uint16_t* faces) +{ + uint16_t totalVerts = 0; + uint16_t totalTris = 0; + + for (uint8_t i = 0; i < scene->modelCount; i++) + { + const modelPos_t* modelPos = &scene->models[i]; + if (NULL != modelPos->model) + { + uint16_t prevVerts = totalVerts; + uint16_t prevTris = totalTris; + totalVerts += modelPos->model->vertCount; + totalTris += modelPos->model->triCount; + + if (totalVerts < prevVerts || totalTris < prevTris) + { + // Detect integer rollover and abort + ESP_LOGE("Model", + "Too many verts/faces in scene: %" PRIu16 " + %" PRIu16 " verts" + " or %" PRIu16 " + %" PRIu16 " faces rolled over", + prevVerts, modelPos->model->vertCount, + prevTris, modelPos->model->triCount); + return; + } + } + } + + *verts = totalVerts; + *faces = totalTris; +} + void initRenderer(const model_t* model) { initRendererCustom(model->vertCount, model->triCount); @@ -57,23 +102,36 @@ void initRenderer(const model_t* model) void initRendererCustom(uint16_t maxVerts, uint16_t maxFaces) { +#ifdef MODEL_USE_STACK + ESP_LOGI("Model", "Using stack for verts and faces! Woo"); +#else // Free any existing buffers deinitRenderer(); ESP_LOGI("Model", "Allocating %" PRIu64 " bytes for verts and faces", (uint64_t)((maxVerts + maxFaces) * 3 * sizeof(uint16_t))); // Allocate the new buffers - verts_out = malloc(maxVerts * 3 * sizeof(uint16_t)); + verts_out = malloc(maxVerts * 3 * sizeof(int16_t)); trimap = malloc(maxFaces * 3 * sizeof(uint16_t)); if (verts_out == NULL || trimap == NULL) { ESP_LOGI("Model", "Renderer could not allocate the buffers :("); } +#endif +} + +void initRendererScene(const scene_t* scene) +{ + uint16_t totalVerts = 0; + uint16_t totalTris = 0; + countScene(scene, &totalVerts, &totalTris); + initRendererCustom(totalVerts, totalTris); } void deinitRenderer(void) { +#ifndef MODEL_USE_STACK if (NULL != verts_out) { free(verts_out); @@ -85,137 +143,181 @@ void deinitRenderer(void) free(trimap); trimap = NULL; } +#endif } void drawModel(const model_t* model, float orient[4], float scale, float translate[3], uint16_t x, uint16_t y, uint16_t w, uint16_t h) { - float plusy[3] = { 0, 1, 0 }; - - // Produce a model matrix from a quaternion. - float plusx_out[3] = { 0.9 * scale, 0, 0 }; - float plusy_out[3] = { 0, 0.9 * scale, 0 }; - float plusz_out[3] = { 0, 0, 0.9 * scale }; - mathRotateVectorByQuaternion( plusy, orient, plusy ); - mathRotateVectorByQuaternion( plusy_out, orient, plusy_out ); - mathRotateVectorByQuaternion( plusx_out, orient, plusx_out ); - mathRotateVectorByQuaternion( plusz_out, orient, plusz_out ); - - int i, vertices = 0; - for( i = 0; i < model->vertCount; i++ ) - { - // Performing the transform this way is about 700us. - float bx = 1.0 * model->verts[i][0] + translate[0]; - float by = 1.0 * model->verts[i][1] + translate[1]; - float bz = 1.0 * model->verts[i][2] + translate[2]; - - float xlvert[3] = { - bx * plusx_out[0] + by * plusx_out[1] + bz * plusx_out[2], - bx * plusy_out[0] + by * plusy_out[1] + bz * plusy_out[2], - bx * plusz_out[0] + by * plusz_out[1] + bz * plusz_out[2] - }; - - verts_out[vertices*3+0] = x + xlvert[0] + w/2; - // Convert from right-handed to left-handed coordinate frame. - verts_out[vertices*3+1] = y - xlvert[1] + h/2; - verts_out[vertices*3+2] = xlvert[2]; - vertices++; - } - - if (model->triCount > 0) + scene_t scene; + scene.models[0].model = model; + scene.modelCount = 1; + memcpy(scene.models[0].orient, orient, sizeof(float) * 4); + scene.models[0].scale = scale; + memcpy(scene.models[0].translate, translate, sizeof(float) * 3); + + drawScene(&scene, x, y, w, h); +} + +void drawScene(const scene_t* scene, uint16_t x, uint16_t y, uint16_t w, uint16_t h) +{ +#ifdef MODEL_USE_STACK + uint16_t maxVerts, maxTris; + countScene(scene, &maxVerts, &maxTris); + int16_t verts_out[maxVerts * 3]; + trimap_t trimap[maxTris]; +#endif + + int vertices = 0; + int totalTrisThisFrame = 0; + int i; + + for (uint8_t modelNum = 0; modelNum < scene->modelCount; modelNum++) { - // Draw model with shaded triangles - int totalTrisThisFrame = 0; + const modelPos_t* modelPos = &scene->models[modelNum]; + const model_t* model = modelPos->model; + ESP_LOGI("Model", "modelNum = %" PRIu8 " and translate is %.2f, %.2f, %.2f", modelNum, modelPos->translate[0], modelPos->translate[1], modelPos->translate[2]); - for( i = 0; i < model->triCount; i++) + if (NULL == model) { - int tv1 = model->tris[i].verts[0] * 3; - int tv2 = model->tris[i].verts[1] * 3; - int tv3 = model->tris[i].verts[2] * 3; - int col = model->tris[i].color; - - int diff1[3] = { - verts_out[tv3+0] - verts_out[tv1+0], - verts_out[tv3+1] - verts_out[tv1+1], - verts_out[tv3+2] - verts_out[tv1+2] }; - int diff2[3] = { - verts_out[tv2+0] - verts_out[tv1+0], - verts_out[tv2+1] - verts_out[tv1+1], - verts_out[tv2+2] - verts_out[tv1+2] }; - - // If we didn't need the normal, could do cross faster. int crossproduct = diff1[1] * diff2[0] - diff1[0] * diff2[1]; - - int icrp[3]; - intcross( icrp, diff1, diff2 ); - if( icrp[2] < 0 ) continue; - int z = verts_out[tv1+2] + verts_out[tv2+2] + verts_out[tv3+2]; - - int b = col % 6; - int g = ( col / 6 ) % 6; - int r = ( col / 36 ) % 6; - - //float fcrp[3] = { icrp[0], icrp[1], icrp[2] }; - int crpscalar = julery_isqrt( icrp[0] * icrp[0] + icrp[1] * icrp[1] + icrp[2] * icrp[2] ); - - // TODO: This is probably not the root cause of the issue - if (crpscalar == 0) - { - crpscalar = 1; - } - - icrp[0] = ( 1024 * icrp[0] ) / crpscalar; - icrp[1] = ( 1024 * icrp[1] ) / crpscalar; - icrp[2] = ( 1024 * icrp[2] ) / crpscalar; - - int isum = icrp[0] - icrp[1] + icrp[2]; + // no model no render! + continue; + } - r = ( r * ( ( isum ) + 1200 ) * 100 ) >> 18; - g = ( g * ( ( isum ) + 1200 ) * 100 ) >> 18; - b = ( b * ( ( isum ) + 1200 ) * 100 ) >> 18; + float plusy[3] = { 0, 1, 0 }; - if( r < 0 ) r = 0; - if( g < 0 ) g = 0; - if( b < 0 ) b = 0; - if( r > 5 ) r = 5; - if( g > 5 ) g = 5; - if( b > 5 ) b = 5; + // Produce a model matrix from a quaternion. + float plusx_out[3] = { 0.9 * modelPos->scale, 0, 0 }; + float plusy_out[3] = { 0, 0.9 * modelPos->scale, 0 }; + float plusz_out[3] = { 0, 0, 0.9 * modelPos->scale }; + mathRotateVectorByQuaternion( plusy, modelPos->orient, plusy ); + mathRotateVectorByQuaternion( plusy_out, modelPos->orient, plusy_out ); + mathRotateVectorByQuaternion( plusx_out, modelPos->orient, plusx_out ); + mathRotateVectorByQuaternion( plusz_out, modelPos->orient, plusz_out ); - trimap[totalTrisThisFrame][0] = z; - trimap[totalTrisThisFrame][1] = i; - trimap[totalTrisThisFrame][2] = r * 36 + g * 6 + b; - totalTrisThisFrame++; + for( i = 0; i < model->vertCount; i++ ) + { + // Performing the transform this way is about 700us. + float bx = 1.0 * model->verts[i][0] + modelPos->translate[0]; + float by = 1.0 * model->verts[i][1] + modelPos->translate[1]; + float bz = 1.0 * model->verts[i][2] + modelPos->translate[2]; + + float xlvert[3] = { + bx * plusx_out[0] + by * plusx_out[1] + bz * plusx_out[2], + bx * plusy_out[0] + by * plusy_out[1] + bz * plusy_out[2], + bx * plusz_out[0] + by * plusz_out[1] + bz * plusz_out[2] + }; + + verts_out[vertices*3+0] = x + xlvert[0] + w/2; + // Convert from right-handed to left-handed coordinate frame. + verts_out[vertices*3+1] = y - xlvert[1] + h/2; + verts_out[vertices*3+2] = xlvert[2]; + vertices++; } - qsort(trimap, totalTrisThisFrame, sizeof( trimap[0] ), (void*)zcompare ); - - for( i = 0; i < totalTrisThisFrame; i++) + if (model->triCount > 0) { - int j = trimap[i][1]; - int tv1 = model->tris[j].verts[0]*3; - int tv2 = model->tris[j].verts[1]*3; - int tv3 = model->tris[j].verts[2]*3; - int tcol = trimap[i][2]; - - drawTriangleOutlined( - verts_out[tv1+0], verts_out[tv1+1], - verts_out[tv2+0], verts_out[tv2+1], - verts_out[tv3+0], verts_out[tv3+1], - tcol, tcol ); + // Draw model with shaded triangles + for( i = 0; i < model->triCount; i++) + { + int tv1 = model->tris[i].verts[0] * 3; + int tv2 = model->tris[i].verts[1] * 3; + int tv3 = model->tris[i].verts[2] * 3; + int col = model->tris[i].color; + + int diff1[3] = { + verts_out[tv3+0] - verts_out[tv1+0], + verts_out[tv3+1] - verts_out[tv1+1], + verts_out[tv3+2] - verts_out[tv1+2] }; + int diff2[3] = { + verts_out[tv2+0] - verts_out[tv1+0], + verts_out[tv2+1] - verts_out[tv1+1], + verts_out[tv2+2] - verts_out[tv1+2] }; + + // If we didn't need the normal, could do cross faster. int crossproduct = diff1[1] * diff2[0] - diff1[0] * diff2[1]; + + int icrp[3]; + intcross( icrp, diff1, diff2 ); + if( icrp[2] < 0 ) continue; + int z = verts_out[tv1+2] + verts_out[tv2+2] + verts_out[tv3+2]; + + int b = col % 6; + int g = ( col / 6 ) % 6; + int r = ( col / 36 ) % 6; + + //float fcrp[3] = { icrp[0], icrp[1], icrp[2] }; + int crpscalar = julery_isqrt( icrp[0] * icrp[0] + icrp[1] * icrp[1] + icrp[2] * icrp[2] ); + + // TODO: This is probably not the root cause of the issue + if (crpscalar == 0) + { + crpscalar = 1; + } + + icrp[0] = ( 1024 * icrp[0] ) / crpscalar; + icrp[1] = ( 1024 * icrp[1] ) / crpscalar; + icrp[2] = ( 1024 * icrp[2] ) / crpscalar; + + int isum = icrp[0] - icrp[1] + icrp[2]; + + r = ( r * ( ( isum ) + 1200 ) * 100 ) >> 18; + g = ( g * ( ( isum ) + 1200 ) * 100 ) >> 18; + b = ( b * ( ( isum ) + 1200 ) * 100 ) >> 18; + + if( r < 0 ) r = 0; + if( g < 0 ) g = 0; + if( b < 0 ) b = 0; + if( r > 5 ) r = 5; + if( g > 5 ) g = 5; + if( b > 5 ) b = 5; + + trimap[totalTrisThisFrame][0] = z; + trimap[totalTrisThisFrame][1] = i; + // Pack the model number into the unused top byte of trimap[][2] for now + trimap[totalTrisThisFrame][2] = (modelNum << 8) | ((r * 36 + g * 6 + b) & 0xFF); + totalTrisThisFrame++; + } } - } - else if (model->lineCount > 0) - { - // Draw wireframe with lines - for (i = 0; i < model->lineCount; i++) + else if (model->lineCount > 0) { - uint16_t v1 = model->lines[i][0] * 3; - uint16_t v2 = model->lines[i][1] * 3; - - float col = verts_out[v1 + 2] / 2000 + 8; - if (col > 5) - col = 5; - else if (col < 0) - continue; - drawLineFast(verts_out[v1], verts_out[v1 + 1], verts_out[v2], verts_out[v2 + 1], col); + // Draw wireframe with lines + for (i = 0; i < model->lineCount; i++) + { + uint16_t v1 = model->lines[i][0] * 3; + uint16_t v2 = model->lines[i][1] * 3; + + float col = verts_out[v1 + 2] / 2000 + 8; + if (col > 5) + col = 5; + else if (col < 0) + continue; + drawLineFast(verts_out[v1], verts_out[v1 + 1], verts_out[v2], verts_out[v2 + 1], col); + } } } -} + + // Sort all faces by Z-index, then by model number + qsort(trimap, totalTrisThisFrame, sizeof( trimap[0] ), (void*)zcompare ); + + for( i = 0; i < totalTrisThisFrame; i++) + { + // Get the face index + int j = trimap[i][1]; + + // Extract the model number from the top byte of trimap[][2] + const model_t* model = scene->models[(trimap[i][2] >> 8) & 0xFF].model; + //ESP_LOGI("Model", "modelNum is %" PRIu16, (trimap[i][2] >> 8) & 0xFF); + + int tv1 = model->tris[j].verts[0]*3; + int tv2 = model->tris[j].verts[1]*3; + int tv3 = model->tris[j].verts[2]*3; + + // Use only the low byte of trimap[][2] for color + int tcol = trimap[i][2] & 0xFF; + + drawTriangleOutlined( + verts_out[tv1+0], verts_out[tv1+1], + verts_out[tv2+0], verts_out[tv2+1], + verts_out[tv3+0], verts_out[tv3+1], + tcol, tcol ); + } +} \ No newline at end of file diff --git a/main/display/model.h b/main/display/model.h index 4250d63d1..113dda31b 100644 --- a/main/display/model.h +++ b/main/display/model.h @@ -1,3 +1,72 @@ +/*! \file model.h + * + * \section model_design Design Philosophy + * + * This module provides a self-contained utility for rendering 3D models. Any \c .obj file placed + * in \c /assets/ will automatically be converted into a binary \c .mdl file in SPIFFS. Models are + * loaded from SPIFFS with loadModel() and unloaded with freeModel(). Once loaded, the model can + * either be passed directly into drawModel(), or composed within a scene_t and passed to drawScene(). + * + * Before rendering, either initRenderer(), initRendererCustom(), or initRendererScene() must be + * called at least once. If necessary, the renderer may be reconfigured by making another call to + * \c initRenderer*(). Once the renderer is no longer needed, it must be deinitialized by calling + * deinitRenderer(). + * + * \section model_example Example + * + * \code{.c} + * #include + * + * // For loadModel() and freeModel() + * #include "spiffs_model.h" + * // for model_t and all rendering functions + * #include "model.h" + * // For TFT_WIDTH, TFT_HEIGHT + * #include "hdw-tft.h" + * // For getting the swadge's orientation (LSM6DSL.fqQuat) + * #include "hdw-imu.h" + * + * //////////////////// + * // Initialization // + * //////////////////// + * + * // Load the model data + * model_t model; + * if (!loadModel("donut.mdl", &model, false)) + * { + * // Error, model not loaded! + * return; + * } + * + * // Initialize the renderer + * initRenderer(&model); + * + * //////////////////// + * // Frame Callback // + * //////////////////// + * + * // Get the swadge's orientation from the accelerometer to rotate the model + * float orient[4]; + * memcpy(orient, LSM6DSL.fqQuat, sizeof(orient)); + * + * float scale = 1.0; + * float translate[3] = {0}; + * + * // Draw the model across the whole screen + * drawModel(&model, orient, scale, translate, 0, 0, TFT_WIDTH, TFT_HEIGHT); + * + * //////////////////// + * // Deinitializing // + * //////////////////// + * + * // Deinitialize the renderer + * deinitRenderer(); + * + * // Free the model data + * freeModel(&model); + * \endcode + * + */ #ifndef _MODEL_H_ #define _MODEL_H_ @@ -6,18 +75,25 @@ #include "palette.h" +//============================================================================== +// Types +//============================================================================== + +/// @brief Type representing a vertex as an array of 3 int8_t for x, y, and z typedef int8_t modelVert_t[3]; + +/// @brief Type representing a line as an array of 2 vertex indices typedef uint16_t modelLine_t[2]; /** - * @brief Structure representing a triangle and its color + * @brief Structure representing a triangular face and its color */ typedef struct { /// @brief Index of each of the triangle's vertices uint16_t verts[3]; - // Triangle color + /// @brief The face's color paletteColor_t color; } modelTri_t; @@ -45,6 +121,24 @@ typedef struct modelLine_t* lines; } model_t; +typedef struct +{ + const model_t* model; + float orient[4]; + float scale; + float translate[3]; +} modelPos_t; + +typedef struct +{ + uint8_t modelCount; + modelPos_t models[16]; +} scene_t; + +//============================================================================== +// Function Prototypes +//============================================================================== + /** * @brief Initializes the renderer, allocating temporary buffers needed to draw efficiently. * @@ -54,20 +148,37 @@ typedef struct * should be called with the maximum numbe of vertices and maximum number of faces for any single * model. * + * Each initRenderer*() function may be called multiple times without calling deinitRenderer() + * in-between each call. + * + * @param A model to use to determine the buffer space needed */ void initRenderer(const model_t* model); /** * @brief Initializes the renderer, allocating temporary buffers needed to draw efficiently. * + * Each initRenderer*() function may be called multiple times without calling deinitRenderer() + * in-between each call. + * * @param maxVerts The maximum number of vertices in a model that will be drawn * @param maxFaces The maximum number of lines in a model that will be drawn */ void initRendererCustom(uint16_t maxVerts, uint16_t maxFaces); /** - * @brief Deinitializes the renderer, clearing any temporary buffers that were allocated + * @brief Initializes the renderer, allocating temporary buffers sufficient to draw the given + * scene efficiently. + * + * Each initRenderer*() function may be called multiple times without calling deinitRenderer() + * in-between each call. * + * @param scene + */ +void initRendererScene(const scene_t* scene); + +/** + * @brief Deinitializes the renderer, clearing any temporary buffers that were allocated. */ void deinitRenderer(void); @@ -86,6 +197,20 @@ void deinitRenderer(void); * @param w The width of the window to draw the model within * @param h The height of the window to draw the model within */ -void drawModel(const model_t* model, float orient[4], float scale, float translate[3], uint16_t x, uint16_t y, uint16_t w, uint16_t h); +void drawModel(const model_t* model, float orient[4], float scale, float translate[3], uint16_t x, uint16_t y, + uint16_t w, uint16_t h); + +/** + * @brief Render a scene with multiple 3D models + * + * initRendererScene() must be called once first before drawing the scene. + * + * @param scene The scene to draw + * @param x The X coordinate of the left side of the location to draw the scene within + * @param y The Y coordinate of the top side of the window to draw the scene within + * @param w The width of the window to draw the model within + * @param h The height of the window to draw the model within + */ +void drawScene(const scene_t* scene, uint16_t x, uint16_t y, uint16_t w, uint16_t h); #endif From b41345ac1a7e6eaea28bf584083fae61af81ab64 Mon Sep 17 00:00:00 2001 From: Dylan Whichard Date: Sat, 21 Oct 2023 17:05:57 -0700 Subject: [PATCH 11/11] Use scene in accelTest --- main/modes/accelTest/accelTest.c | 86 ++++++++++++++++++++------------ 1 file changed, 55 insertions(+), 31 deletions(-) diff --git a/main/modes/accelTest/accelTest.c b/main/modes/accelTest/accelTest.c index 044200eae..99e61773a 100644 --- a/main/modes/accelTest/accelTest.c +++ b/main/modes/accelTest/accelTest.c @@ -13,6 +13,7 @@ #include "swadge2024.h" #include "accelTest.h" +#include "hdw-imu.h" #include "esp_log.h" #include "trigonometry.h" #include "shapes.h" @@ -76,10 +77,14 @@ typedef struct model_t bunny; ///< The bunny 3D model model_t donut; ///< The donut 3D model + scene_t scene; + bool translateY; float scale; float translate[3]; + uint8_t selectedModel; + uint16_t btnState; ///< The button state int16_t x; ///< The latest X accelerometer reading @@ -169,13 +174,24 @@ static void accelTestEnterMode(void) ESP_LOGI("Model", "loadModel(bunny.mdl) returned %s", loadModel("bunny.mdl", &accelTest->bunny, true) ? "true" : "false"); loadModel("donut.mdl", &accelTest->donut, true); - accelTest->scale = 1.0; - accelTest->translate[0] = 0.0; - accelTest->translate[1] = 0.0; - accelTest->translate[2] = 0.0; + accelTest->scene.modelCount = 2; + accelTest->scene.models[0].model = &accelTest->donut; + accelTest->scene.models[0].scale = 0.5; + accelTest->scene.models[0].translate[0] = -25.0; + accelTest->scene.models[0].translate[1] = -25.0; + accelTest->scene.models[0].translate[2] = 0.0; + + accelTest->scene.models[1].model = &accelTest->donut; + accelTest->scene.models[1].scale = 0.1; + accelTest->scene.models[1].translate[0] = 25.0; + accelTest->scene.models[1].translate[1] = 25.0; + accelTest->scene.models[1].translate[2] = -1.0; + + // Ensure there's sufficient space to draw both models + initRendererScene(&accelTest->scene); // Ensure there's sufficient space to draw either model - initRendererCustom(MAX(accelTest->bunny.vertCount, accelTest->donut.vertCount), MAX(accelTest->bunny.triCount, accelTest->donut.triCount)); + //initRendererCustom(MAX(accelTest->bunny.vertCount, accelTest->donut.vertCount), MAX(accelTest->bunny.triCount, accelTest->donut.triCount)); // writeTextlabels doesn't get reset by accelTestReset(), so initialize that here accelTest->writeTextLabels = true; @@ -213,6 +229,20 @@ static void accelTestExitMode(void) */ static void accelTestMainLoop(int64_t elapsedUs) { + int32_t angle, radius, intensity; + if (getTouchJoystick(&angle, &radius, &intensity)) + { + int32_t x, y; + getTouchCartesian(angle, radius, &x, &y); + + float minX = -126.0; + float maxX = 126.0; + float minY = -126.0; + float maxY = 126.0; + + accelTest->scene.models[accelTest->selectedModel].translate[0] = minX + ((maxX - minX) * x / 1023.0); + accelTest->scene.models[accelTest->selectedModel].translate[1] = minY + ((maxY - minY) * y / 1023.0); + } // Always process button events, regardless of control scheme, so the main menu button can be captured buttonEvt_t evt = {0}; while (checkButtonQueueWrapper(&evt)) @@ -233,44 +263,27 @@ static void accelTestMainLoop(int64_t elapsedUs) if (evt.down && (PB_B == evt.button)) { - accelTest->translateY = !accelTest->translateY; + accelTest->selectedModel = (accelTest->selectedModel + 1) % accelTest->scene.modelCount; } if (evt.down && (PB_UP == evt.button)) { - accelTest->scale += .1; + accelTest->scene.models[accelTest->selectedModel].scale += .1; } if (evt.down && (PB_DOWN == evt.button)) { - if (accelTest->scale > .15) - { - accelTest->scale -= .1; - } + accelTest->scene.models[accelTest->selectedModel].scale -= .1; } if (evt.down && (PB_LEFT == evt.button)) { - if (accelTest->translateY) - { - accelTest->translate[1] -= 5.0; - } - else - { - accelTest->translate[0] -= 5.0; - } + accelTest->scene.models[accelTest->selectedModel].translate[0] -= 5.0; } if (evt.down && (PB_RIGHT == evt.button)) { - if (accelTest->translateY) - { - accelTest->translate[1] += 5.0; - } - else - { - accelTest->translate[0] += 5.0; - } + accelTest->scene.models[accelTest->selectedModel].translate[0] += 5.0; } ESP_LOGI("Accel", "Scale: %f", accelTest->scale); @@ -330,11 +343,22 @@ static void accelTestHandleInput(void) static void accelDrawBunny(void) { // Get the orientation from the accelerometer - float orient[4]; - memcpy(orient, LSM6DSL.fqQuat, sizeof(orient)); + for (uint8_t i = 0; i < accelTest->scene.modelCount; i++) + { + memcpy(accelTest->scene.models[i].orient, LSM6DSL.fqQuat, sizeof(float) * 4); + + if (i == 0) + { + float objRot[4] = {0}; + objRot[3] = 600.0; + mathQuatApply(accelTest->scene.models[i].orient, accelTest->scene.models[i].orient, objRot); + } + } + + drawScene(&accelTest->scene, 0, 0, TFT_WIDTH, TFT_HEIGHT); - drawModel(&accelTest->donut, orient, accelTest->scale / 2, accelTest->translate, 0, TFT_HEIGHT / 2, TFT_WIDTH / 2, TFT_HEIGHT / 2); - drawModel(&accelTest->bunny, orient, accelTest->scale / 2, accelTest->translate, TFT_WIDTH / 2, TFT_HEIGHT / 2, TFT_WIDTH / 2, TFT_HEIGHT / 2); + //drawModel(&accelTest->donut, orient, accelTest->scale / 2, accelTest->translate, 0, TFT_HEIGHT / 2, TFT_WIDTH / 2, TFT_HEIGHT / 2); + //drawModel(&accelTest->bunny, orient, accelTest->scale / 2, accelTest->translate, TFT_WIDTH / 2, TFT_HEIGHT / 2, TFT_WIDTH / 2, TFT_HEIGHT / 2); } /**