Last active
December 28, 2018 08:39
-
-
Save salty-godzilla/dc5865965819d0819446d0d6ef602e9b to your computer and use it in GitHub Desktop.
BD1 to OBJ Converter (Licence: CC0)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string> | |
#include <iostream> | |
#include <vector> | |
#include <Windows.h> | |
#include "MapData.hpp" | |
void printBd1Structure(MapData map) | |
{ | |
printf("- Textures\n"); | |
for (int i = 0; i < NUM_TEXTURES; i++) { | |
printf(" - %d: %s\n", i, map.texturesPath[i].c_str()); | |
} | |
printf("\n- Num of blocks: %d\n", map.numBlocks); | |
for (int i = 0; i < map.numBlocks; i++) { | |
printf("\n- Block %d\n", i); | |
for (int j = 0; j < NUM_VERTICES; j++) { | |
printf(" - Vertex %d (X: %f Y: %f Z: %f)\n", | |
j, | |
map.block[i].vertex[j].x, | |
map.block[i].vertex[j].y, | |
map.block[i].vertex[j].z); | |
} | |
for (int j = 0; j < NUM_FACES; j++) { | |
printf(" - Face %d\n", j); | |
printf(" - Texture: %d\n", map.block[i].face[j].textureId); | |
for (int k = 0; k < 4; k++) { | |
printf(" - UV %d (U: %f V: %f)\n", k, map.block[i].face[j].uv[k].u, map.block[i].face[j].uv[k].v); | |
} | |
} | |
} | |
} | |
void outputFaceLine(MapData &map, FILE *fp, int textureId, int v1, int vt1, int v2, int vt2, int v3, int vt3, int v4, int vt4) | |
{ | |
static int lastTexture = -1; | |
if (lastTexture != textureId) { | |
fprintf(fp, "usemtl %s\n", map.texturesPath[textureId].c_str()); | |
lastTexture = textureId; | |
} | |
fprintf(fp, "f %d/%d %d/%d %d/%d %d/%d\n", v1, vt1, v2, vt2, v3, vt3, v4, vt4); | |
}; | |
void exportObjFile(MapData map, std::wstring path) | |
{ | |
FILE *fp; | |
fp = _wfopen(path.c_str(), L"wb"); | |
fprintf(fp, "# generated by bd1Parser\n\n"); | |
fprintf(fp, "mtllib temp.mtl\n\n"); | |
for (int i = 0; i < map.numBlocks; i++) { | |
for (int j = 0; j < NUM_VERTICES; j++) { | |
fprintf(fp, "v %f %f %f\n", -map.block[i].vertex[j].x / 100, map.block[i].vertex[j].y / 100, map.block[i].vertex[j].z / 100); | |
} | |
} | |
fprintf(fp, "\n\n"); | |
for (int i = 0; i < map.numBlocks; i++) { | |
for (int j = 0; j < NUM_FACES; j++) { | |
for (int k = 0; k < 4; k++) { | |
fprintf(fp, "vt %f %f\n", map.block[i].face[j].uv[k].u, 1 - map.block[i].face[j].uv[k].v); | |
} | |
} | |
} | |
fprintf(fp, "\n\n"); | |
for (int i = 0; i < map.numBlocks; i++) { | |
int b = i * 8; | |
int uvb = i * 24; | |
outputFaceLine(map, fp, map.block[i].face[0].textureId, b + 1, uvb + 4, b + 2, uvb + 3, b + 3, uvb + 2, b + 4, uvb + 1); // 上 | |
outputFaceLine(map, fp, map.block[i].face[1].textureId, b + 8, uvb + 8, b + 7, uvb + 7, b + 6, uvb + 6, b + 5, uvb + 5); // 下 | |
outputFaceLine(map, fp, map.block[i].face[2].textureId, b + 5, uvb + 12, b + 6, uvb + 11, b + 2, uvb + 10, b + 1, uvb + 9); // 前 | |
outputFaceLine(map, fp, map.block[i].face[3].textureId, b + 6, uvb + 16, b + 7, uvb + 15, b + 3, uvb + 14, b + 2, uvb + 13); // 右 | |
outputFaceLine(map, fp, map.block[i].face[4].textureId, b + 7, uvb + 20, b + 8, uvb + 19, b + 4, uvb + 18, b + 3, uvb + 17); // 後 | |
outputFaceLine(map, fp, map.block[i].face[5].textureId, b + 8, uvb + 24, b + 5, uvb + 23, b + 1, uvb + 22, b + 4, uvb + 21); // 左 | |
} | |
fclose(fp); | |
} | |
void exportMtlFile(MapData map, std::wstring path) | |
{ | |
FILE *fp; | |
fp = _wfopen(path.c_str(), L"wb"); | |
fprintf(fp, "# generated by bd1Parser\n"); | |
for (int i = 0; i < 10; i++) { | |
if (map.texturesPath[i].empty()) { | |
continue; | |
} | |
fprintf(fp, "\nnewmtl %s\n", map.texturesPath[i].c_str()); | |
fprintf(fp, "Ka 0.40000 0.40000 0.40000\n"); | |
fprintf(fp, "Kd 0.90000 0.90000 0.90000\n"); | |
fprintf(fp, "Ks 0.00000 0.00000 0.00000\n"); | |
fprintf(fp, "Ns 5.00000\n"); | |
fprintf(fp, "map_Kd %s\n", map.texturesPath[i].c_str()); | |
} | |
fclose(fp); | |
} | |
int openBd1FileDialog(std::wstring &path) { | |
OPENFILENAME ofn = {}; | |
wchar_t _path[1024] = {}; | |
ofn.lStructSize = sizeof(OPENFILENAME); | |
ofn.lpstrFilter = L"Block data(*.bd1)\0*.bd1\0"; | |
ofn.lpstrFile = _path; | |
ofn.nMaxFile = sizeof(_path); | |
ofn.lpstrTitle = L"Select a block data file"; | |
ofn.Flags = OFN_FILEMUSTEXIST; | |
if (!GetOpenFileName(&ofn)) { | |
return 1; | |
} | |
path = _path; | |
return 0; | |
} | |
int parseBd1(std::wstring bd1Path, MapData &map) { | |
FILE *fp; | |
fp = _wfopen(bd1Path.c_str(), L"rb"); | |
if (!fp) { | |
printf("bd1 open failed!\n"); | |
fclose(fp); | |
return 1; | |
} | |
// textures | |
for (int i = 0; i < NUM_TEXTURES; i++) { | |
char texturePath[32]; | |
fread(texturePath, sizeof(texturePath) - 1, 1, fp); | |
map.texturesPath[i] = texturePath; | |
} | |
// block count | |
fread(&map.numBlocks, 1, 1, fp); | |
// skip 1byte | |
fseek(fp, 1, SEEK_CUR); | |
for (int i = 0; i < map.numBlocks; i++) { | |
float vertexRawData[3 * NUM_VERTICES]; | |
fread(vertexRawData, sizeof(float), (3 * NUM_VERTICES), fp); | |
// vertex data | |
for (int j = 0; j < NUM_VERTICES; j++) { | |
map.block[i].vertex[j].x = vertexRawData[0 + j]; | |
map.block[i].vertex[j].y = vertexRawData[8 + j]; | |
map.block[i].vertex[j].z = vertexRawData[16 + j]; | |
} | |
// uv data | |
float uvRawData[48]; // 48 * 4 = 192 bytes | |
fread(uvRawData, sizeof(float), 48, fp); | |
for (int face = 0; face < NUM_FACES; face++) { | |
for (int uvs = 0; uvs < 4; uvs++) { | |
map.block[i].face[face].uv[uvs].u = uvRawData[face * 4 + uvs]; | |
map.block[i].face[face].uv[uvs].v = uvRawData[face * 4 + uvs + 24]; | |
} | |
} | |
// texture selection | |
uint8_t texSelectRawData[24]; | |
fread(texSelectRawData, 1, 24, fp); | |
for (int face = 0; face < NUM_FACES; face++) { | |
map.block[i].face[face].textureId = texSelectRawData[face * 4]; | |
} | |
// enable / disable flag | |
fread(&map.block[i].isEnabled, 1, 1, fp); | |
// skip 3 bytes | |
fseek(fp, 3, SEEK_CUR); | |
} | |
fclose(fp); | |
return 0; | |
} | |
int main() | |
{ | |
std::wstring bd1Path; | |
if (openBd1FileDialog(bd1Path)) { | |
return 1; | |
} | |
std::wstring objPath = bd1Path.substr(0, bd1Path.find_last_of('\\')) + L"\\temp.obj"; | |
std::wstring mtlPath = bd1Path.substr(0, bd1Path.find_last_of('\\')) + L"\\temp.mtl"; | |
MapData map; | |
parseBd1(bd1Path, map); | |
printBd1Structure(map); | |
exportObjFile(map, objPath); | |
exportMtlFile(map, mtlPath); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <iostream> | |
#include <vector> | |
const auto NUM_TEXTURES = 10; | |
const auto NUM_FACES = 6; | |
const auto NUM_VERTICES = 8; | |
struct MapData | |
{ | |
struct Block | |
{ | |
struct Face | |
{ | |
struct Uv | |
{ | |
float u; | |
float v; | |
} uv[4]; | |
uint8_t textureId; | |
} face[NUM_FACES]; | |
struct Vertices | |
{ | |
float x; | |
float y; | |
float z; | |
} vertex[NUM_VERTICES]; | |
bool isEnabled; | |
} block[160]; | |
std::string texturesPath[NUM_TEXTURES]; | |
uint8_t numBlocks; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment