从 obj 文件加载时显示单色而不是纹理
Posted
技术标签:
【中文标题】从 obj 文件加载时显示单色而不是纹理【英文标题】:Single color is displayed instead of texture while loading from obj file 【发布时间】:2014-05-14 09:45:43 【问题描述】:当我尝试从 mtl 文件加载纹理时,会显示一种颜色。我试图通过改变照明来修复它,但它不起作用。我是 Opengl 的新手,使用 cpplusplusguy 的 opengl 教程系列来学习。 我正在使用的图像! http://i.imgur.com/3QfAtnD.png?1 我得到的结果! http://i.imgur.com/BOiOhA0.png
我的文件
SDL.cpp
#include "objloader.h"
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
float angle = 0.0;
//Starts up SDL, creates window, and initializes OpenGL
bool init();
//Initializes matrices and clear color
bool initGL();
//Per frame update
void update();
//Renders quad to the screen
void render();
//Frees media and shuts down SDL
void close();
int loadObject(const char* filename);
//The window we'll be rendering to
SDL_Window* gWindow = NULL;
//OpenGL context
SDL_GLContext gContext;
bool init()
//Initialization flag
bool success = true;
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
printf( "SDL could not initialize! SDL Error: %s\n", SDL_GetError() );
success = false;
else
//Use OpenGL 2.1
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 2 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 );
//Create window
gWindow = SDL_CreateWindow( "SDL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN );
if( gWindow == NULL )
printf( "Window could not be created! SDL Error: %s\n", SDL_GetError() );
success = false;
else
//Create context
gContext = SDL_GL_CreateContext( gWindow );
if( gContext == NULL )
printf( "OpenGL context could not be created! SDL Error: %s\n", SDL_GetError() );
success = false;
else
//Use Vsync
if( SDL_GL_SetSwapInterval( 1 ) < 0 )
printf( "Warning: Unable to set VSync! SDL Error: %s\n", SDL_GetError() );
//Initialize OpenGL
if( !initGL() )
printf( "Unable to initialize OpenGL!\n" );
success = false;
return success;
int cube;
objloader obj;
bool initGL()
bool success = true;
GLenum error = GL_NO_ERROR;
glClearColor( 0.0, 0.0, 0.0, 1.0 );
//Initialize Projection Matrix
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective(45.0,640.0/480.0,1.0,500.0);
//Check for error
error = glGetError();
if( error != GL_NO_ERROR )
printf( "Error initializing OpenGL! %s\n", gluErrorString( error ) );
success = false;
//Initialize Modelview Matrix
glMatrixMode( GL_MODELVIEW );
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
cube=obj.load("test.obj");
//cube = loadObject("test.obj");
//glEnable(GL_LIGHTING);
//glEnable(GL_LIGHT0);
//glEnable(GL_FOG);
//glFogi(GL_FOG_MODE,GL_EXP);
//glFogf(GL_FOG_DENSITY,0.6);
//float col[] = 0.5,0.5,0.5,1.0;
//glFogfv(GL_FOG_COLOR,col);
float col[] = 1.0,1.0,1.0,1.0;
// glLightfv(GL_LIGHT0,GL_DIFFUSE,col);
//Check for error
error = glGetError();
if( error != GL_NO_ERROR )
printf( "Error initializing OpenGL! %s\n", gluErrorString( error ) );
success = false;
//Check for error
error = glGetError();
if( error != GL_NO_ERROR )
printf( "Error initializing OpenGL! %s\n", gluErrorString( error ) );
success = false;
return success;
void update()
//No per frame update needed
void render()
//Clear color buffer
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
float pos[]=0.0,10.0,-50.0,-5.0;
//glLightfv(GL_LIGHT0,GL_POSITION,pos);
glTranslatef(0.0,0.5,-5.0);
//glRotatef(angle,1.0,1.0,1.0);
glCallList(cube);
void close()
//Destroy window
SDL_DestroyWindow( gWindow );
gWindow = NULL;
//Quit SDL subsystems
SDL_Quit();
int main( int argc, char* args[] )
//Start up SDL and create window
if( !init() )
printf( "Failed to initialize!\n" );
else
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
//While application is running
while( !quit )
//Handle events on queue
while( SDL_PollEvent( &e ) != 0 )
//User requests quit
if( e.type == SDL_QUIT )
quit = true;
else if(e.type == SDL_KEYDOWN)
if(e.key.keysym.sym == SDLK_ESCAPE)
quit = true;
//Render quad
render();
angle += 0.5;
if(angle > 360)
angle -= 360;
//Update screen
SDL_GL_SwapWindow( gWindow );
//Free resources and close SDL
close();
return 0;
objloader.h
#ifndef OBJLOADER_H
#define OBJLOADER_H
#include <SDL.h>
#include <SDL_opengl.h>
#include <GL\GLU.h>
#include <stdio.h>
#include <cstdlib>
#include <vector>
#include <string>
#include <algorithm>
#include <fstream>
#include <cstdio>
#include<iostream>
#include<SDL_image.h>
#include <math.h>
//This struct contain 3 floats and a constructor, it's used for vertexes and normal vectors
struct coordinate
float x,y,z;
coordinate(float a,float b,float c);
;
//This structure is store every property of a face
struct face
int facenum; //the number of the face (it's start from 1 not 0, so if you use it as an index, subtract 1 from it), it's used for the normal vectors
bool four; //if true, than it's a quad else it's a triangle
int faces[4]; //indexes for every vertex, which makes the face (it's start from 1 not 0, so if you use it as an index, subtract 1 from it)
int texcoord[4]; //indexes for every texture coorinate that is in the face (it's start from 1 not 0, so if you use it as an index, subtract 1 from it)
int mat; //the index for the material, which is used by the face
face(int facen,int f1,int f2,int f3,int t1,int t2,int t3,int m); //constuctor for triangle
face(int facen,int f1,int f2,int f3,int f4,int t1,int t2,int t3,int t4,int m); //-"- for quad
;
//this is a structure, which contain one material
struct material
std::string name; //the name of the material
float alpha,ns,ni; //some property, alpha, shininess, and some other, which we not used
float dif[3],amb[3],spec[3]; //the color property (diffuse, ambient, specular)
int illum; //illum - we not use it
int texture; //the id for the texture, if there is no texture than -1
material(const char* na,float al,float n,float ni2,float* d,float* a,float* s,int i,int t);
;
//texture coorinate (UV coordinate), nothing to explain here
struct texcoord
float u,v;
texcoord(float a,float b);
;
//the main class for the object loader
class objloader
std::vector<std::string*> coord; //every line of code from the obj file
std::vector<coordinate*> vertex; //all vertexes
std::vector<face*> faces; //all faces
std::vector<coordinate*> normals; //all normal vectors
std::vector<unsigned int> texture;//the id for all the textures (so we can delete the textures after use it)
std::vector<unsigned int> lists; //the id for all lists (so we can delete the lists after use it)
std::vector<material*> materials; //all materials
std::vector<texcoord*> texturecoordinate; //all texture coorinate (UV coordinate)
bool ismaterial,isnormals,istexture; //obvious
unsigned int loadTexture(const char* filename); //private load texture function
void clean(); //free all of the used memory
public:
objloader();
~objloader(); //free the textures and lists
int load(const char* filename); //the main model load function
;
#endif // OBJLOADER_H
objloader.cpp
#include "objloader.h"
//nothing to explain here
coordinate::coordinate(float a,float b,float c)
x=a;
y=b;
z=c;
//nothing to explain here
face::face(int facen,int f1,int f2,int f3,int t1,int t2,int t3,int m)
facenum=facen;
faces[0]=f1;
faces[1]=f2;
faces[2]=f3;
texcoord[0]=t1;
texcoord[1]=t2;
texcoord[2]=t3;
mat=m;
four=false;
//nothing to explain here
face::face(int facen,int f1,int f2,int f3,int f4,int t1,int t2,int t3,int t4,int m)
facenum=facen;
faces[0]=f1;
faces[1]=f2;
faces[2]=f3;
faces[3]=f4;
texcoord[0]=t1;
texcoord[1]=t2;
texcoord[2]=t3;
texcoord[3]=t4;
mat=m;
four=true;
//nothing to explain here
material::material(const char* na,float al,float n,float ni2,float* d,float* a,float* s,int i,int t)
name=na;
alpha=al;
ni=ni2;
ns=n;
dif[0]=d[0];
dif[1]=d[1];
dif[2]=d[2];
amb[0]=a[0];
amb[1]=a[1];
amb[2]=a[2];
spec[0]=s[0];
spec[1]=s[1];
spec[2]=s[2];
illum=i;
texture=t;
//nothing to explain here
texcoord::texcoord(float a,float b)
u=a;
v=b;
int objloader::load(const char* filename)
std::ifstream in(filename); //open the model file
if(!in.is_open())
std::cout << "Nor oepened" << std::endl; //if it's not opened then error message, and return with -1
return -1;
char buf[256]; //temp buffer
int curmat=0; //the current (default) material is 0, it's used, when we read the faces
while(!in.eof())
in.getline(buf,256); //while we are not in the end of the file, read everything as a string to the coord vector
coord.push_back(new std::string(buf));
for(int i=0;i<coord.size();i++) //and then go through all line and decide what kind of line it is
if((*coord[i])[0]=='#') //if it's a comment
continue; //we don't have to do anything with it
else if((*coord[i])[0]=='v' && (*coord[i])[1]==' ') //if a vertex
float tmpx,tmpy,tmpz;
sscanf(coord[i]->c_str(),"v %f %f %f",&tmpx,&tmpy,&tmpz); //read the 3 floats, which makes up the vertex
vertex.push_back(new coordinate(tmpx,tmpy,tmpz)); //and put it in the vertex vector
else if((*coord[i])[0]=='v' && (*coord[i])[1]=='n') //if it's a normal vector
float tmpx,tmpy,tmpz;
sscanf(coord[i]->c_str(),"vn %f %f %f",&tmpx,&tmpy,&tmpz);
normals.push_back(new coordinate(tmpx,tmpy,tmpz)); //basically do the same
isnormals=true;
else if((*coord[i])[0]=='f') //if it's a face
int a,b,c,d,e;
if(count(coord[i]->begin(),coord[i]->end(),' ')==4) //if this is a quad
if(coord[i]->find("//")!=std::string::npos) //if it's contain a normal vector, but not contain texture coorinate
sscanf(coord[i]->c_str(),"f %d//%d %d//%d %d//%d %d//%d",&a,&b,&c,&b,&d,&b,&e,&b); //read in this form
faces.push_back(new face(b,a,c,d,e,0,0,0,0,curmat)); //and put to the faces, we don't care about the texture coorinate in this case
//and if there is no material, it doesn't matter, what is curmat
else if(coord[i]->find("/")!=std::string::npos) //if we have texture coorinate and normal vectors
int t[4]; //texture coorinates
//read in this form, and put to the end of the vector
sscanf(coord[i]->c_str(),"f %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d",&a,&t[0],&b,&c,&t[1],&b,&d,&t[2],&b,&e,&t[3],&b);
faces.push_back(new face(b,a,c,d,e,t[0],t[1],t[2],t[3],curmat));
else
//else we don't have normal vectors nor texture coorinate
sscanf(coord[i]->c_str(),"f %d %d %d %d",&a,&b,&c,&d);
faces.push_back(new face(-1,a,b,c,d,0,0,0,0,curmat));
else //if it's a triangle
//do the same, except we use one less vertex/texture coorinate/face number
if(coord[i]->find("//")!=std::string::npos)
sscanf(coord[i]->c_str(),"f %d//%d %d//%d %d//%d",&a,&b,&c,&b,&d,&b);
faces.push_back(new face(b,a,c,d,0,0,0,curmat));
else if(coord[i]->find("/")!=std::string::npos)
int t[3];
sscanf(coord[i]->c_str(),"f %d/%d/%d %d/%d/%d %d/%d/%d",&a,&t[0],&b,&c,&t[1],&b,&d,&t[2],&b);
faces.push_back(new face(b,a,c,d,t[0],t[1],t[2],curmat));
else
sscanf(coord[i]->c_str(),"f %d %d %d",&a,&b,&c);
faces.push_back(new face(-1,a,b,c,0,0,0,curmat));
else if((*coord[i])[0]=='u' && (*coord[i])[1]=='s' && (*coord[i])[2]=='e') //use material material_name
char tmp[200];
sscanf(coord[i]->c_str(),"usemtl %s",tmp); //read the name of the material to tmp
for(int i=0;i<materials.size();i++) //go through all of the materials
if(strcmp(materials[i]->name.c_str(),tmp)==0) //and compare the tmp with the name of the material
curmat=i; //if it's equal then set the current material to that
break;
else if((*coord[i])[0]=='m' && (*coord[i])[1]=='t' && (*coord[i])[2]=='l' && (*coord[i])[3]=='l') //material library, a file, which contain
//all of the materials
char filen[200];
sscanf(coord[i]->c_str(),"mtllib %s",filen); //read the filename
std::ifstream mtlin(filen); //open the file
if(!mtlin.is_open()) //if not opened error message, clean all memory, return with -1
std::cout << "connot open the material file" << std::endl;
clean();
return -1;
ismaterial=true; //we use materials
std::vector<std::string> tmp;//contain all of the line of the file
char c[200];
while(!mtlin.eof())
mtlin.getline(c,200); //read all lines to tmp
tmp.push_back(c);
char name[200]; //name of the material
char filename[200]; //filename of the texture
float amb[3],dif[3],spec[3],alpha,ns,ni; //colors, shininess, and something else
int illum;
unsigned int texture;
bool ismat=false; //do we already have a material read in to these variables?
strcpy(filename,"\0"); //set filename to nullbyte character
for(int i=0;i<tmp.size();i++) //go through all lines of the mtllib file
if(tmp[i][0]=='#') //we don't care about comments
continue;
if(tmp[i][0]=='n' && tmp[i][1]=='e' && tmp[i][2]=='w') //new material
if(ismat) //if we have a material
if(strcmp(filename,"\0")!=0) //if we have a texture
materials.push_back(new material(name,alpha,ns,ni,dif,amb,spec,illum,texture)); //push back
strcpy(filename,"\0");
else
materials.push_back(new material(name,alpha,ns,ni,dif,amb,spec,illum,-1)); //push back, but use -1 to texture
ismat=false; //we start from a fresh material
sscanf(tmp[i].c_str(),"newmtl %s",name); //read in the name
else if(tmp[i][0]=='N' && tmp[i][1]=='s') //the shininess
sscanf(tmp[i].c_str(),"Ns %f",&ns);
ismat=true;
else if(tmp[i][0]=='K' && tmp[i][1]=='a') //the ambient
sscanf(tmp[i].c_str(),"Ka %f %f %f",&amb[0],&amb[1],&amb[2]);
ismat=true;
else if(tmp[i][0]=='K' && tmp[i][1]=='d') //the diffuse
sscanf(tmp[i].c_str(),"Kd %f %f %f",&dif[0],&dif[1],&dif[2]);
ismat=true;
else if(tmp[i][0]=='K' && tmp[i][1]=='s') //the specular
sscanf(tmp[i].c_str(),"Ks %f %f %f",&spec[0],&spec[1],&spec[2]);
ismat=true;
else if(tmp[i][0]=='N' && tmp[i][1]=='i') //the I don't know what is this
sscanf(tmp[i].c_str(),"Ni %f",&ni);
ismat=true;
else if(tmp[i][0]=='d' && tmp[i][1]==' ') //the alpha
sscanf(tmp[i].c_str(),"d %f",&alpha);
ismat=true;
else if(tmp[i][0]=='i' && tmp[i][1]=='l') //the illum (don't ask)
sscanf(tmp[i].c_str(),"illum %d",&illum);
ismat=true;
else if(tmp[i][0]=='m' && tmp[i][1]=='a') //and the texture
sscanf(tmp[i].c_str(),"map_Kd %s",filename);
texture=loadTexture(filename); //read the filename, and use the loadTexture function to load it, and get the id.
ismat=true;
if(ismat) //there is no newmat after the last newmat, so we have to put the last material 'manually'
if(strcmp(filename,"\0")!=0)
materials.push_back(new material(name,alpha,ns,ni,dif,amb,spec,illum,texture));
else
materials.push_back(new material(name,alpha,ns,ni,dif,amb,spec,illum,-1));
else if((*coord[i])[0]=='v' && (*coord[i])[1]=='t') //back to the obj file, texture coorinate
float u,v;
sscanf(coord[i]->c_str(),"vt %f %f",&u,&v); //read the uv coordinate
texturecoordinate.push_back(new texcoord(u,1-v));
istexture=true;
if(materials.size()==0) //if some reason the material file doesn't contain any material, we don't have material
ismaterial=false;
else //else we have
ismaterial=true;
std::cout << vertex.size() << " " << normals.size() << " " << faces.size() << " " << materials.size() << std::endl; //test purposes
//draw
int num;
num=glGenLists(1);
glNewList(num,GL_COMPILE);
int last=-1; //the last material (default -1, which doesn't exist, so we use the first material)
for(int i=0;i<faces.size();i++) //go throught all faces
if(last!=faces[i]->mat && ismaterial)
//set all of the material property
float diffuse[]=materials[faces[i]->mat]->dif[0],materials[faces[i]->mat]->dif[1],materials[faces[i]->mat]->dif[2],1.0;
float ambient[]=materials[faces[i]->mat]->amb[0],materials[faces[i]->mat]->amb[1],materials[faces[i]->mat]->amb[2],1.0;
float specular[]=materials[faces[i]->mat]->spec[0],materials[faces[i]->mat]->spec[1],materials[faces[i]->mat]->spec[2],1.0;
glMaterialfv(GL_FRONT,GL_DIFFUSE,diffuse);
glMaterialfv(GL_FRONT,GL_AMBIENT,ambient);
glMaterialfv(GL_FRONT,GL_SPECULAR,specular);
glMaterialf(GL_FRONT,GL_SHININESS,materials[faces[i]->mat]->ns);
last=faces[i]->mat; //set the current to last
if(materials[faces[i]->mat]->texture==-1)
glDisable(GL_TEXTURE_2D);
else
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,materials[faces[i]->mat]->texture); //and use it
if(faces[i]->four) //if quad
glBegin(GL_QUADS);
if(isnormals) //if there are normals
glNormal3f(normals[faces[i]->facenum-1]->x,normals[faces[i]->facenum-1]->y,normals[faces[i]->facenum-1]->z); //use them
if(istexture && materials[faces[i]->mat]->texture!=-1) //if there are textures
glTexCoord2f(texturecoordinate[faces[i]->texcoord[0]-1]->u,texturecoordinate[faces[i]->texcoord[0]-1]->v); //set the texture coorinate
glVertex3f(vertex[faces[i]->faces[0]-1]->x,vertex[faces[i]->faces[0]-1]->y,vertex[faces[i]->faces[0]-1]->z);
if(istexture && materials[faces[i]->mat]->texture!=-1)
glTexCoord2f(texturecoordinate[faces[i]->texcoord[1]-1]->u,texturecoordinate[faces[i]->texcoord[1]-1]->v);
glVertex3f(vertex[faces[i]->faces[1]-1]->x,vertex[faces[i]->faces[1]-1]->y,vertex[faces[i]->faces[1]-1]->z);
if(istexture && materials[faces[i]->mat]->texture!=-1)
glTexCoord2f(texturecoordinate[faces[i]->texcoord[2]-1]->u,texturecoordinate[faces[i]->texcoord[2]-1]->v);
glVertex3f(vertex[faces[i]->faces[2]-1]->x,vertex[faces[i]->faces[2]-1]->y,vertex[faces[i]->faces[2]-1]->z);
if(istexture && materials[faces[i]->mat]->texture!=-1)
glTexCoord2f(texturecoordinate[faces[i]->texcoord[3]-1]->u,texturecoordinate[faces[i]->texcoord[3]-1]->v);
glVertex3f(vertex[faces[i]->faces[3]-1]->x,vertex[faces[i]->faces[3]-1]->y,vertex[faces[i]->faces[3]-1]->z);
glEnd();
else
glBegin(GL_TRIANGLES);
if(isnormals) //if there are normals
glNormal3f(normals[faces[i]->facenum-1]->x,normals[faces[i]->facenum-1]->y,normals[faces[i]->facenum-1]->z);
if(istexture && materials[faces[i]->mat]->texture!=-1)
glTexCoord2f(texturecoordinate[faces[i]->texcoord[0]-1]->u,texturecoordinate[faces[i]->texcoord[0]-1]->v);
glVertex3f(vertex[faces[i]->faces[0]-1]->x,vertex[faces[i]->faces[0]-1]->y,vertex[faces[i]->faces[0]-1]->z);
if(istexture && materials[faces[i]->mat]->texture!=-1)
glTexCoord2f(texturecoordinate[faces[i]->texcoord[1]-1]->u,texturecoordinate[faces[i]->texcoord[1]-1]->v);
glVertex3f(vertex[faces[i]->faces[1]-1]->x,vertex[faces[i]->faces[1]-1]->y,vertex[faces[i]->faces[1]-1]->z);
if(istexture && materials[faces[i]->mat]->texture!=-1)
glTexCoord2f(texturecoordinate[faces[i]->texcoord[2]-1]->u,texturecoordinate[faces[i]->texcoord[2]-1]->v);
glVertex3f(vertex[faces[i]->faces[2]-1]->x,vertex[faces[i]->faces[2]-1]->y,vertex[faces[i]->faces[2]-1]->z);
glEnd();
glEndList();
clean();
lists.push_back(num);
return num;
void objloader::clean()
//delete all the dynamically allocated memory
for(int i=0;i<coord.size();i++)
delete coord[i];
for(int i=0;i<faces.size();i++)
delete faces[i];
for(int i=0;i<normals.size();i++)
delete normals[i];
for(int i=0;i<vertex.size();i++)
delete vertex[i];
for(int i=0;i<materials.size();i++)
delete materials[i];
for(int i=0;i<texturecoordinate.size();i++)
delete texturecoordinate[i];
//and all elements from the vector
coord.clear();
faces.clear();
normals.clear();
vertex.clear();
materials.clear();
texturecoordinate.clear();
objloader::~objloader()
//delete lists and textures
for(std::vector<unsigned int>::const_iterator it=texture.begin();it!=texture.end();it++)
glDeleteTextures(1,&(*it));
for(std::vector<unsigned int>::const_iterator it=lists.begin();it!=lists.end();it++)
glDeleteLists(*it,1);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
unsigned int objloader::loadTexture(const char* filename)
unsigned int num;
int mode;
glGenTextures(1,&num);
SDL_Surface* img=IMG_Load(filename);
if(img==NULL)
std::cout << "Image error" << std::endl;
if (img->format->BytesPerPixel == 3)
mode = GL_RGB;
else if (img->format->BytesPerPixel == 4)
mode = GL_RGBA;
else
SDL_FreeSurface(img);
return 0;
glBindTexture(GL_TEXTURE_2D,num);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTexImage2D(GL_TEXTURE_2D,0,mode,img->w,img->h,0,mode,GL_UNSIGNED_BYTE,img->pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
return num;
texture.push_back(num);
objloader::objloader()
ismaterial=false;
isnormals=false;
istexture=false;
test.obj
# Blender v2.70 (sub 0) OBJ File: ''
# www.blender.org
mtllib test.mtl
o Cube
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -0.999999
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 1.000000 0.000000 0.000000
vn -0.000000 -0.000000 1.000000
vn -1.000000 -0.000000 -0.000000
vn 0.000000 0.000000 -1.000000
usemtl Material
s off
f 1//1 2//1 3//1 4//1
f 5//2 8//2 7//2 6//2
f 1//3 5//3 6//3 2//3
f 2//4 6//4 7//4 3//4
f 3//5 7//5 8//5 4//5
f 5//6 1//6 4//6 8//6
test.mtl
# Blender MTL File: 'None'
# Material Count: 1
newmtl Material
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2
map_Kd a.png
【问题讨论】:
【参考方案1】:OBJ 文件中缺少纹理坐标。
istexture
很可能在加载后未为此 obj 文件设置。那里没有纹理 (vt) 坐标。在 (f) 定义中也没有设置。
f v1/t1/n1 v2/t2/n2 v3/t3/n3
文件中的位置 tX 不存在,因此纹理的坐标不是每个顶点都设置的,四边形的颜色是 (0,0 ) 纹理坐标。
【讨论】:
以上是关于从 obj 文件加载时显示单色而不是纹理的主要内容,如果未能解决你的问题,请参考以下文章
ARKit学习之SCNGeometrySource加顶点法线纹理及索引时贴图不正确
来自 Blender 的 PNG 纹理文件,而不是 mtl 文件
如何将 UV 纹理从搅拌机加载到 opengl android java