Added the materials system; Any model can have any number of materials with different textures and properties

This commit is contained in:
Grayson Riffe (Laptop) 2021-09-09 22:49:49 -05:00
parent 70318b28fd
commit 39e0c8e808
37 changed files with 1616 additions and 1327 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 KiB

View File

@ -1,46 +0,0 @@
# Blender v2.93.3 OBJ File: ''
# www.blender.org
o Cube_Cube.001
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 1.000000
v -1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
vt 0.380883 0.000961
vt 0.630883 0.250961
vt 0.380883 0.250961
vt 0.875500 0.748039
vt 0.625500 0.498039
vt 0.875500 0.498039
vt 0.625500 0.748039
vt 0.375500 0.498039
vt 0.375500 0.748039
vt 0.125500 0.498039
vt 0.375500 0.248039
vt 0.625500 0.248039
vt 0.625500 0.998039
vt 0.630883 0.000961
vt 0.125500 0.748039
vt 0.375500 0.998039
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
s off
f 2/1/1 3/2/1 1/3/1
f 4/4/2 7/5/2 3/6/2
f 8/7/3 5/8/3 7/5/3
f 6/9/4 1/10/4 5/8/4
f 7/5/5 1/11/5 3/12/5
f 4/13/6 6/9/6 8/7/6
f 2/1/1 4/14/1 3/2/1
f 4/4/2 8/7/2 7/5/2
f 8/7/3 6/9/3 5/8/3
f 6/9/4 2/15/4 1/10/4
f 7/5/5 5/8/5 1/11/5
f 4/13/6 2/16/6 6/9/6

View File

@ -0,0 +1,14 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl Material.001
Ns 750.283502
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Kd diff.png
map_Ks spec.png

View File

@ -0,0 +1,46 @@
# Blender v2.93.3 OBJ File: ''
# www.blender.org
mtllib spec.mtl
o Cube_Cube.001
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 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vt -2.000000 -1.000000
vt -1.000000 0.000000
vt -2.000000 0.000000
vt -1.000000 -1.000000
vt 0.000000 0.000000
vt 0.000000 -1.000000
vt 1.000000 0.000000
vt 1.000000 -1.000000
vt 2.000000 -0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 -2.000000
vt 2.000000 -1.000000
vt 1.000000 -2.000000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
usemtl Material.001
s off
f 2/1/1 3/2/1 1/3/1
f 4/4/2 7/5/2 3/2/2
f 8/6/3 5/7/3 7/5/3
f 6/8/4 1/9/4 5/7/4
f 7/5/5 1/10/5 3/11/5
f 4/12/6 6/8/6 8/6/6
f 2/1/1 4/4/1 3/2/1
f 4/4/2 8/6/2 7/5/2
f 8/6/3 6/8/3 5/7/3
f 6/8/4 2/13/4 1/9/4
f 7/5/5 5/7/5 1/10/5
f 4/12/6 2/14/6 6/8/6

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -0,0 +1,10 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl None
Ns 100
Ka 0.8 0.8 0.8
Kd 0.8 0.8 0.8
Ks 0.8 0.8 0.8
d 1
illum 2

View File

@ -1,5 +1,6 @@
# Blender v2.93.3 OBJ File: ''
# www.blender.org
mtllib cone.mtl
o Cone
v 0.000000 -1.000000 -1.000000
v 0.195090 -1.000000 -0.980785
@ -133,6 +134,7 @@ vn -0.4969 0.4472 -0.7437
vn -0.3423 0.4472 -0.8263
vn 0.0000 -1.0000 0.0000
vn -0.1745 0.4472 -0.8772
usemtl None
s 1
f 1/1/1 33/2/2 2/3/3
f 2/3/3 33/2/2 3/4/4

View File

@ -0,0 +1,10 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl None
Ns 100
Ka 0.8 0.8 0.8
Kd 0.8 0.8 0.8
Ks 0.8 0.8 0.8
d 1
illum 2

View File

@ -1,6 +1,7 @@
# Blender v2.93.3 OBJ File: ''
# www.blender.org
o Cube_Cube.002
mtllib cube.mtl
o Cube_Cube.001
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
@ -29,6 +30,7 @@ vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
usemtl None
s off
f 2/1/1 3/2/1 1/3/1
f 4/4/2 7/5/2 3/2/2

View File

@ -0,0 +1,10 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl None
Ns 100
Ka 0.8 0.8 0.8
Kd 0.8 0.8 0.8
Ks 0.8 0.8 0.8
d 1
illum 2

View File

@ -1,6 +1,7 @@
# Blender v2.93.3 OBJ File: ''
# www.blender.org
o Cylinder
mtllib cylinder.mtl
o Cylinder_Cylinder.001
v 0.000000 -1.000000 -1.000000
v 0.000000 1.000000 -1.000000
v 0.195090 -1.000000 -0.980785
@ -229,6 +230,7 @@ vn -0.3827 0.0000 -0.9239
vn 0.0000 1.0000 -0.0000
vn -0.1951 0.0000 -0.9808
vn 0.0000 -1.0000 0.0000
usemtl None
s 1
f 2/1/1 3/2/2 1/3/1
f 4/4/2 5/5/3 3/2/2

View File

@ -0,0 +1,10 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl None
Ns 100
Ka 0.8 0.8 0.8
Kd 0.8 0.8 0.8
Ks 0.8 0.8 0.8
d 1
illum 2

View File

