mtl support
This commit is contained in:
parent
1f0437ab0c
commit
76bbf980eb
9 changed files with 194 additions and 54 deletions
BIN
data/mdl/maxwell.mdl
Normal file
BIN
data/mdl/maxwell.mdl
Normal file
Binary file not shown.
Binary file not shown.
|
|
@ -18,9 +18,12 @@ GSDECL int GSGLShaderPrepare(GSGL gl, GLuint* shader, const char* vs, const char
|
||||||
/* gl_texture.c */
|
/* gl_texture.c */
|
||||||
GSDECL void GSGLTexturePrepare(GSGL gl, GLuint* texture, unsigned char* rgba, int width, int height);
|
GSDECL void GSGLTexturePrepare(GSGL gl, GLuint* texture, unsigned char* rgba, int width, int height);
|
||||||
GSDECL void GSGLTextureSet(GSGL gl, GLuint texture);
|
GSDECL void GSGLTextureSet(GSGL gl, GLuint texture);
|
||||||
GSDECL int GSGLTextureLoadFile(GSGL gl, GLuint* texture, int* width, int* height, const char* filename);
|
|
||||||
GSDECL void GSGLTextureDelete(GSGL gl, GLuint texture);
|
GSDECL void GSGLTextureDelete(GSGL gl, GLuint texture);
|
||||||
|
|
||||||
|
/* gl_common.c */
|
||||||
|
GSDECL int GSGLTextureLoadFile(GSGL gl, GLuint* texture, int* width, int* height, const char* filename);
|
||||||
|
GSDECL int GSGLTextureTry(GSGL gl, GLuint* texture, int* width, int* height, const char* prefix);
|
||||||
|
|
||||||
/* gl_shadow.c */
|
/* gl_shadow.c */
|
||||||
GSDECL void GSGLShadowInit(GSGL gl);
|
GSDECL void GSGLShadowInit(GSGL gl);
|
||||||
GSDECL int GSGLShadowBeforeMapping(GSGL gl);
|
GSDECL int GSGLShadowBeforeMapping(GSGL gl);
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,9 @@ typedef struct _GSGL* GSGL;
|
||||||
typedef struct _GSSkyBox* GSSkyBox;
|
typedef struct _GSSkyBox* GSSkyBox;
|
||||||
typedef struct _GSModel* GSModel;
|
typedef struct _GSModel* GSModel;
|
||||||
|
|
||||||
typedef struct _GSModelFace GSModelFace;
|
typedef struct _GSModelFace GSModelFace;
|
||||||
|
typedef struct _GSModelMaterial GSModelMaterial;
|
||||||
|
typedef struct _GSModelUseMaterial GSModelUseMaterial;
|
||||||
#else
|
#else
|
||||||
typedef void* GSClient;
|
typedef void* GSClient;
|
||||||
typedef void* GSServer;
|
typedef void* GSServer;
|
||||||
|
|
@ -121,12 +123,24 @@ struct _GSModelFace {
|
||||||
GSVector2* texcoord;
|
GSVector2* texcoord;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _GSModelMaterial {
|
||||||
|
char* key;
|
||||||
|
GLuint value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GSModelUseMaterial {
|
||||||
|
int key;
|
||||||
|
char* value;
|
||||||
|
};
|
||||||
|
|
||||||
struct _GSModel {
|
struct _GSModel {
|
||||||
GSEngine engine;
|
GSEngine engine;
|
||||||
|
|
||||||
GLuint texture;
|
|
||||||
GLuint call_list;
|
GLuint call_list;
|
||||||
|
|
||||||
|
GSModelMaterial* material;
|
||||||
|
GSModelUseMaterial* usemtl;
|
||||||
|
|
||||||
float* vertex;
|
float* vertex;
|
||||||
float* texcoord;
|
float* texcoord;
|
||||||
GSModelFace* face;
|
GSModelFace* face;
|
||||||
|
|
|
||||||
62
engine/src/gl_common.c
Normal file
62
engine/src/gl_common.c
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
#include <GearSrc/GL.h>
|
||||||
|
|
||||||
|
#include <GearSrc/String.h>
|
||||||
|
#include <GearSrc/File.h>
|
||||||
|
|
||||||
|
#include <stb_image.h>
|
||||||
|
|
||||||
|
int GSGLTextureLoadFile(GSGL gl, GLuint* texture, int* width, int* height, const char* filename) {
|
||||||
|
GSFile f = GSFileOpen(gl->engine, filename);
|
||||||
|
unsigned char* data;
|
||||||
|
unsigned char* rgba;
|
||||||
|
unsigned long sz;
|
||||||
|
int ch;
|
||||||
|
int st = 1;
|
||||||
|
int w, h;
|
||||||
|
if(f == NULL) return 0;
|
||||||
|
|
||||||
|
sz = GSFileSize(f);
|
||||||
|
|
||||||
|
data = malloc(sz);
|
||||||
|
GSFileRead(f, data, sz);
|
||||||
|
GSFileClose(f);
|
||||||
|
|
||||||
|
if((rgba = stbi_load_from_memory(data, sz, &w, &h, &ch, 4)) == NULL) {
|
||||||
|
st = 0;
|
||||||
|
} else {
|
||||||
|
GSGLTexturePrepare(gl, texture, rgba, w, h);
|
||||||
|
|
||||||
|
free(rgba);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(width != NULL) *width = w;
|
||||||
|
if(height != NULL) *height = h;
|
||||||
|
|
||||||
|
free(data);
|
||||||
|
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GSGLTextureTry(GSGL gl, GLuint* texture, int* width, int* height, const char* prefix) {
|
||||||
|
char* png = GSStringConcat(prefix, ".png");
|
||||||
|
char* bmp = GSStringConcat(prefix, ".bmp");
|
||||||
|
char* jpg = GSStringConcat(prefix, ".jpg");
|
||||||
|
char* jpeg = GSStringConcat(prefix, ".jpeg");
|
||||||
|
int st = 1;
|
||||||
|
|
||||||
|
if(GSGLTextureLoadFile(gl, texture, width, height, prefix)) {
|
||||||
|
} else if(GSGLTextureLoadFile(gl, texture, width, height, png)) {
|
||||||
|
} else if(GSGLTextureLoadFile(gl, texture, width, height, bmp)) {
|
||||||
|
} else if(GSGLTextureLoadFile(gl, texture, width, height, jpg)) {
|
||||||
|
} else if(GSGLTextureLoadFile(gl, texture, width, height, jpeg)) {
|
||||||
|
} else {
|
||||||
|
st = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(jpeg);
|
||||||
|
free(jpg);
|
||||||
|
free(bmp);
|
||||||
|
free(png);
|
||||||
|
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,5 @@
|
||||||
#include <GearSrc/GL.h>
|
#include <GearSrc/GL.h>
|
||||||
|
|
||||||
#include <GearSrc/File.h>
|
|
||||||
|
|
||||||
#include <stb_image.h>
|
|
||||||
|
|
||||||
void GSGLTexturePrepare(GSGL gl, GLuint* texture, unsigned char* rgba, int width, int height) {
|
void GSGLTexturePrepare(GSGL gl, GLuint* texture, unsigned char* rgba, int width, int height) {
|
||||||
glGenTextures(1, texture);
|
glGenTextures(1, texture);
|
||||||
glBindTexture(GL_TEXTURE_2D, *texture);
|
glBindTexture(GL_TEXTURE_2D, *texture);
|
||||||
|
|
@ -23,38 +19,6 @@ void GSGLTextureDisable(GSGL gl, GLuint texture) {
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int GSGLTextureLoadFile(GSGL gl, GLuint* texture, int* width, int* height, const char* filename) {
|
|
||||||
GSFile f = GSFileOpen(gl->engine, filename);
|
|
||||||
unsigned char* data;
|
|
||||||
unsigned char* rgba;
|
|
||||||
unsigned long sz;
|
|
||||||
int ch;
|
|
||||||
int st = 1;
|
|
||||||
int w, h;
|
|
||||||
if(f == NULL) return 0;
|
|
||||||
|
|
||||||
sz = GSFileSize(f);
|
|
||||||
|
|
||||||
data = malloc(sz);
|
|
||||||
GSFileRead(f, data, sz);
|
|
||||||
GSFileClose(f);
|
|
||||||
|
|
||||||
if((rgba = stbi_load_from_memory(data, sz, &w, &h, &ch, 4)) == NULL) {
|
|
||||||
st = 0;
|
|
||||||
} else {
|
|
||||||
GSGLTexturePrepare(gl, texture, rgba, w, h);
|
|
||||||
|
|
||||||
free(rgba);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(width != NULL) *width = w;
|
|
||||||
if(height != NULL) *height = h;
|
|
||||||
|
|
||||||
free(data);
|
|
||||||
|
|
||||||
return st;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSGLTextureSet(GSGL gl, GLuint texture) {
|
void GSGLTextureSet(GSGL gl, GLuint texture) {
|
||||||
glBindTexture(GL_TEXTURE_2D, texture);
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
if(texture == 0) {
|
if(texture == 0) {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include <GearSrc/File.h>
|
#include <GearSrc/File.h>
|
||||||
#include <GearSrc/Log.h>
|
#include <GearSrc/Log.h>
|
||||||
#include <GearSrc/Math.h>
|
#include <GearSrc/Math.h>
|
||||||
|
#include <GearSrc/String.h>
|
||||||
|
|
||||||
#include <stb_ds.h>
|
#include <stb_ds.h>
|
||||||
|
|
||||||
|
|
@ -25,13 +26,18 @@ static void parse_obj(GSModel model, char* txt) {
|
||||||
if(strlen(f) > 0 && f[0] != '#') {
|
if(strlen(f) > 0 && f[0] != '#') {
|
||||||
char* arg;
|
char* arg;
|
||||||
|
|
||||||
if(f[strlen(f) - 1] == '\n') f[strlen(f) - 1] = 0;
|
if(f[strlen(f) - 1] == '\r') f[strlen(f) - 1] = 0;
|
||||||
|
|
||||||
if((arg = strchr(f, ' ')) != NULL) {
|
if((arg = strchr(f, ' ')) != NULL) {
|
||||||
arg[0] = 0;
|
arg[0] = 0;
|
||||||
arg++;
|
arg++;
|
||||||
|
|
||||||
if(strcmp(f, "v") == 0) {
|
if(strcmp(f, "usemtl") == 0) {
|
||||||
|
int k = arrlen(model->face);
|
||||||
|
char* v = GSStringDuplicate(arg);
|
||||||
|
|
||||||
|
hmput(model->usemtl, k, v);
|
||||||
|
} else if(strcmp(f, "v") == 0) {
|
||||||
float v0, v1, v2;
|
float v0, v1, v2;
|
||||||
|
|
||||||
sscanf(arg, "%f %f %f", &v0, &v1, &v2);
|
sscanf(arg, "%f %f %f", &v0, &v1, &v2);
|
||||||
|
|
@ -154,12 +160,54 @@ static void parse_obj(GSModel model, char* txt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void parse_mtl(GSModel model, char* txt) {
|
||||||
|
char* f = txt;
|
||||||
|
char* m = NULL;
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
char* s = strchr(f, '\n');
|
||||||
|
|
||||||
|
if(s != NULL) s[0] = 0;
|
||||||
|
|
||||||
|
if(strlen(f) > 0 && f[0] != '#') {
|
||||||
|
char* arg;
|
||||||
|
|
||||||
|
if(f[strlen(f) - 1] == '\r') f[strlen(f) - 1] = 0;
|
||||||
|
|
||||||
|
if((arg = strchr(f, ' ')) != NULL) {
|
||||||
|
arg[0] = 0;
|
||||||
|
arg++;
|
||||||
|
|
||||||
|
if(strcmp(f, "newmtl") == 0) {
|
||||||
|
GLuint v = 0;
|
||||||
|
|
||||||
|
shput(model->material, arg, v);
|
||||||
|
|
||||||
|
if(m != NULL) free(m);
|
||||||
|
m = GSStringDuplicate(arg);
|
||||||
|
} else if(strcmp(f, "map_Kd") == 0 && m != NULL) {
|
||||||
|
GLuint t = 0;
|
||||||
|
char* p = GSStringConcat("model-ws:/", arg);
|
||||||
|
|
||||||
|
if(GSGLTextureTry(model->engine->client->gl, &t, NULL, NULL, p)) {
|
||||||
|
shput(model->material, m, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(s == NULL) break;
|
||||||
|
f = s + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m != NULL) free(m);
|
||||||
|
}
|
||||||
|
|
||||||
GSModel GSModelOpen(GSEngine engine, const char* path) {
|
GSModel GSModelOpen(GSEngine engine, const char* path) {
|
||||||
GSModel model = malloc(sizeof(*model));
|
GSModel model = malloc(sizeof(*model));
|
||||||
GSFile f;
|
GSFile f;
|
||||||
char* buffer;
|
char* buffer;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
int w, h;
|
|
||||||
GSGL gl = NULL;
|
GSGL gl = NULL;
|
||||||
|
|
||||||
if(engine->client != NULL) gl = engine->client->gl;
|
if(engine->client != NULL) gl = engine->client->gl;
|
||||||
|
|
@ -173,6 +221,22 @@ GSModel GSModelOpen(GSEngine engine, const char* path) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model->material = NULL;
|
||||||
|
sh_new_strdup(model->material);
|
||||||
|
|
||||||
|
model->usemtl = NULL;
|
||||||
|
|
||||||
|
if(gl != NULL) {
|
||||||
|
GLuint t = 0;
|
||||||
|
|
||||||
|
GSGLTextureTry(gl, &t, NULL, NULL, "model-ws:/model");
|
||||||
|
|
||||||
|
if(t != 0) {
|
||||||
|
char* k = "default";
|
||||||
|
shput(model->material, k, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((f = GSFileOpen(engine, "model-ws:/model.obj")) == NULL) {
|
if((f = GSFileOpen(engine, "model-ws:/model.obj")) == NULL) {
|
||||||
GSEngineUnregisterResource(engine, "model-ws");
|
GSEngineUnregisterResource(engine, "model-ws");
|
||||||
|
|
||||||
|
|
@ -180,14 +244,6 @@ GSModel GSModelOpen(GSEngine engine, const char* path) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(gl != NULL) {
|
|
||||||
if(GSGLTextureLoadFile(gl, &model->texture, &w, &h, "model-ws:/model.png")) {
|
|
||||||
} else if(GSGLTextureLoadFile(gl, &model->texture, &w, &h, "model-ws:/model.bmp")) {
|
|
||||||
} else if(GSGLTextureLoadFile(gl, &model->texture, &w, &h, "model-ws:/model.jpg")) {
|
|
||||||
} else if(GSGLTextureLoadFile(gl, &model->texture, &w, &h, "model-ws:/model.jpeg")) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size = GSFileSize(f);
|
size = GSFileSize(f);
|
||||||
buffer = malloc(size + 1);
|
buffer = malloc(size + 1);
|
||||||
buffer[size] = 0;
|
buffer[size] = 0;
|
||||||
|
|
@ -199,6 +255,19 @@ GSModel GSModelOpen(GSEngine engine, const char* path) {
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
|
if(gl != NULL && (f = GSFileOpen(engine, "model-ws:/model.mtl")) != NULL) {
|
||||||
|
size = GSFileSize(f);
|
||||||
|
buffer = malloc(size + 1);
|
||||||
|
buffer[size] = 0;
|
||||||
|
|
||||||
|
GSFileRead(f, buffer, size);
|
||||||
|
GSFileClose(f);
|
||||||
|
|
||||||
|
parse_mtl(model, buffer);
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
GSEngineUnregisterResource(engine, "model-ws");
|
GSEngineUnregisterResource(engine, "model-ws");
|
||||||
|
|
||||||
GSLog(GSLogInfo, "Opened model %s, %d vertexes, %d faces", path, arrlen(model->vertex), arrlen(model->face));
|
GSLog(GSLogInfo, "Opened model %s, %d vertexes, %d faces", path, arrlen(model->vertex), arrlen(model->face));
|
||||||
|
|
@ -225,9 +294,17 @@ void GSModelDraw(GSModel model, GSVector3 pos, GSVector3 rot) {
|
||||||
GSGLSetPosition(gl, pos, rot);
|
GSGLSetPosition(gl, pos, rot);
|
||||||
|
|
||||||
if(model->call_list == 0) {
|
if(model->call_list == 0) {
|
||||||
GSGLTextureSet(gl, model->texture);
|
char* k = "default";
|
||||||
|
|
||||||
|
GSGLTextureSet(gl, shget(model->material, k));
|
||||||
|
|
||||||
for(i = 0; i < arrlen(model->face); i++) {
|
for(i = 0; i < arrlen(model->face); i++) {
|
||||||
|
int ind = hmgeti(model->usemtl, i);
|
||||||
|
|
||||||
|
if(ind != -1) {
|
||||||
|
GSGLTextureSet(gl, shget(model->material, model->usemtl[ind].value));
|
||||||
|
}
|
||||||
|
|
||||||
GSGLPolygon(gl, model->face[i].count, model->face[i].vertex, model->face[i].texcoord, model->face[i].normal);
|
GSGLPolygon(gl, model->face[i].count, model->face[i].vertex, model->face[i].texcoord, model->face[i].normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -247,10 +324,18 @@ void GSModelClose(GSModel model) {
|
||||||
}
|
}
|
||||||
arrfree(model->face);
|
arrfree(model->face);
|
||||||
|
|
||||||
|
for(i = 0; i < shlen(model->material); i++) {
|
||||||
|
GSGLTextureDelete(model->engine->client->gl, model->material[i].value);
|
||||||
|
}
|
||||||
|
shfree(model->material);
|
||||||
|
|
||||||
|
for(i = 0; i < hmlen(model->usemtl); i++) {
|
||||||
|
free(model->usemtl[i].value);
|
||||||
|
}
|
||||||
|
hmfree(model->usemtl);
|
||||||
|
|
||||||
arrfree(model->vertex);
|
arrfree(model->vertex);
|
||||||
arrfree(model->texcoord);
|
arrfree(model->texcoord);
|
||||||
|
|
||||||
if(model->texture != 0) GSGLTextureDelete(model->engine->client->gl, model->texture);
|
|
||||||
|
|
||||||
free(model);
|
free(model);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
resource/model/tetopear/model.mtl
Normal file
12
resource/model/tetopear/model.mtl
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
# File generated by ImageToStl.com - Free Image and 3D model conversion tools
|
||||||
|
|
||||||
|
newmtl mat0
|
||||||
|
Ns 0
|
||||||
|
Ka 1.0 1.0 1.0
|
||||||
|
Kd 1 1 1
|
||||||
|
Ks 0.5 0.5 0.5
|
||||||
|
Ke 0.0 0.0 0.0
|
||||||
|
Ni 1.0
|
||||||
|
d 1
|
||||||
|
illum 2
|
||||||
|
map_Kd model.png
|
||||||
|
|
@ -1878,7 +1878,7 @@ vt 0.49441 0.27544
|
||||||
vt 0.49577 0.28985
|
vt 0.49577 0.28985
|
||||||
vt 0.04985 0.93435
|
vt 0.04985 0.93435
|
||||||
vt 0.04985 0.93435
|
vt 0.04985 0.93435
|
||||||
|
usemtl mat0
|
||||||
f 1/1/1 2/2/2 3/3/3
|
f 1/1/1 2/2/2 3/3/3
|
||||||
f 1/1/1 3/3/3 4/4/4
|
f 1/1/1 3/3/3 4/4/4
|
||||||
f 5/5/5 6/6/6 1/1/1
|
f 5/5/5 6/6/6 1/1/1
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue