Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
66d43a1f0This file is pinned to the selected release. Download the original to open it in your design tool.
#include "model.h"
#include <string.h> // memcpy
#include <cmath>
#include <fstream>
#include <iostream>
#include <sstream>
#include "Bullet3Common/b3Logging.h"
namespace TinyRender
{
Model::Model(const char *filename) : verts_(), faces_(), norms_(), uv_(), diffusemap_(), normalmap_(), specularmap_()
{
std::ifstream in;
in.open(filename, std::ifstream::in);
if (in.fail()) return;
std::string line;
while (!in.eof())
{
std::getline(in, line);
std::istringstream iss(line.c_str());
char trash;
if (!line.compare(0, 2, "v "))
{
iss >> trash;
Vec3f v;
for (int i = 0; i < 3; i++) iss >> v[i];
verts_.push_back(v);
}
else if (!line.compare(0, 3, "vn "))
{
iss >> trash >> trash;
Vec3f n;
for (int i = 0; i < 3; i++) iss >> n[i];
norms_.push_back(n);
}
else if (!line.compare(0, 3, "vt "))
{
iss >> trash >> trash;
Vec2f uv;
for (int i = 0; i < 2; i++) iss >> uv[i];
uv_.push_back(uv);
}
else if (!line.compare(0, 2, "f "))
{
std::vector<Vec3i> f;
Vec3i tmp;
iss >> trash;
while (iss >> tmp[0] >> trash >> tmp[1] >> trash >> tmp[2])
{
for (int i = 0; i < 3; i++) tmp[i]--; // in wavefront obj all indices start at 1, not zero
f.push_back(tmp);
}
faces_.push_back(f);
}
}
std::cerr << "# v# " << verts_.size() << " f# " << faces_.size() << " vt# " << uv_.size() << " vn# " << norms_.size() << std::endl;
load_texture(filename, "_diffuse.tga", diffusemap_);
load_texture(filename, "_nm_tangent.tga", normalmap_);
load_texture(filename, "_spec.tga", specularmap_);
}
Model::Model() : verts_(), faces_(), norms_(), uv_(), diffusemap_(), normalmap_(), specularmap_()
{
}
void Model::setDiffuseTextureFromData(unsigned char *textureImage, int textureWidth, int textureHeight)
{
{
B3_PROFILE("new TGAImage");
diffusemap_ = TGAImage(textureWidth, textureHeight, TGAImage::RGB);
}
TGAColor color;
color.bgra[3] = 255;
color.bytespp = 3;
{
B3_PROFILE("copy texels");
memcpy(diffusemap_.buffer(), textureImage, textureHeight * textureWidth * 3);
}
{
B3_PROFILE("flip_vertically");
diffusemap_.flip_vertically();
}
}
void Model::loadDiffuseTexture(const char *relativeFileName)
{
diffusemap_.read_tga_file(relativeFileName);
}
void Model::reserveMemory(int numVertices, int numIndices)
{
verts_.reserve(numVertices);
norms_.reserve(numVertices);
uv_.reserve(numVertices);
faces_.reserve(numIndices);
}
void Model::addVertex(float x, float y, float z, float normalX, float normalY, float normalZ, float u, float v)
{
verts_.push_back(Vec3f(x, y, z));
norms_.push_back(Vec3f(normalX, normalY, normalZ));
uv_.push_back(Vec2f(u, v));
}
void Model::addTriangle(int vertexposIndex0, int normalIndex0, int uvIndex0,
int vertexposIndex1, int normalIndex1, int uvIndex1,
int vertexposIndex2, int normalIndex2, int uvIndex2)
{
std::vector<Vec3i> f;
f.push_back(Vec3i(vertexposIndex0, normalIndex0, uvIndex0));
f.push_back(Vec3i(vertexposIndex1, normalIndex1, uvIndex1));
f.push_back(Vec3i(vertexposIndex2, normalIndex2, uvIndex2));
faces_.push_back(f);
}
Model::~Model() {}
int Model::nverts()
{
return (int)verts_.size();
}
int Model::nfaces()
{
return (int)faces_.size();
}
std::vector<int> Model::face(int idx)
{
std::vector<int> face;
face.reserve((int)faces_[idx].size());
for (int i = 0; i < (int)faces_[idx].size(); i++)
face.push_back(faces_[idx][i][0]);
return face;
}
Vec3f Model::vert(int i)
{
return verts_[i];
}
Vec3f Model::vert(int iface, int nthvert)
{
return verts_[faces_[iface][nthvert][0]];
}
void Model::load_texture(std::string filename, const char *suffix, TGAImage &img)
{
std::string texfile(filename);
size_t dot = texfile.find_last_of('.');
if (dot != std::string::npos)
{
texfile = texfile.substr(0, dot) + std::string(suffix);
std::cerr << "texture file " << texfile << " loading " << (img.read_tga_file(texfile.c_str()) ? "ok" : "failed") << std::endl;
img.flip_vertically();
}
}
TGAColor Model::diffuse(Vec2f uvf)
{
if (diffusemap_.get_width() && diffusemap_.get_height())
{
double val;
// bool repeat = true;
// if (repeat)
{
uvf[0] = std::modf(uvf[0], &val);
if (uvf[0] < 0)
{
uvf[0] = uvf[0] + 1;
}
uvf[1] = std::modf(uvf[1], &val);
if (uvf[1] < 0)
{
uvf[1] = uvf[1] + 1;
}
}
Vec2i uv(uvf[0] * diffusemap_.get_width(), uvf[1] * diffusemap_.get_height());
return diffusemap_.get(uv[0], uv[1]);
}
return TGAColor(255, 255, 255, 255);
}
Vec3f Model::normal(Vec2f uvf)
{
Vec2i uv(uvf[0] * normalmap_.get_width(), uvf[1] * normalmap_.get_height());
TGAColor c = normalmap_.get(uv[0], uv[1]);
Vec3f res;
for (int i = 0; i < 3; i++)
res[2 - i] = (float)c[i] / 255.f * 2.f - 1.f;
return res;
}
Vec2f Model::uv(int iface, int nthvert)
{
return uv_[faces_[iface][nthvert][1]];
}
float Model::specular(Vec2f uvf)
{
if (specularmap_.get_width() && specularmap_.get_height())
{
Vec2i uv(uvf[0] * specularmap_.get_width(), uvf[1] * specularmap_.get_height());
return specularmap_.get(uv[0], uv[1])[0] / 1.f;
}
return 2.0;
}
Vec3f Model::normal(int iface, int nthvert)
{
int idx = faces_[iface][nthvert][2];
return norms_[idx].normalize();
}
}