@ -1,5 +1,6 @@
# Blender v2.93.3 OBJ File: ''
# www.blender.org
mtllib plane.mtl
o Plane
v -1.000000 0.000000 1.000000
v 1.000000 0.000000 1.000000
@ -10,6 +11,7 @@ vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 1.000000
vn 0.0000 1.0000 0.0000
usemtl None
s off
f 2/1/1 3/2/1 1/3/1
f 2/1/1 4/4/1 3/2/1

View File

@ -0,0 +1,10 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl None
Ns 100
Ka 0.8 0.8 0.8
Kd 0.8 0.8 0.8
Ks 0.8 0.8 0.8
d 1
illum 2

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl None
Ns 100
Ka 0.8 0.8 0.8
Kd 0.8 0.8 0.8
Ks 0.8 0.8 0.8
d 1
illum 2

View File

@ -1,5 +1,6 @@
# Blender v2.93.3 OBJ File: ''
# www.blender.org
mtllib torus.mtl
o Torus
v 1.250000 0.000000 0.000000
v 1.216506 0.125000 0.000000
@ -1742,6 +1743,7 @@ vn 0.5036 -0.8614 0.0663
vn 0.8612 -0.4954 0.1134
vn -0.8559 0.5047 -0.1127
vn -0.4876 -0.8707 -0.0642
usemtl None
s 1
f 13/1/1 2/2/2 1/3/3
f 2/2/2 15/4/4 3/5/5

View File

@ -9,8 +9,12 @@ struct Camera {
};
struct Material {
float shininess;
//Do I want a specular color here?
bool hasDiffuseTex;
sampler2D diffuseTexture;
vec3 diffuseColor;
bool hasSpecTex;
sampler2D specularTexture;
float specPower;
};
struct Light {
@ -21,7 +25,6 @@ struct Light {
float strength;
};
uniform sampler2D modelTexture;
uniform Camera camera;
uniform Material material;
uniform Light light[100];
@ -30,13 +33,21 @@ uniform int numberOfLights;
out vec4 outColor;
void main() {
vec4 texColor = texture(modelTexture, texCoord);
vec3 color = vec3(0.0);
vec3 matDiff;
if (material.hasDiffuseTex)
matDiff = texture(material.diffuseTexture, texCoord).rgb;
else
matDiff = material.diffuseColor;
vec3 matSpec = vec3(1.0);
if(material.hasSpecTex)
matSpec = texture(material.specularTexture, texCoord).rgb;
for (int i = 0; i < numberOfLights; i++) {
float ambientStrength = 0.2f;
vec3 ambient = ambientStrength * texColor.rgb;
vec3 ambient = ambientStrength * matDiff;
if (i == numberOfLights - 1 && numberOfLights == 1) {
color += ambient;
break;
@ -46,12 +57,12 @@ void main() {
vec3 lightDir = normalize(-light[i].pos);
vec3 norm = normalize(normals);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light[i].color * (diff * texColor.rgb) * light[i].strength;
vec3 diffuse = light[i].color * (diff * matDiff) * (light[i].strength / 2.0f);
vec3 viewDir = normalize(camera.pos - fragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess * 32.0f);
vec3 specular = light[i].color * spec * light[i].strength;
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.specPower);
vec3 specular = light[i].color * spec * matSpec * (light[i].strength / 2.0f);
color += (ambient + diffuse + specular);
continue;
@ -60,12 +71,12 @@ void main() {
vec3 lightDir = normalize(light[i].pos - fragPos);
vec3 norm = normalize(normals);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light[i].color * (diff * texColor.rgb) * light[i].strength;
vec3 diffuse = light[i].color * (diff * matDiff) * (light[i].strength / 2.0f);
vec3 viewDir = normalize(camera.pos - fragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess * 32.0f);
vec3 specular = light[i].color * spec * (light[i].strength) / 8.0f;
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.specPower);
vec3 specular = light[i].color * spec * matSpec * (light[i].strength / 2.0f);
float length = length(light[i].pos - fragPos);
float att = clamp(10.0 / length, 0.0, 1.0) * light[i].strength;
@ -74,5 +85,5 @@ void main() {
continue;
}
}
outColor = vec4(color, texColor.a);
outColor = vec4(color, 1.0);
}

View File

@ -64,6 +64,22 @@ void writeFile(const std::string& filename, const std::string& in, bool encrypte
out.close();
}
void getNeededImages(std::string mtl, std::set<std::string>& set) {
while (mtl.size()) {
unsigned int pos = mtl.find("map_");
if (pos == std::string::npos)
break;
mtl = mtl.substr(pos + 7);
std::stringstream ss(mtl);
std::string temp;
ss >> temp;
unsigned int pos2 = temp.find_last_of("/\\");
if (pos2 != std::string::npos)
temp = temp.substr(pos2 + 1);
set.insert(temp);
}
}
int main(int argc, char* argv[]) {
Log("Starting up");
@ -84,6 +100,7 @@ int main(int argc, char* argv[]) {
continue;
std::string filename = currDir.path().filename().string().append(".nfpack");
Log("Creating pack \"" + filename + (std::string)"\"");
std::string currFileExtension;
std::string currFileContents;
std::stringstream out;
unsigned int fileCount = 0;
@ -91,11 +108,46 @@ int main(int argc, char* argv[]) {
if (curr.is_directory())
continue;
std::filesystem::path relative = std::filesystem::relative(curr, currDir);
if (extensions.find(relative.extension().string().substr(1)) == extensions.end())
currFileExtension = relative.extension().string().substr(1);
if (currFileExtension == "mtl")
continue;
if (extensions.find(currFileExtension) == extensions.end())
Error("File \"" + relative.string() + (std::string)"\" is not of supported type!");
Log("Current file: " + relative.string());
currFileContents = readFile(curr.path().string());
if (currFileExtension == "obj") {
std::filesystem::path mtlPath;
for (const auto& curr2 : std::filesystem::recursive_directory_iterator(curr.path().parent_path())) {
if (curr2.is_directory())
continue;
if (curr2.path().extension() != ".mtl")
continue;
std::string mtlFile = relative.filename().string().substr(0, relative.filename().string().size() - 4) + (std::string)".mtl";
if (curr2.path().filename().string() == mtlFile) {
mtlPath = curr2.path();
break;
}
}
if (mtlPath.empty())
Error("No mtl file found for " + relative.filename().string() + (std::string)"!");
Log("Found mtl file for " + relative.filename().string());
std::set<std::string> neededImages;
std::string mtlContents = readFile(mtlPath.string());
getNeededImages(mtlContents, neededImages);
if (!neededImages.empty()) {
currFileContents.insert(0, "\n");
for(std::string curr : neededImages) {
currFileContents.insert(0, curr);
currFileContents.insert(0, " ");
}
currFileContents = currFileContents.substr(1);
}
else {
currFileContents.insert(0, "none\n");
}
currFileContents += '\n' + mtlContents;
}
if (out.rdbuf()->in_avail() != 0)
out << "\n";
out << "#NFASSET " + curr.path().filename().string();

View File

@ -1,5 +1,7 @@
#include "Assets.h"
#include <sstream>
#include "Application.h"
#include "Model.h"
#include "Utility.h"
@ -9,11 +11,11 @@ namespace nf {
delete[] data;
}
AModel::~AModel() {
ATexture::~ATexture() {
}
ATexture::~ATexture() {
AModel::~AModel() {
}
@ -41,6 +43,7 @@ namespace nf {
void AssetPack::load(const char* packName) {
std::string path = "assets/" + (std::string)packName;
std::string packContents = readFile(path);
std::string packContentsOBJ = packContents;
std::unordered_map<std::string, ACubemap*> cubemaps;
unsigned int cubemapCount = 0;
while (packContents.size()) {
@ -63,18 +66,8 @@ namespace nf {
}
size_t assetSize = assetContents.size();
if (extension == "obj") {
AModel* geometry = new AModel;
geometry->data = new char[assetSize + 1];
std::memcpy(geometry->data, &assetContents[0], assetSize);
geometry->data[assetSize] = '\0';
geometry->alreadyLoaded = false;
geometry->loadedModel = nullptr;
if (packName == "base.nfpack")
geometry->isBaseAsset = true;
m_assets[assetName] = geometry;
if (extension == "obj")
continue;
}
if (extension == "png") {
if (assetName.find("_cmfront") != std::string::npos || assetName.find("_cmback") != std::string::npos || assetName.find("_cmtop") != std::string::npos || assetName.find("_cmbottom") != std::string::npos || assetName.find("_cmleft") != std::string::npos || assetName.find("_cmright") != std::string::npos) {
std::string cmName = assetName.substr(0, assetName.find('_'));
@ -156,6 +149,48 @@ namespace nf {
}
if (cubemapCount % 6 != 0)
Error("Could not find full cubemap in pack \"" + (std::string)packName + (std::string)"\"!");
while (packContentsOBJ.size()) {
unsigned int startingPos = packContentsOBJ.find_first_of("#NFASSET ") + 9;
packContentsOBJ = packContentsOBJ.substr(9);
unsigned int endAssetNamePos = packContentsOBJ.find_first_of('\n');
std::string assetName = packContentsOBJ.substr(0, endAssetNamePos);
packContentsOBJ = packContentsOBJ.substr(endAssetNamePos + 1);
unsigned int extensionPos = assetName.find_first_of('.');
std::string extension = assetName.substr(extensionPos + 1);
std::string assetContents;
unsigned int nextAssetPos = packContentsOBJ.find("#NFASSET ");
if (nextAssetPos != std::string::npos) {
assetContents = packContentsOBJ.substr(0, nextAssetPos - 1);
packContentsOBJ = packContentsOBJ.substr(nextAssetPos);
}
else {
assetContents = packContentsOBJ;
packContentsOBJ = "";
}
size_t assetSize = assetContents.size();
if (extension == "obj") {
AModel* model = new AModel;
std::string textures = assetContents.substr(0, assetContents.find("\n"));
if (textures != "none") {
std::stringstream ss(textures);
std::string curr;
while (ss >> curr) {
model->neededTextures[curr] = (ATexture*)m_assets[curr];
}
}
assetContents = assetContents.substr(assetContents.find("\n") + 1);
model->data = new char[assetSize + 1];
std::memcpy(model->data, &assetContents[0], assetSize);
model->data[assetSize] = '\0';
if (packName == "base.nfpack")
model->isBaseAsset = true;
m_assets[assetName] = model;
continue;
}
}
if (packName != "base.nfpack")
Application::getApp()->getCurrentState()->m_nfObjects.push_back(this);
}

View File

@ -9,7 +9,7 @@ namespace nf {
Log("Intro onEnter!");
m_logoTex.create(BaseAssets::logo, Vec2(0.0, 0.0));
m_logoTex.centered(true, true);
m_text.create("(C) Grayson Riffe 2021", Vec2(0.01, 0.025), Vec3(0.8));
m_text.create("(c) Grayson Riffe 2021", Vec2(0.01, 0.025), Vec3(0.8));
m_text.setScale(0.6);
m_start = std::chrono::steady_clock::now();
}

View File

@ -17,26 +17,14 @@ namespace nf {
}
void Entity::create(Asset* modelAsset, Asset* textureAsset) {
void Entity::create(Asset* modelAsset) {
m_constructed = true;
AModel& model = *(AModel*)modelAsset;
//TODO: Change this when doing materials
if (model.alreadyLoaded && textureAsset == nullptr) {
if (model.alreadyLoaded) {
m_model = model.loadedModel;
}
else {
if (!textureAsset)
Error("No texture given to Entity create function on new model load!");
ATexture& texture = *(ATexture*)textureAsset;
std::string obj = model.data;
m_model = new Model;
std::vector<float> vb;
std::vector<unsigned int> ib;
size_t ibCount = 0;
std::vector<float> tc;
std::vector<float> vn;
parseOBJ(obj, vb, ib, ibCount, tc, vn);
m_model->create(&vb[0], vb.size() * sizeof(float), &ib[0], ibCount, &vn[0], vn.size() * sizeof(float), &tc[0], tc.size() * sizeof(float), &texture);
m_model = new Model(&model);
model.alreadyLoaded = true;
model.loadedModel = m_model;
}
@ -76,10 +64,10 @@ namespace nf {
m_scale = scale;
}
void Entity::bind(Shader* shader) {
m_model->bind();
void Entity::render(Shader* shader) {
shader->bind();
setModelMatrix(shader);
m_model->render(shader);
}
Model* Entity::getModel() const {
@ -101,15 +89,9 @@ namespace nf {
if(m_model && !m_model->isBaseAsset())
delete m_model;
m_model = nullptr;
m_position.x = 0.0;
m_position.y = 0.0;
m_position.z = 0.0;
m_rotation.x = 0.0;
m_rotation.y = 0.0;
m_rotation.z = 0.0;
m_scale.x = 1.0;
m_scale.y = 1.0;
m_scale.z = 1.0;
m_position = Vec3(0.0);
m_rotation = Vec3(0.0);
m_scale = Vec3(1.0);
}
Entity::~Entity() {

View File

@ -12,12 +12,12 @@ namespace nf {
}
void Light::create(const Vec3& position, const Vec3& color, float strength, Type type) {
void Light::create(const Vec3& position, const Vec3& color, double strength, Type type) {
m_constructed = true;
m_position = position;
m_color = color;
m_type = type;
m_strength = strength;
m_strength = (float)strength;
Application::getApp()->getCurrentState()->m_nfObjects.push_back(this);
}

View File

@ -1,49 +1,284 @@
#include "Model.h"
#include <map>
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "GL/glew.h"
#include "Utility.h"
#include "Texture.h"
#include "Shader.h"
#include "Utility.h"
namespace nf {
Model::Model() :
m_base(false),
m_texture(nullptr)
{
}
void Model::create(const void* vertexBufferData, const size_t vertexBufferSize, const void* indexBufferData, size_t indexBufferCount, const void* normalsBufferData, size_t normalsBufferSize, const void* textureCoordinatesBufferData, size_t textureCoordinatesBufferSize, ATexture* texture) {
m_vao = new VertexArray;
m_vao->addBuffer(vertexBufferData, vertexBufferSize);
Material::Material(const void* vb, const size_t vbSize, const void* tc, const size_t tcSize, const void* vn, const size_t vnSize, const void* ib, const unsigned int ibCount, ATexture* diffTex, Vec3& diffColor, ATexture* specTex, float shininess) {
m_vao = new VertexArray();
m_vao->addBuffer(vb, vbSize);
m_vao->push<float>(3);
m_vao->finishBufferLayout();
m_vao->addBuffer(textureCoordinatesBufferData, textureCoordinatesBufferSize);
m_vao->addBuffer(tc, tcSize);
m_vao->push<float>(2);
m_vao->finishBufferLayout();
m_vao->addBuffer(normalsBufferData, normalsBufferSize);
m_vao->addBuffer(vn, vnSize);
m_vao->push<float>(3);
m_vao->finishBufferLayout();
if (texture->alreadyLoaded) {
m_texture = texture->loadedTexture;
m_ib = new IndexBuffer(ib, ibCount);
if (diffTex) {
m_hasDiffuse = true;
m_diffuseTexture = new Texture(diffTex);
}
else {
m_texture = new Texture;
m_texture->create(texture);
texture->alreadyLoaded = true;
texture->loadedTexture = m_texture;
m_diffColor = diffColor;
if (specTex) {
m_hasSpecular = true;
m_specularTexture = new Texture(specTex);
}
m_ib = new IndexBuffer(indexBufferData, indexBufferCount);
m_shininess = shininess;
}
void Model::bind() {
if (m_vao == nullptr)
Error("Tried to bind uninitialized model!");
void Material::render(Shader* shader) {
m_vao->bind();
if (m_texture)
m_texture->bind();
m_ib->bind();
if (m_hasDiffuse) {
shader->setUniform("material.hasDiffuseTex", true);
m_diffuseTexture->bind();
}
else {
shader->setUniform("material.hasDiffuseTex", false);
glm::vec3 color(m_diffColor.x, m_diffColor.y, m_diffColor.z);
shader->setUniform("material.diffuseColor", color);
}
if (m_hasSpecular) {
shader->setUniform("material.hasSpecTex", true);
m_specularTexture->bind(1);
shader->setUniform("material.specularTexture", 1);
}
else
shader->setUniform("material.hasSpecTex", false);
shader->setUniform("material.specPower", m_shininess);
glDrawElements(GL_TRIANGLES, m_ib->getCount(), GL_UNSIGNED_INT, nullptr);
}
Material::~Material() {
delete m_diffuseTexture;
delete m_specularTexture;
}
Model::Model(AModel* model) :
m_base(false)
{
std::string obj = model->data;
unsigned int startMtlPos = obj.find("newmtl");
if (startMtlPos == std::string::npos)
Error("No materials found in model!");
std::string mtl = obj.substr(startMtlPos);
struct TempMaterial {
std::vector<float> outVB;
std::vector<float> unindexedVB;
std::vector<unsigned int> vbIndices;
std::vector<float> outTC;
std::vector<float> unindexedTC;
std::vector<unsigned int> tcIndices;
std::vector<float> outVN;
std::vector<float> unindexedVN;
std::vector<unsigned int> vnIndices;
std::vector<unsigned int> outIB;
unsigned int ibCount = 0;
std::string diffuseTextureName;
Vec3 diffuseColor;
std::string specularTextureName;
float shininess = 1.0f;
};
std::unordered_map<std::string, TempMaterial*> mats;
std::string currMat;
while (true) {
char line[500];
int result = sscanf_s(mtl.c_str(), "\n%s", line, (unsigned)_countof(line));
if (result == EOF)
break;
if (std::strcmp(line, "newmtl") == 0) {
char matName[100];
sscanf_s(mtl.c_str(), "\nnewmtl %s\n", matName, (unsigned)_countof(matName));
currMat = matName;
mats[currMat] = new TempMaterial;
}
else if (std::strcmp(line, "Kd") == 0) {
float r = 0.0, g = 0.0, b = 0.0;
sscanf_s(mtl.c_str(), "\nKd %f %f %f\n", &r, &g, &b);
mats[currMat]->diffuseColor = Vec3(r, g, b);
}
else if (std::strcmp(line, "map_Kd") == 0) {
char texName[100];
sscanf_s(mtl.c_str(), "\nmap_Kd %s\n", texName, (unsigned)_countof(texName));
mats[currMat]->diffuseTextureName = (std::string)texName;
}
else if (std::strcmp(line, "map_Ks") == 0) {
char texName[100];
sscanf_s(mtl.c_str(), "\nmap_Ks %s\n", texName, (unsigned)_countof(texName));
mats[currMat]->specularTextureName = (std::string)texName;
}
else if (std::strcmp(line, "Ns") == 0) {
float s = 0.0;
sscanf_s(mtl.c_str(), "\nNs %f\n", &s);
mats[currMat]->shininess = s;
}
unsigned int pos = mtl.find(line) + strlen(line);
mtl = mtl.substr(pos);
}
std::string file = obj.substr(0, startMtlPos);
std::vector<float> vbRaw, tcRaw, vnRaw;
std::string usingMat;
bool tcPresent = false, vnPresent = false;
while (true) {
char line[500];
int remove = 0;
int result = sscanf_s(file.c_str(), "\n%s", line, (unsigned)_countof(line));
if (result == EOF)
break;
if (std::strcmp(line, "v") == 0) {
float x = 0.0, y = 0.0, z = 0.0;
sscanf_s(file.c_str(), "\nv %f %f %f\n", &x, &y, &z);
remove = 28;
vbRaw.push_back(x);
vbRaw.push_back(y);
vbRaw.push_back(z);
}
else if (std::strcmp(line, "vt") == 0) {
tcPresent = true;
float u = 0.0, v = 0.0;
sscanf_s(file.c_str(), "\nvt %f %f\n", &u, &v);
remove = 18;
tcRaw.push_back(u);
tcRaw.push_back(v);
}
else if (std::strcmp(line, "vn") == 0) {
vnPresent = true;
float x = 0.0, y = 0.0, z = 0.0;
sscanf_s(file.c_str(), "\nvn %f %f %f\n", &x, &y, &z);
remove = 20;
vnRaw.push_back(x);
vnRaw.push_back(y);
vnRaw.push_back(z);
}
else if (std::strcmp(line, "usemtl") == 0) {
char matName[100];
sscanf_s(file.c_str(), "\nusemtl %s\n", matName, (unsigned)_countof(matName));
usingMat = matName;
remove = 5;
}
else if (std::strcmp(line, "f") == 0) {
unsigned int vertexIndex[3], uvIndex[3], vnIndex[3];
sscanf_s(file.c_str(), "\nf %d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex[0], &uvIndex[0], &vnIndex[0], &vertexIndex[1], &uvIndex[1], &vnIndex[1], &vertexIndex[2], &uvIndex[2], &vnIndex[2]);
remove = 15;
mats[usingMat]->vbIndices.push_back(vertexIndex[0]);
mats[usingMat]->vbIndices.push_back(vertexIndex[1]);
mats[usingMat]->vbIndices.push_back(vertexIndex[2]);
mats[usingMat]->tcIndices.push_back(uvIndex[0]);
mats[usingMat]->tcIndices.push_back(uvIndex[1]);
mats[usingMat]->tcIndices.push_back(uvIndex[2]);
mats[usingMat]->vnIndices.push_back(vnIndex[0]);
mats[usingMat]->vnIndices.push_back(vnIndex[1]);
mats[usingMat]->vnIndices.push_back(vnIndex[2]);
}
unsigned int pos = file.find(line) + strlen(line) + remove;
file = file.substr(pos);
}
if (!tcPresent)
Error("No texture coordinates found in model!");
if (!vnPresent)
Error("No normals found in model!");
for (auto& m : mats) {
std::string curr = m.first;
for (unsigned int i = 0; i < mats[curr]->vbIndices.size(); i++) {
unsigned int vertexIndex = mats[curr]->vbIndices[i];
unsigned int uvIndex = mats[curr]->tcIndices[i];
unsigned int vnIndex = mats[curr]->vnIndices[i];
float vertexX = vbRaw[(vertexIndex - 1) * 3];
float vertexY = vbRaw[(vertexIndex - 1) * 3 + 1];
float vertexZ = vbRaw[(vertexIndex - 1) * 3 + 2];
float vertexU = tcRaw[(uvIndex - 1) * 2];
float vertexV = tcRaw[(uvIndex - 1) * 2 + 1];
float vnX = vnRaw[(vnIndex - 1) * 3];
float vnY = vnRaw[(vnIndex - 1) * 3 + 1];
float vnZ = vnRaw[(vnIndex - 1) * 3 + 2];
mats[curr]->unindexedVB.push_back(vertexX);
mats[curr]->unindexedVB.push_back(vertexY);
mats[curr]->unindexedVB.push_back(vertexZ);
mats[curr]->unindexedTC.push_back(vertexU);
mats[curr]->unindexedTC.push_back(vertexV);
mats[curr]->unindexedVN.push_back(vnX);
mats[curr]->unindexedVN.push_back(vnY);
mats[curr]->unindexedVN.push_back(vnZ);
}
}
struct Vertex {
float x;
float y;
float z;
float u;
float v;
float vnX;
float vnY;
float vnZ;
bool operator<(const Vertex other) const {
return std::memcmp((void*)this, (void*)&other, sizeof(Vertex)) > 0;
}
};
for (auto& m : mats) {
std::string curr = m.first;
std::map<Vertex, unsigned int> vertexMap;
for (unsigned int i = 0; i * 3 < mats[curr]->unindexedVB.size(); i++) {
Vertex currVertex = { mats[curr]->unindexedVB[(i * 3)], mats[curr]->unindexedVB[(i * 3) + 1], mats[curr]->unindexedVB[(i * 3) + 2], mats[curr]->unindexedTC[(i * 2)], mats[curr]->unindexedTC[(i * 2) + 1], mats[curr]->unindexedVN[(i * 3)], mats[curr]->unindexedVN[(i * 3) + 1], mats[curr]->unindexedVN[(i * 3) + 2] };
bool found = false;
found = vertexMap.find(currVertex) != vertexMap.end();
if (found) {
unsigned int index = vertexMap[currVertex];
mats[curr]->outIB.push_back(index);
mats[curr]->ibCount++;
}
else {
mats[curr]->outVB.push_back(currVertex.x);
mats[curr]->outVB.push_back(currVertex.y);
mats[curr]->outVB.push_back(currVertex.z);
mats[curr]->outTC.push_back(currVertex.u);
mats[curr]->outTC.push_back(currVertex.v);
mats[curr]->outVN.push_back(currVertex.vnX);
mats[curr]->outVN.push_back(currVertex.vnY);
mats[curr]->outVN.push_back(currVertex.vnZ);
unsigned int index = (mats[curr]->outVB.size() / 3) - 1;
mats[curr]->outIB.push_back(index);
vertexMap[currVertex] = index;
mats[curr]->ibCount++;
}
}
}
for (auto& m : mats) {
TempMaterial& curr = *m.second;
ATexture* diff = nullptr;
if (curr.diffuseTextureName.size())
diff = model->neededTextures[curr.diffuseTextureName];
ATexture* spec = nullptr;
if (curr.specularTextureName.size())
spec = model->neededTextures[curr.specularTextureName];
m_materials.push_back(new Material(&curr.outVB[0], curr.outVB.size() * sizeof(float), &curr.outTC[0], curr.outTC.size() * sizeof(float), &curr.outVN[0], curr.outVN.size() * sizeof(float), &curr.outIB[0], curr.ibCount, diff, curr.diffuseColor, spec, curr.shininess));
delete m.second;
}
}
void Model::render(Shader* shader) {
for (Material* curr : m_materials) {
curr->render(shader);
}
}
void Model::setBaseAsset(bool isBase) {
@ -55,6 +290,8 @@ namespace nf {
}
Model::~Model() {
delete m_texture;
for (Material* curr : m_materials) {
delete curr;
}
}
}

View File

@ -136,9 +136,11 @@ namespace nf {
1.0, 1.0,
1.0, 0.0
};
glActiveTexture(GL_TEXTURE10);
glBindTexture(GL_TEXTURE_2D, c.texID);
m_vao->setBufferData(0, vb, sizeof(vb));
m_vao->setBufferData(1, tc, sizeof(tc));
shader->setUniform("text", 10);
glDrawArrays(GL_TRIANGLES, 0, 6);
currX += (c.advance >> 6) * scale * m_scale;
}

View File

@ -25,8 +25,7 @@ namespace nf {
m_texture = tex->loadedTexture;
}
else {
m_texture = new Texture;
m_texture->create(tex);
m_texture = new Texture(tex);
}
m_vao = new VertexArray;

View File

@ -155,15 +155,12 @@ namespace nf {
m_entityShader->setUniform("proj", proj);
for (Entity* draw : m_lGame) {
Entity& curr = *draw;
curr.bind(m_entityShader);
//TODO: Clean this up a bit
m_entityShader->setUniform("numberOfLights", (int)m_lights.size() + 1);
for (unsigned int i = 0; i < m_lights.size(); i++) {
m_lights[i]->bind(m_entityShader, i);
}
//TODO: Bind and draw every material here
m_entityShader->setUniform("material.shininess", 1.0f);
glDrawElements(GL_TRIANGLES, curr.getModel()->getIndexCount(), GL_UNSIGNED_INT, nullptr);
curr.render(m_entityShader);
}
m_lGame.clear();
m_lights.clear();
@ -203,7 +200,9 @@ namespace nf {
m_loadingText.setOpacity(opacity);
m_loadingText.render(m_textShader, m_app->getConfig().width, m_app->getConfig().height);
}
opacity -= 0.8 * dT;
if (dT > 1.0 / 60.0)
dT = 1.0 / 60.0;
opacity -= 2.5 * dT;
if (opacity <= 0.0) {
m_fadeIn = false;
m_fadeOutComplete = false;
@ -221,7 +220,7 @@ namespace nf {
m_loadingText.setOpacity(opacity);
m_loadingText.render(m_textShader, m_app->getConfig().width, m_app->getConfig().height);
}
opacity += 1.2 * dT;
opacity += 3.0 * dT;
if (opacity >= 1.0) {
m_fadeIn = false;
m_fadeOutComplete = true;

View File

@ -8,16 +8,12 @@
#include "Utility.h"
namespace nf {
Texture::Texture() :
Texture::Texture(ATexture* tex) :
m_isBase(false),
m_id(0),
m_x(0),
m_y(0)
{
}
void Texture::create(ATexture* tex) {
int nChannels;
stbi_set_flip_vertically_on_load(true);
unsigned char* texture = stbi_load_from_memory((unsigned char*)tex->data, tex->size, &m_x, &m_y, &nChannels, 0);
@ -33,8 +29,10 @@ namespace nf {
m_isBase = tex->isBaseAsset;
}
void Texture::bind() {
void Texture::bind(unsigned int slot) {
glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(GL_TEXTURE_2D, m_id);
glActiveTexture(GL_TEXTURE0);
}
Vec2 Texture::getDimensions() {

View File

@ -3,7 +3,6 @@
#include <iostream>
#include <sstream>
#include <fstream>
#include <map>
#include "glm/glm.hpp"
#include "Config.h"
@ -110,133 +109,6 @@ namespace nf {
}
return read;
}
void parseOBJ(std::string& in, std::vector<float>& vbOut, std::vector<unsigned int>& ibOut, size_t& ibCountOut, std::vector<float>& tcOut, std::vector<float>& vnOut) {
std::string file = in;
std::vector<float> vbRaw, tcRaw, vnRaw;
std::vector<unsigned int> vertexIndices, uvIndices, vnIndices;
std::vector<float> tempVertices, tempTC, tempVN;
bool tcPresent = false, vnPresent = false;
while (true) {
char line[500];
int remove = 0;
int result = sscanf_s(file.c_str(), "\n%s", line, (unsigned)_countof(line));
if (result == EOF)
break;
if (std::strcmp(line, "v") == 0) {
float x = 0.0, y = 0.0, z = 0.0;
sscanf_s(file.c_str(), "\nv %f %f %f\n", &x, &y, &z);
remove = 28;
tempVertices.push_back(x);
tempVertices.push_back(y);
tempVertices.push_back(z);
}
else if (std::strcmp(line, "vt") == 0) {
tcPresent = true;
float u = 0.0, v = 0.0;
sscanf_s(file.c_str(), "\nvt %f %f\n", &u, &v);
remove = 18;
tempTC.push_back(u);
tempTC.push_back(v);
}
if (std::strcmp(line, "vn") == 0) {
vnPresent = true;
float x = 0.0, y = 0.0, z = 0.0;
sscanf_s(file.c_str(), "\nvn %f %f %f\n", &x, &y, &z);
remove = 20;
tempVN.push_back(x);
tempVN.push_back(y);
tempVN.push_back(z);
}
else if (std::strcmp(line, "f") == 0) {
unsigned int vertexIndex[3], uvIndex[3], vnIndex[3];
sscanf_s(file.c_str(), "\nf %d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex[0], &uvIndex[0], &vnIndex[0], &vertexIndex[1], &uvIndex[1], &vnIndex[1], &vertexIndex[2], &uvIndex[2], &vnIndex[2]);
remove = 15;
vertexIndices.push_back(vertexIndex[0]);
vertexIndices.push_back(vertexIndex[1]);
vertexIndices.push_back(vertexIndex[2]);
uvIndices.push_back(uvIndex[0]);
uvIndices.push_back(uvIndex[1]);
uvIndices.push_back(uvIndex[2]);
vnIndices.push_back(vnIndex[0]);
vnIndices.push_back(vnIndex[1]);
vnIndices.push_back(vnIndex[2]);
}
unsigned int pos = file.find(line) + strlen(line) + remove;
file = file.substr(pos);
}
if (!tcPresent)
Error("No texture coordinates found in model!");
if (!vnPresent)
Error("No normals found in model!");
for (unsigned int i = 0; i < vertexIndices.size(); i++) {
unsigned int vertexIndex = vertexIndices[i];
unsigned int uvIndex = uvIndices[i];
unsigned int vnIndex = vnIndices[i];
float vertexX = tempVertices[(vertexIndex - 1) * 3];
float vertexY = tempVertices[(vertexIndex - 1) * 3 + 1];
float vertexZ = tempVertices[(vertexIndex - 1) * 3 + 2];
float vertexU = tempTC[(uvIndex - 1) * 2];
float vertexV = tempTC[(uvIndex - 1) * 2 + 1];
float vnX = tempVN[(vnIndex - 1) * 3];
float vnY = tempVN[(vnIndex - 1) * 3 + 1];
float vnZ = tempVN[(vnIndex - 1) * 3 + 2];
vbRaw.push_back(vertexX);
vbRaw.push_back(vertexY);
vbRaw.push_back(vertexZ);
tcRaw.push_back(vertexU);
tcRaw.push_back(vertexV);
vnRaw.push_back(vnX);
vnRaw.push_back(vnY);
vnRaw.push_back(vnZ);
}
struct Vertex {
float x;
float y;
float z;
float u;
float v;
float vnX;
float vnY;
float vnZ;
bool operator<(const Vertex other) const {
return std::memcmp((void*)this, (void*)&other, sizeof(Vertex)) > 0;
}
};
std::map<Vertex, unsigned int> vertexMap;
for (unsigned int i = 0; i * 3 < vbRaw.size(); i++) {
Vertex curr = { vbRaw[(i * 3)], vbRaw[(i * 3) + 1], vbRaw[(i * 3) + 2], tcRaw[(i * 2)], tcRaw[(i * 2) + 1], vnRaw[(i * 3)], vnRaw[(i * 3) + 1], vnRaw[(i * 3) + 2] };
bool found = false;
found = vertexMap.find(curr) != vertexMap.end();
if (found) {
unsigned int index = vertexMap[curr];
ibOut.push_back(index);
ibCountOut++;
}
else {
vbOut.push_back(curr.x);
vbOut.push_back(curr.y);
vbOut.push_back(curr.z);
tcOut.push_back(curr.u);
tcOut.push_back(curr.v);
vnOut.push_back(curr.vnX);
vnOut.push_back(curr.vnY);
vnOut.push_back(curr.vnZ);
unsigned int index = (vbOut.size() / 3) - 1;
ibOut.push_back(index);
vertexMap[curr] = index;
ibCountOut++;
}
}
}
}
//Nvidia Optimius support

View File

@ -1,5 +1,6 @@
#pragma once
#include <unordered_map>
#include "NFObject.h"
namespace nf {
@ -14,12 +15,6 @@ namespace nf {
virtual ~Asset();
};
struct AModel : Asset {
Model* loadedModel = nullptr;
~AModel() override;
};
struct ATexture : Asset {
size_t size = 0;
Texture* loadedTexture = nullptr;
@ -27,6 +22,14 @@ namespace nf {
~ATexture() override;
};
struct AModel : Asset {
Model* loadedModel = nullptr;
std::unordered_map<std::string, ATexture*> neededTextures;
~AModel() override;
};
struct ACubemap : Asset {
char* frontData = nullptr;
size_t frontSize = 0;

View File

@ -11,7 +11,7 @@ namespace nf {
public:
Entity();
void create(Asset* modelAsset, Asset* textureAsset = nullptr);
void create(Asset* modelAsset);
bool isConstructed();
void setPosition(double x, double y, double z);
@ -22,7 +22,7 @@ namespace nf {
void setScale(double x, double y, double z);
void setScale(const Vec3& scale);
void bind(Shader* shader);
void render(Shader* shader);
Model* getModel() const;
void destroy() override;

View File

@ -13,7 +13,7 @@ namespace nf {
};
Light();
void create(const Vec3& position, const Vec3& color, float strength = 1.0f, Type type = Type::POINT);
void create(const Vec3& position, const Vec3& color, double strength = 1.0, Type type = Type::POINT);
bool isConstructed();
void setPosition(const Vec3& position);
void setColor(const Vec3& color);

View File

@ -1,17 +1,34 @@
#pragma once
#include "Drawable.h"
#include "Assets.h"
#include "Utility.h"
namespace nf {
class Drawable;
class Texture;
class Shader;
class Model : public Drawable {
class Material : public Drawable {
public:
Model();
Material(const void* vb, const size_t vbSize, const void* tc, const size_t tcSize, const void* vn, const size_t vnSize, const void* ib, const unsigned int ibCount, ATexture* diffTex, Vec3& diffColor, ATexture* specTex, float shininess);
void create(const void* vertexBufferData, const size_t vertexBufferSize, const void* indexBufferData, size_t indexBufferCount, const void* textureCoordinatesBufferData, size_t textureCoordinatesBufferSize, const void* normalsBufferData, size_t normalsBufferSize, ATexture* texture);
void bind() override;
void render(Shader* shader);
~Material();
private:
bool m_hasDiffuse = false;
Texture* m_diffuseTexture = nullptr;
Vec3 m_diffColor;
bool m_hasSpecular = false;
Texture* m_specularTexture = nullptr;
float m_shininess;
};
class Model {
public:
Model(AModel* model);
void render(Shader* shader);
void setBaseAsset(bool isBase);
bool isBaseAsset();
@ -19,6 +36,6 @@ namespace nf {
~Model();
private:
bool m_base;
Texture* m_texture;
std::vector<Material*> m_materials;
};
}

View File

@ -6,10 +6,9 @@ namespace nf {
class Texture {
public:
Texture();
Texture(ATexture* tex);
void create(ATexture* tex);
void bind();
void bind(unsigned int slot = 0);
Vec2 getDimensions();
bool isBaseAsset();

View File

@ -1,7 +1,6 @@
#pragma once
#include <chrono>
#include <string>
#include <vector>
#include <Windows.h>
namespace nf {
@ -83,6 +82,4 @@ std::exit(-1);}
const wchar_t* toWide(const std::string& in);
void writeFile(const std::string& filename, const std::string& in, bool encrypted = false);
std::string readFile(const std::string& filename);
void parseOBJ(std::string& in, std::vector<float>& vbOut, std::vector<unsigned int>& ibOut, size_t& ibCountOut, std::vector<float>& tcOut, std::vector<float>& vnOut);
}