Use assimp for loading 3d models
This commit is contained in:
parent
96ac056a5d
commit
5a7e5cd10f
|
@ -0,0 +1,178 @@
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
# BasedOnStyle: LLVM
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignArrayOfStructures: None
|
||||||
|
AlignConsecutiveMacros: None
|
||||||
|
AlignConsecutiveAssignments: None
|
||||||
|
AlignConsecutiveBitFields: None
|
||||||
|
AlignConsecutiveDeclarations: None
|
||||||
|
AlignEscapedNewlines: Right
|
||||||
|
AlignOperands: Align
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllArgumentsOnNextLine: true
|
||||||
|
AllowAllConstructorInitializersOnNextLine: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowShortEnumsOnASingleLine: true
|
||||||
|
AllowShortBlocksOnASingleLine: Never
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: All
|
||||||
|
AllowShortLambdasOnASingleLine: All
|
||||||
|
AllowShortIfStatementsOnASingleLine: Never
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: MultiLine
|
||||||
|
AttributeMacros:
|
||||||
|
- __capability
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: false
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: Never
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: false
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
BeforeLambdaBody: false
|
||||||
|
BeforeWhile: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeConceptDeclarations: true
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
BreakBeforeInheritanceComma: false
|
||||||
|
BreakInheritanceList: BeforeColon
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ColumnLimit: 120
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DeriveLineEnding: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
EmptyLineAfterAccessModifier: Never
|
||||||
|
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
ForEachMacros:
|
||||||
|
- foreach
|
||||||
|
- Q_FOREACH
|
||||||
|
- BOOST_FOREACH
|
||||||
|
IfMacros:
|
||||||
|
- KJ_IF_MAYBE
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||||
|
Priority: 2
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||||
|
Priority: 3
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 1
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
IncludeIsMainRegex: '(Test)?$'
|
||||||
|
IncludeIsMainSourceRegex: ''
|
||||||
|
IndentAccessModifiers: false
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentCaseBlocks: false
|
||||||
|
IndentGotoLabels: true
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentExternBlock: AfterExternBlock
|
||||||
|
IndentRequires: false
|
||||||
|
IndentWidth: 4
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
InsertTrailingCommas: None
|
||||||
|
JavaScriptQuotes: Leave
|
||||||
|
JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
|
LambdaBodyIndentation: Signature
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: All
|
||||||
|
ObjCBinPackProtocolList: Auto
|
||||||
|
ObjCBlockIndentWidth: 2
|
||||||
|
ObjCBreakBeforeNestedBlockParam: true
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 19
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyBreakTemplateDeclaration: 10
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
|
PenaltyIndentedWhitespace: 0
|
||||||
|
PointerAlignment: Right
|
||||||
|
PPIndentWidth: -1
|
||||||
|
ReferenceAlignment: Pointer
|
||||||
|
ReflowComments: true
|
||||||
|
ShortNamespaceLines: 1
|
||||||
|
SortIncludes: CaseSensitive
|
||||||
|
SortJavaStaticImport: Before
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterLogicalNot: false
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCaseColon: false
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceAroundPointerQualifiers: Default
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceInEmptyBlock: false
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
SpacesInAngles: Never
|
||||||
|
SpacesInConditionalStatement: false
|
||||||
|
SpacesInContainerLiterals: true
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInLineCommentPrefix:
|
||||||
|
Minimum: 1
|
||||||
|
Maximum: -1
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
SpaceBeforeSquareBrackets: false
|
||||||
|
BitFieldColonSpacing: Both
|
||||||
|
Standard: Latest
|
||||||
|
StatementAttributeLikeMacros:
|
||||||
|
- Q_EMIT
|
||||||
|
StatementMacros:
|
||||||
|
- Q_UNUSED
|
||||||
|
- QT_REQUIRE_VERSION
|
||||||
|
TabWidth: 8
|
||||||
|
UseCRLF: false
|
||||||
|
UseTab: Never
|
||||||
|
WhitespaceSensitiveMacros:
|
||||||
|
- STRINGIZE
|
||||||
|
- PP_STRINGIZE
|
||||||
|
- BOOST_PP_STRINGIZE
|
||||||
|
- NS_SWIFT_NAME
|
||||||
|
- CF_SWIFT_NAME
|
||||||
|
...
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
{
|
||||||
|
"asset": {
|
||||||
|
"generator": "COLLADA2GLTF",
|
||||||
|
"version": "2.0"
|
||||||
|
},
|
||||||
|
"scene": 0,
|
||||||
|
"scenes": [
|
||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"children": [
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"matrix": [
|
||||||
|
1.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
-1.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mesh": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meshes": [
|
||||||
|
{
|
||||||
|
"primitives": [
|
||||||
|
{
|
||||||
|
"attributes": {
|
||||||
|
"NORMAL": 1,
|
||||||
|
"POSITION": 2
|
||||||
|
},
|
||||||
|
"indices": 0,
|
||||||
|
"mode": 4,
|
||||||
|
"material": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "Mesh"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accessors": [
|
||||||
|
{
|
||||||
|
"bufferView": 0,
|
||||||
|
"byteOffset": 0,
|
||||||
|
"componentType": 5123,
|
||||||
|
"count": 36,
|
||||||
|
"max": [
|
||||||
|
23
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"type": "SCALAR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 1,
|
||||||
|
"byteOffset": 0,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 24,
|
||||||
|
"max": [
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
1.0
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-1.0,
|
||||||
|
-1.0,
|
||||||
|
-1.0
|
||||||
|
],
|
||||||
|
"type": "VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 1,
|
||||||
|
"byteOffset": 288,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 24,
|
||||||
|
"max": [
|
||||||
|
0.5,
|
||||||
|
0.5,
|
||||||
|
0.5
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-0.5,
|
||||||
|
-0.5,
|
||||||
|
-0.5
|
||||||
|
],
|
||||||
|
"type": "VEC3"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"materials": [
|
||||||
|
{
|
||||||
|
"pbrMetallicRoughness": {
|
||||||
|
"baseColorFactor": [
|
||||||
|
0.800000011920929,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
1.0
|
||||||
|
],
|
||||||
|
"metallicFactor": 0.0
|
||||||
|
},
|
||||||
|
"name": "Red"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bufferViews": [
|
||||||
|
{
|
||||||
|
"buffer": 0,
|
||||||
|
"byteOffset": 576,
|
||||||
|
"byteLength": 72,
|
||||||
|
"target": 34963
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer": 0,
|
||||||
|
"byteOffset": 0,
|
||||||
|
"byteLength": 576,
|
||||||
|
"byteStride": 12,
|
||||||
|
"target": 34962
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buffers": [
|
||||||
|
{
|
||||||
|
"byteLength": 648,
|
||||||
|
"uri": "Box0.bin"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
set(TINYGLTF_HEADER_ONLY ON CACHE INTERNAL "" FORCE)
|
||||||
|
set(TINYGLTF_INSTALL OFF CACHE INTERNAL "" FORCE)
|
||||||
|
set(TINYGLTF_BUILD_LOADER_EXAMPLE OFF CACHE INTERNAL "" FORCE)
|
||||||
|
|
||||||
|
# Get the tinygltf header libraries.
|
||||||
|
include(FetchContent)
|
||||||
|
FetchContent_Declare(
|
||||||
|
tinygltf
|
||||||
|
GIT_REPOSITORY https://github.com/syoyo/tinygltf.git
|
||||||
|
GIT_TAG eec4c98862b7fb760b2fb70971d7b652e593af9f
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(tinygltf)
|
||||||
|
|
||||||
|
message("Downloaded tinygltf library to: ${tinygltf_SOURCE_DIR}")
|
||||||
|
|
||||||
|
#set(STB_INCLUDE_DIR ${stb_SOURCE_DIR})
|
|
@ -20,16 +20,7 @@ find_package(GLEW REQUIRED)
|
||||||
find_package(glfw3 CONFIG REQUIRED)
|
find_package(glfw3 CONFIG REQUIRED)
|
||||||
find_package(glm CONFIG REQUIRED)
|
find_package(glm CONFIG REQUIRED)
|
||||||
find_package(OpenGL REQUIRED)
|
find_package(OpenGL REQUIRED)
|
||||||
|
find_package(assimp REQUIRED)
|
||||||
# Get the stb header libraries.
|
|
||||||
#include(FetchContent)
|
|
||||||
#FetchContent_Declare(
|
|
||||||
# stb
|
|
||||||
# GIT_REPOSITORY https://github.com/nothings/stb.git
|
|
||||||
# GIT_TAG 8b5f1f37b5b75829fc72d38e7b5d4bcbf8a26d55
|
|
||||||
#)
|
|
||||||
#FetchContent_MakeAvailable(stb)
|
|
||||||
#message("Downloaded stb library to: ${stb_SOURCE_DIR}")
|
|
||||||
|
|
||||||
# Link sources
|
# Link sources
|
||||||
file(GLOB_RECURSE source_list src/*.cpp)
|
file(GLOB_RECURSE source_list src/*.cpp)
|
||||||
|
@ -53,12 +44,14 @@ target_link_libraries(simpleengine PUBLIC GLEW::GLEW)
|
||||||
target_link_libraries(simpleengine PUBLIC glfw)
|
target_link_libraries(simpleengine PUBLIC glfw)
|
||||||
target_link_libraries(simpleengine PUBLIC ${GLM_LIBRARIES})
|
target_link_libraries(simpleengine PUBLIC ${GLM_LIBRARIES})
|
||||||
target_link_libraries(simpleengine PUBLIC ${OPENGL_LIBRARIES})
|
target_link_libraries(simpleengine PUBLIC ${OPENGL_LIBRARIES})
|
||||||
|
target_link_libraries(simpleengine PUBLIC assimp)
|
||||||
target_link_libraries(simpleengine PRIVATE simpleengine_resources)
|
target_link_libraries(simpleengine PRIVATE simpleengine_resources)
|
||||||
|
|
||||||
target_include_directories(simpleengine PUBLIC ${STB_INCLUDE_DIR})
|
target_include_directories(simpleengine PUBLIC ${STB_INCLUDE_DIR})
|
||||||
|
|
||||||
# Include some dependencies' include directories
|
# Include some dependencies' include directories
|
||||||
include_directories(${OPENGL_INCLUDE_DIR})
|
target_include_directories(simpleengine PUBLIC ${OPENGL_INCLUDE_DIR})
|
||||||
include_directories(${GLM_INCLUDE_DIRS})
|
target_include_directories(simpleengine PUBLIC ${GLM_INCLUDE_DIRS})
|
||||||
|
|
||||||
# Add examples as a target if the user has them enabled
|
# Add examples as a target if the user has them enabled
|
||||||
if (SIMPLE_ENGINE_BUILD_EXAMPLES)
|
if (SIMPLE_ENGINE_BUILD_EXAMPLES)
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
#include "simpleengine/camera.h"
|
#include "simpleengine/camera.h"
|
||||||
#include "simpleengine/ecs/component/model_componenet.h"
|
#include "simpleengine/ecs/component/mesh_component.h"
|
||||||
|
#include <simpleengine/ecs/component/model_component.h>
|
||||||
#include "simpleengine/ecs/entity.h"
|
#include "simpleengine/ecs/entity.h"
|
||||||
#include "simpleengine/entity_manager.h"
|
#include "simpleengine/entity_manager.h"
|
||||||
#include "simpleengine/gfx/light.h"
|
#include "simpleengine/gfx/light.h"
|
||||||
#include "simpleengine/gfx/material.h"
|
#include "simpleengine/gfx/material.h"
|
||||||
|
#include "simpleengine/gfx/mesh.h"
|
||||||
#include "simpleengine/gfx/model.h"
|
#include "simpleengine/gfx/model.h"
|
||||||
#include "simpleengine/gfx/renderer.h"
|
#include "simpleengine/gfx/renderer.h"
|
||||||
#include "simpleengine/gfx/texture.h"
|
#include "simpleengine/gfx/texture.h"
|
||||||
|
@ -16,6 +18,7 @@
|
||||||
#include <simpleengine/game.h>
|
#include <simpleengine/game.h>
|
||||||
#include <simpleengine/vertex.h>
|
#include <simpleengine/vertex.h>
|
||||||
#include <simpleengine/gfx/shaders/core_3d_shader.h>
|
#include <simpleengine/gfx/shaders/core_3d_shader.h>
|
||||||
|
#include <simpleengine/gfx/model.h>
|
||||||
|
|
||||||
//#include <simpleengine/scene.h>
|
//#include <simpleengine/scene.h>
|
||||||
|
|
||||||
|
@ -166,13 +169,11 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
// Create the entity and add the model component to it.
|
// Create the entity and add the model component to it.
|
||||||
/* auto entity = std::make_shared<simpleengine::Entity>();
|
/* auto entity = std::make_shared<simpleengine::Entity>();
|
||||||
entity->add_component<se::ModelComponent>(cube_vertices, cube_indicies, material, true);
|
entity->add_component<se::MeshComponent>(cube_vertices, cube_indicies, material, true);
|
||||||
entity->translate(3.5f, 0.f, 0.f); */
|
entity->translate(3.5f, 0.f, 0.f); */
|
||||||
|
|
||||||
//auto entity = std::make_shared<se::gfx::M>(game.get_window(), core_shader, white_texture, "examples/dev_testing/resources/dragon.obj");
|
|
||||||
auto entity = std::make_shared<simpleengine::Entity>();
|
auto entity = std::make_shared<simpleengine::Entity>();
|
||||||
se::gfx::Model model(material, "examples/dev_testing/resources/dragon.obj");
|
entity->add_component<se::ModelComponent>("examples/dev_testing/resources/dragon.obj");
|
||||||
entity->add_component<se::ModelComponent>(model);
|
|
||||||
entity->translate(12.f, -4.f, 0.f);
|
entity->translate(12.f, -4.f, 0.f);
|
||||||
|
|
||||||
// Create a renderer and submit the entity into it.
|
// Create a renderer and submit the entity into it.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../../gfx/model.h"
|
#include "../../gfx/mesh.h"
|
||||||
#include "../../event/event.h"
|
#include "../../event/event.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "component.h"
|
#include "component.h"
|
||||||
#include "../../gfx/model.h"
|
#include "../../gfx/mesh.h"
|
||||||
#include "../../gfx/material.h"
|
#include "../../gfx/material.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -12,16 +12,16 @@ namespace simpleengine {
|
||||||
* @brief A Model is a object that will be shown on the screen by a renderer.
|
* @brief A Model is a object that will be shown on the screen by a renderer.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class ModelComponent : public simpleengine::Component {
|
class MeshComponent : public simpleengine::Component {
|
||||||
public:
|
public:
|
||||||
gfx::Model model;
|
gfx::Mesh model;
|
||||||
//gfx::Material material;
|
//gfx::Material material;
|
||||||
|
|
||||||
ModelComponent(gfx::Model model) : model(model) {
|
MeshComponent(gfx::Mesh model) : model(model) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelComponent(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, gfx::Material material,
|
MeshComponent(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, gfx::Material material,
|
||||||
bool calculate_normals = false): model(vertices, indicies, material) {
|
bool calculate_normals = false): model(vertices, indicies, material) {
|
||||||
|
|
||||||
if (calculate_normals) {
|
if (calculate_normals) {
|
||||||
|
@ -29,7 +29,7 @@ namespace simpleengine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelComponent(std::vector<LitVertex> vertices, std::vector<GLuint> indicies = std::vector<GLuint>(),
|
MeshComponent(std::vector<LitVertex> vertices, std::vector<GLuint> indicies = std::vector<GLuint>(),
|
||||||
std::optional<gfx::Material> material = std::nullopt, bool calculate_normals = false) :
|
std::optional<gfx::Material> material = std::nullopt, bool calculate_normals = false) :
|
||||||
model(vertices, indicies, material) {
|
model(vertices, indicies, material) {
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ namespace simpleengine {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void update(const float& delta_time) override {
|
virtual void update(const float& delta_time) override {
|
||||||
std::cout << "Model Component update" << std::endl;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "component.h"
|
||||||
|
#include "../../gfx/model.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace simpleengine {
|
||||||
|
/**
|
||||||
|
* @brief A Model is a object that will be shown on the screen by a renderer.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class ModelComponent : public simpleengine::Component {
|
||||||
|
public:
|
||||||
|
gfx::Model model;
|
||||||
|
|
||||||
|
ModelComponent(gfx::Model model) : model(model) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelComponent(std::string model_file_path) : model(model_file_path) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void update(const float& delta_time) override {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -54,13 +54,11 @@ namespace simpleengine {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void update(const float& delta_time) override {
|
virtual void update(const float& delta_time) override {
|
||||||
std::cout << "Update entity" << std::endl;
|
|
||||||
|
|
||||||
for (auto& component : components) {
|
for (auto& component : components) {
|
||||||
component->update(delta_time);
|
component->update(delta_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
rotate_y(delta_time * 10);
|
rotate_y(delta_time * 10); // TODO: Remove
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace simpleengine::gfx {
|
||||||
float shine;
|
float shine;
|
||||||
float reflectivity;
|
float reflectivity;
|
||||||
|
|
||||||
Material(Texture texture, float shine, float reflectivity, float specular_scalar, float ambient_scalar, float diffuse_scalar) :
|
Material(Texture texture, float shine = 1.f, float reflectivity = 0.f, float specular_scalar = 0.f, float ambient_scalar = 0.f, float diffuse_scalar = 0.f) :
|
||||||
texture(texture), ambient_scalar(ambient_scalar), diffuse_scalar(diffuse_scalar), specular_scalar(specular_scalar),
|
texture(texture), ambient_scalar(ambient_scalar), diffuse_scalar(diffuse_scalar), specular_scalar(specular_scalar),
|
||||||
shine(shine), reflectivity(reflectivity) {
|
shine(shine), reflectivity(reflectivity) {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "shader.h"
|
||||||
|
#include "../event/event.h"
|
||||||
|
#include "vao.h"
|
||||||
|
#include "vbo.h"
|
||||||
|
#include "../vertex.h"
|
||||||
|
#include "../renderable.h"
|
||||||
|
#include "../transformable.h"
|
||||||
|
#include "material.h"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace simpleengine::gfx {
|
||||||
|
/**
|
||||||
|
* @brief A Mesh is a object that will be shown on the screen by a renderer.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Mesh : public simpleengine::Event, public simpleengine::Transformable {
|
||||||
|
public:
|
||||||
|
std::optional<Material> material;
|
||||||
|
std::vector<LitVertex> vertices;
|
||||||
|
std::vector<GLuint> indicies;
|
||||||
|
|
||||||
|
gfx::VBO ebo;
|
||||||
|
gfx::VBO vbo;
|
||||||
|
gfx::VAO vao;
|
||||||
|
|
||||||
|
Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, Material material);
|
||||||
|
Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies = std::vector<GLuint>(), std::optional<Material> material = std::nullopt);
|
||||||
|
Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, Material material, gfx::VBO ebo, gfx::VBO vbo, gfx::VAO vao);
|
||||||
|
Mesh(Material material, std::string filename);
|
||||||
|
Mesh(Material material, std::ifstream file_stream);
|
||||||
|
|
||||||
|
virtual void destroy() override;
|
||||||
|
|
||||||
|
virtual void update(const float& delta_time) override;
|
||||||
|
|
||||||
|
glm::vec3 compute_face_normal(const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& p3);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate the normals of the model.
|
||||||
|
*
|
||||||
|
* @note This **will** overwrite the existing normals.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void calculate_normals();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void process_vertex(const std::vector<std::string>& vertex_data, const std::vector<glm::vec2>& in_textures,
|
||||||
|
const std::vector<glm::vec3>& in_normals, std::vector<GLuint>& out_indicies,
|
||||||
|
std::vector<glm::vec2>& out_textures, std::vector<glm::vec3>& out_normals);
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,55 +1,33 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "shader.h"
|
#include "mesh.h"
|
||||||
#include "../event/event.h"
|
#include "simpleengine/gfx/texture.h"
|
||||||
#include "vao.h"
|
|
||||||
#include "vbo.h"
|
|
||||||
#include "../vertex.h"
|
|
||||||
#include "../renderable.h"
|
|
||||||
#include "../transformable.h"
|
|
||||||
#include "material.h"
|
|
||||||
|
|
||||||
#include <optional>
|
#include <assimp/material.h>
|
||||||
#include <vector>
|
#include <assimp/mesh.h>
|
||||||
|
#include <assimp/scene.h>
|
||||||
|
|
||||||
|
//#include <assimp/mesh.h>
|
||||||
|
|
||||||
namespace simpleengine::gfx {
|
namespace simpleengine::gfx {
|
||||||
/**
|
/**
|
||||||
* @brief A Model is a object that will be shown on the screen by a renderer.
|
* @brief A Model is a group of Meshes read from the 3D model file.
|
||||||
|
*
|
||||||
|
* The engine uses assimp, so all formats that it supports can be found here:
|
||||||
|
* https://github.com/assimp/assimp/blob/master/doc/Fileformats.md
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class Model : public simpleengine::Event, public simpleengine::Transformable {
|
class Model : public simpleengine::Transformable {
|
||||||
|
protected:
|
||||||
|
std::string model_directory; // May be needed
|
||||||
public:
|
public:
|
||||||
std::optional<Material> material;
|
std::vector<gfx::Mesh> meshes;
|
||||||
std::vector<LitVertex> vertices;
|
|
||||||
std::vector<GLuint> indicies;
|
|
||||||
|
|
||||||
// Buffer objects
|
Model(std::string file_path);
|
||||||
gfx::VBO ebo;
|
|
||||||
gfx::VBO vbo;
|
|
||||||
gfx::VAO vao;
|
|
||||||
|
|
||||||
Model(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, Material material);
|
void load_model(std::string path);
|
||||||
Model(std::vector<LitVertex> vertices, std::vector<GLuint> indicies = std::vector<GLuint>(), std::optional<Material> material = std::nullopt);
|
void process_node(aiNode* node, const aiScene* scene);
|
||||||
Model(Material material, std::string filename);
|
gfx::Mesh process_mesh(aiMesh* mesh, const aiScene* scene);
|
||||||
Model(Material material, std::ifstream file_stream);
|
std::vector<Texture> load_material_textures(aiMaterial* material, aiTextureType* type, std::string type_name);
|
||||||
|
|
||||||
virtual void destroy() override;
|
|
||||||
|
|
||||||
virtual void update(const float& delta_time) override;
|
|
||||||
|
|
||||||
glm::vec3 compute_face_normal(const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& p3);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Calculate the normals of the model.
|
|
||||||
*
|
|
||||||
* @note This **will** overwrite the existing normals.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void calculate_normals();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void process_vertex(const std::vector<std::string>& vertex_data, const std::vector<glm::vec2>& in_textures,
|
|
||||||
const std::vector<glm::vec3>& in_normals, std::vector<GLuint>& out_indicies,
|
|
||||||
std::vector<glm::vec2>& out_textures, std::vector<glm::vec3>& out_normals);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
//#include "renderable.h"
|
//#include "renderable.h"
|
||||||
|
#include "mesh.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
@ -19,7 +20,7 @@ namespace simpleengine::gfx {
|
||||||
class RenderingModel {
|
class RenderingModel {
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<simpleengine::Entity> entity;
|
std::shared_ptr<simpleengine::Entity> entity;
|
||||||
std::unordered_map<uint32_t, gfx::Model&> component_models;
|
std::unordered_map<uint32_t, gfx::Mesh&> component_models;
|
||||||
|
|
||||||
RenderingModel(std::shared_ptr<simpleengine::Entity> entity) : entity(entity) {
|
RenderingModel(std::shared_ptr<simpleengine::Entity> entity) : entity(entity) {
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,12 @@
|
||||||
namespace simpleengine::gfx {
|
namespace simpleengine::gfx {
|
||||||
class Texture {
|
class Texture {
|
||||||
private:
|
private:
|
||||||
unsigned char* img_data;
|
unsigned char* img_data; // TODO Free this if its not used anymore
|
||||||
unsigned int texture_id;
|
unsigned int texture_id;
|
||||||
|
|
||||||
unsigned int image_type;
|
unsigned int image_type_gl;
|
||||||
|
|
||||||
|
Texture() = default;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief The type of the texture
|
* @brief The type of the texture
|
||||||
|
@ -36,8 +38,6 @@ namespace simpleengine::gfx {
|
||||||
int height;
|
int height;
|
||||||
int width;
|
int width;
|
||||||
int channels;
|
int channels;
|
||||||
float shine_damper = 1.f;
|
|
||||||
float reflectivity = 0.f;
|
|
||||||
Type type;
|
Type type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,7 +47,7 @@ namespace simpleengine::gfx {
|
||||||
* @param img_2d Whether or not the texture is 2D.
|
* @param img_2d Whether or not the texture is 2D.
|
||||||
* @param mipmap Whether or not to generate mipmaps for this texture.
|
* @param mipmap Whether or not to generate mipmaps for this texture.
|
||||||
*/
|
*/
|
||||||
Texture(const char* path, bool img_2d = true, bool mipmap = true);
|
Texture(const char* path, Type type = Type::TexT_DIFFUSE, bool img_2d = true, bool mipmap = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Construct a new Texture object from the loaded file buffer.
|
* @brief Construct a new Texture object from the loaded file buffer.
|
||||||
|
@ -57,7 +57,7 @@ namespace simpleengine::gfx {
|
||||||
* @param img_2d Whether or not the texture is 2D.
|
* @param img_2d Whether or not the texture is 2D.
|
||||||
* @param mipmap Whether or not to generate mipmaps for this texture.
|
* @param mipmap Whether or not to generate mipmaps for this texture.
|
||||||
*/
|
*/
|
||||||
Texture(const unsigned char *const buffer, int buffer_length, bool img_2d = true, bool mipmap = true);
|
Texture(const unsigned char *const buffer, int buffer_length, Type type = Type::TexT_DIFFUSE, bool img_2d = true, bool mipmap = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Construct a new Texture object from the loaded file buffer.
|
* @brief Construct a new Texture object from the loaded file buffer.
|
||||||
|
@ -66,7 +66,9 @@ namespace simpleengine::gfx {
|
||||||
* @param img_2d Whether or not the texture is 2D.
|
* @param img_2d Whether or not the texture is 2D.
|
||||||
* @param mipmap Whether or not to generate mipmaps for this texture.
|
* @param mipmap Whether or not to generate mipmaps for this texture.
|
||||||
*/
|
*/
|
||||||
Texture(std::vector<unsigned char> buffer, bool img_2d = true, bool mipmap = true);
|
Texture(std::vector<unsigned char> buffer, Type type = Type::TexT_DIFFUSE, bool img_2d = true, bool mipmap = true);
|
||||||
|
|
||||||
|
static Texture white_texture();
|
||||||
|
|
||||||
void bind() const;
|
void bind() const;
|
||||||
void unbind() const;
|
void unbind() const;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "gfx/model.h"
|
#include "gfx/mesh.h"
|
||||||
#include "entity.h"
|
#include "entity.h"
|
||||||
#include "event/event.h"
|
#include "event/event.h"
|
||||||
#include "renderable.h"
|
#include "renderable.h"
|
||||||
|
|
|
@ -37,7 +37,6 @@ void main() {
|
||||||
vec3 final_specular = calculate_specular(unit_normal, shine_damper, reflectivity);
|
vec3 final_specular = calculate_specular(unit_normal, shine_damper, reflectivity);
|
||||||
|
|
||||||
fs_color = vec4(diffuse, 1.f) * texture(u_textures[id], vs_texcoord) + vec4(final_specular, 1.f);
|
fs_color = vec4(diffuse, 1.f) * texture(u_textures[id], vs_texcoord) + vec4(final_specular, 1.f);
|
||||||
//fs_color = texture(u_textures[1], vs_texcoord);
|
|
||||||
} else {
|
} else {
|
||||||
fs_color = vec4(vs_color, 1.f); // We don't add any reflectivity to solid colored vectors.
|
fs_color = vec4(vs_color, 1.f); // We don't add any reflectivity to solid colored vectors.
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ pkgs.mkShell {
|
||||||
glew
|
glew
|
||||||
glfw
|
glfw
|
||||||
glm
|
glm
|
||||||
|
assimp
|
||||||
(callPackage ./soil2.nix { })
|
(callPackage ./soil2.nix { })
|
||||||
];
|
];
|
||||||
}
|
}
|
|
@ -0,0 +1,167 @@
|
||||||
|
#include "gfx/mesh.h"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace simpleengine::gfx {
|
||||||
|
Mesh::Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, Material material) :
|
||||||
|
material(std::make_optional(material)), vertices(vertices), indicies(indicies),
|
||||||
|
vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)), ebo(gfx::VBO::init(GL_ELEMENT_ARRAY_BUFFER, false)),
|
||||||
|
vao(gfx::VAO::init()) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh::Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, std::optional<Material> material) :
|
||||||
|
material(material), vertices(vertices), indicies(indicies),
|
||||||
|
vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)), ebo(gfx::VBO::init(GL_ELEMENT_ARRAY_BUFFER, false)),
|
||||||
|
vao(gfx::VAO::init()) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh::Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, Material material, gfx::VBO ebo, gfx::VBO vbo, gfx::VAO vao) :
|
||||||
|
vertices(vertices), indicies(indicies), material(material), ebo(ebo), vbo(vbo), vao(vao) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh::Mesh(Material material, std::string filename) :
|
||||||
|
Mesh(material, std::ifstream(filename, std::ios::in | std::ios::binary)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> split_string(std::string str, const char delim) {
|
||||||
|
std::istringstream ss(str);
|
||||||
|
|
||||||
|
std::vector<std::string> tokens;
|
||||||
|
size_t pos = 0;
|
||||||
|
std::string token;
|
||||||
|
while ((pos = str.find(delim)) != std::string::npos) {
|
||||||
|
token = str.substr(0, pos);
|
||||||
|
tokens.push_back(token);
|
||||||
|
str.erase(0, pos + 1);
|
||||||
|
}
|
||||||
|
tokens.push_back(str);
|
||||||
|
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh::Mesh(Material material, std::ifstream file_stream) :
|
||||||
|
vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)), ebo(gfx::VBO::init(GL_ELEMENT_ARRAY_BUFFER, false)),
|
||||||
|
vao(gfx::VAO::init()), material(material) {
|
||||||
|
|
||||||
|
if (!file_stream.is_open()) {
|
||||||
|
std::cerr << "File stream that was given to ObjModel::ObjModel is not open!" << std::endl;
|
||||||
|
throw std::runtime_error("Failed to open ObjModel model file");
|
||||||
|
}
|
||||||
|
|
||||||
|
// The vertices, texture coords, and normals that were read from the obj file
|
||||||
|
// these are not in a particular order.
|
||||||
|
std::vector<glm::vec3> obj_vertices;
|
||||||
|
std::vector<glm::vec2> obj_textures;
|
||||||
|
std::vector<glm::vec3> obj_normals;
|
||||||
|
|
||||||
|
// The texture coords and normals that have been sorted.
|
||||||
|
std::vector<glm::vec2> textures;
|
||||||
|
std::vector<glm::vec3> normals;
|
||||||
|
|
||||||
|
// Read the vertices, texture coords, and normals. Break when run into indices
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(file_stream, line)) {
|
||||||
|
std::vector<std::string> line_tokens = split_string(line, ' ');
|
||||||
|
|
||||||
|
if (line_tokens.front() == "v") {
|
||||||
|
//glm::vec3 vertex(stof(line_tokens[1]), stof(line_tokens[2]), stof(line_tokens[3]));
|
||||||
|
obj_vertices.emplace_back(stof(line_tokens[1]), stof(line_tokens[2]), stof(line_tokens[3]));
|
||||||
|
} else if (line_tokens.front() == "vt") {
|
||||||
|
obj_textures.emplace_back(stof(line_tokens[1]), stof(line_tokens[2]));
|
||||||
|
} else if (line_tokens.front() == "vn") {
|
||||||
|
obj_normals.emplace_back(stof(line_tokens[1]), stof(line_tokens[2]), stof(line_tokens[3]));
|
||||||
|
} else if (line_tokens.front() == "f") {
|
||||||
|
auto size = obj_vertices.size();
|
||||||
|
textures.resize(size);
|
||||||
|
normals.resize(size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the indicies. This will sort everything for storing inside of the Vertex list.
|
||||||
|
do {
|
||||||
|
if (!line.starts_with("f")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::vector<std::string> line_tokens = split_string(line, ' ');
|
||||||
|
std::vector<std::string> vertex1 = split_string(line_tokens[1], '/');
|
||||||
|
std::vector<std::string> vertex2 = split_string(line_tokens[2], '/');
|
||||||
|
std::vector<std::string> vertex3 = split_string(line_tokens[3], '/');
|
||||||
|
|
||||||
|
process_vertex(vertex1, obj_textures, obj_normals, indicies, textures, normals);
|
||||||
|
process_vertex(vertex2, obj_textures, obj_normals, indicies, textures, normals);
|
||||||
|
process_vertex(vertex3, obj_textures, obj_normals, indicies, textures, normals);
|
||||||
|
} while (std::getline(file_stream, line));
|
||||||
|
|
||||||
|
file_stream.close();
|
||||||
|
|
||||||
|
const int texture_id = 0;
|
||||||
|
|
||||||
|
std::cout << "Texture ID: " << texture_id << std::endl;
|
||||||
|
|
||||||
|
// Insert everything into lit_vertices.
|
||||||
|
for (int i = 0; i < obj_vertices.size(); i++) {
|
||||||
|
vertices.emplace_back(simpleengine::Vectorf(obj_vertices.at(i)), glm::vec3(1.f), textures.at(i), normals.at(i), texture_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh::process_vertex(const std::vector<std::string>& vertex_data, const std::vector<glm::vec2>& in_textures,
|
||||||
|
const std::vector<glm::vec3>& in_normals, std::vector<GLuint>& out_indicies,
|
||||||
|
std::vector<glm::vec2>& out_textures, std::vector<glm::vec3>& out_normals) {
|
||||||
|
|
||||||
|
// Get the index the current vertex and put it in indicies
|
||||||
|
int currentVertexIndex = stoi(vertex_data[0]) - 1;
|
||||||
|
out_indicies.push_back(currentVertexIndex);
|
||||||
|
|
||||||
|
// Read texture coords
|
||||||
|
glm::vec2 current_tex = in_textures.at(stoi(vertex_data[1]) - 1);
|
||||||
|
current_tex.y = 1 - current_tex.y;
|
||||||
|
out_textures.at(currentVertexIndex) = current_tex;
|
||||||
|
|
||||||
|
// Read normals
|
||||||
|
glm::vec3 current_norm = in_normals.at(stoi(vertex_data[2]) - 1);
|
||||||
|
out_normals.at(currentVertexIndex) = current_norm;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh::destroy() {
|
||||||
|
this->ebo.destroy();
|
||||||
|
this->vbo.destroy();
|
||||||
|
this->vao.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh::update(const float& delta_time) {
|
||||||
|
this->rotate_y(1.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 Mesh::compute_face_normal(const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& p3) {
|
||||||
|
// Uses p2 as a new origin for p1,p3
|
||||||
|
auto a = p3 - p2;
|
||||||
|
auto b = p1 - p2;
|
||||||
|
|
||||||
|
// Compute the cross product a X b to get the face normal
|
||||||
|
return glm::normalize(glm::cross(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh::calculate_normals() {
|
||||||
|
std::vector<glm::vec3> normals = std::vector<glm::vec3>(vertices.size());
|
||||||
|
|
||||||
|
for (int i = 0; i < indicies.size(); i+=3) {
|
||||||
|
const glm::vec3& a = vertices[indicies[i]].position;
|
||||||
|
const glm::vec3& b = vertices[indicies[i + 1]].position;
|
||||||
|
const glm::vec3& c = vertices[indicies[i + 2]].position;
|
||||||
|
glm::vec3 normal = compute_face_normal(a, b, c);
|
||||||
|
|
||||||
|
normals[indicies[i]] += normal;
|
||||||
|
normals[indicies[i + 1]] += normal;
|
||||||
|
normals[indicies[i + 2]] += normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < normals.size(); i++) {
|
||||||
|
normals[i] = glm::normalize(normals[i]);
|
||||||
|
|
||||||
|
vertices[i].normal = normals[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,163 +1,114 @@
|
||||||
#include "gfx/model.h"
|
#include "gfx/model.h"
|
||||||
|
#include "gfx/material.h"
|
||||||
|
#include "gfx/texture.h"
|
||||||
|
#include "vector.h"
|
||||||
|
|
||||||
|
#include <assimp/Importer.hpp>
|
||||||
|
#include <assimp/material.h>
|
||||||
|
#include <assimp/scene.h>
|
||||||
|
#include <assimp/postprocess.h>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
namespace simpleengine::gfx {
|
namespace simpleengine::gfx {
|
||||||
Model::Model(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, Material material) :
|
Model::Model(std::string file_path) {
|
||||||
material(std::make_optional(material)), vertices(vertices), indicies(indicies),
|
load_model(file_path);
|
||||||
vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)), ebo(gfx::VBO::init(GL_ELEMENT_ARRAY_BUFFER, false)),
|
|
||||||
vao(gfx::VAO::init()) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Model::Model(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, std::optional<Material> material) :
|
void Model::load_model(std::string path) {
|
||||||
material(material), vertices(vertices), indicies(indicies),
|
Assimp::Importer importer;
|
||||||
vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)), ebo(gfx::VBO::init(GL_ELEMENT_ARRAY_BUFFER, false)),
|
|
||||||
vao(gfx::VAO::init()) {
|
|
||||||
|
|
||||||
|
// assimp post processing options: http://assimp.sourceforge.net/lib_html/postprocess_8h.html
|
||||||
|
const aiScene *scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);
|
||||||
|
|
||||||
|
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
|
||||||
|
std::cout << "ERROR::ASSIMP::" << importer.GetErrorString() << std::endl;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Model::Model(Material material,std::string filename) :
|
model_directory = path.substr(0, path.find_last_of('/'));
|
||||||
Model(material, std::ifstream(filename, std::ios::in | std::ios::binary)) {
|
|
||||||
|
|
||||||
|
process_node(scene->mRootNode, scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> split_string(std::string str, const char delim) {
|
void Model::process_node(aiNode* node, const aiScene* scene) {
|
||||||
std::istringstream ss(str);
|
// process all the node's meshes (if any)
|
||||||
|
for (int i = 0; i < node->mNumMeshes; i++) {
|
||||||
std::vector<std::string> tokens;
|
aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
|
||||||
size_t pos = 0;
|
meshes.push_back(process_mesh(mesh, scene));
|
||||||
std::string token;
|
|
||||||
while ((pos = str.find(delim)) != std::string::npos) {
|
|
||||||
token = str.substr(0, pos);
|
|
||||||
tokens.push_back(token);
|
|
||||||
str.erase(0, pos + 1);
|
|
||||||
}
|
|
||||||
tokens.push_back(str);
|
|
||||||
|
|
||||||
return tokens;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Model::Model(Material material, std::ifstream file_stream) :
|
// then do the same for each of its children
|
||||||
vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)), ebo(gfx::VBO::init(GL_ELEMENT_ARRAY_BUFFER, false)),
|
for (int i = 0; i < node->mNumChildren; i++) {
|
||||||
vao(gfx::VAO::init()), material(material) {
|
process_node(node->mChildren[i], scene);
|
||||||
|
|
||||||
if (!file_stream.is_open()) {
|
|
||||||
std::cerr << "File stream that was given to ObjModel::ObjModel is not open!" << std::endl;
|
|
||||||
throw std::runtime_error("Failed to open ObjModel model file");
|
|
||||||
}
|
|
||||||
|
|
||||||
// The vertices, texture coords, and normals that were read from the obj file
|
|
||||||
// these are not in a particular order.
|
|
||||||
std::vector<glm::vec3> obj_vertices;
|
|
||||||
std::vector<glm::vec2> obj_textures;
|
|
||||||
std::vector<glm::vec3> obj_normals;
|
|
||||||
|
|
||||||
// The texture coords and normals that have been sorted.
|
|
||||||
std::vector<glm::vec2> textures;
|
|
||||||
std::vector<glm::vec3> normals;
|
|
||||||
|
|
||||||
// Read the vertices, texture coords, and normals. Break when run into indices
|
|
||||||
std::string line;
|
|
||||||
while (std::getline(file_stream, line)) {
|
|
||||||
std::vector<std::string> line_tokens = split_string(line, ' ');
|
|
||||||
|
|
||||||
if (line_tokens.front() == "v") {
|
|
||||||
//glm::vec3 vertex(stof(line_tokens[1]), stof(line_tokens[2]), stof(line_tokens[3]));
|
|
||||||
obj_vertices.emplace_back(stof(line_tokens[1]), stof(line_tokens[2]), stof(line_tokens[3]));
|
|
||||||
} else if (line_tokens.front() == "vt") {
|
|
||||||
obj_textures.emplace_back(stof(line_tokens[1]), stof(line_tokens[2]));
|
|
||||||
} else if (line_tokens.front() == "vn") {
|
|
||||||
obj_normals.emplace_back(stof(line_tokens[1]), stof(line_tokens[2]), stof(line_tokens[3]));
|
|
||||||
} else if (line_tokens.front() == "f") {
|
|
||||||
auto size = obj_vertices.size();
|
|
||||||
textures.resize(size);
|
|
||||||
normals.resize(size);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process the indicies. This will sort everything for storing inside of the Vertex list.
|
gfx::Mesh Model::process_mesh(aiMesh* mesh, const aiScene* scene) {
|
||||||
do {
|
std::vector<LitVertex> vertices;
|
||||||
if (!line.starts_with("f")) {
|
std::vector<unsigned int> indices;
|
||||||
continue;
|
std::vector<Texture> textures;
|
||||||
|
|
||||||
|
for(unsigned int i = 0; i < mesh->mNumVertices; i++) {
|
||||||
|
LitVertex vertex;
|
||||||
|
vertex.color = glm::vec3(1.f);
|
||||||
|
vertex.texture_id = 0;
|
||||||
|
|
||||||
|
simpleengine::Vectorf position(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
|
||||||
|
vertex.position = position;
|
||||||
|
|
||||||
|
glm::vec3 normal(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z);
|
||||||
|
vertex.normal = normal;
|
||||||
|
|
||||||
|
if(mesh->mTextureCoords[0]) {
|
||||||
|
glm::vec2 tex_coord(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y);
|
||||||
|
|
||||||
|
vertex.tex_coord = tex_coord;
|
||||||
}
|
}
|
||||||
std::vector<std::string> line_tokens = split_string(line, ' ');
|
|
||||||
std::vector<std::string> vertex1 = split_string(line_tokens[1], '/');
|
|
||||||
std::vector<std::string> vertex2 = split_string(line_tokens[2], '/');
|
|
||||||
std::vector<std::string> vertex3 = split_string(line_tokens[3], '/');
|
|
||||||
|
|
||||||
process_vertex(vertex1, obj_textures, obj_normals, indicies, textures, normals);
|
vertices.push_back(vertex);
|
||||||
process_vertex(vertex2, obj_textures, obj_normals, indicies, textures, normals);
|
}
|
||||||
process_vertex(vertex3, obj_textures, obj_normals, indicies, textures, normals);
|
|
||||||
} while (std::getline(file_stream, line));
|
|
||||||
|
|
||||||
file_stream.close();
|
// Process indices
|
||||||
|
for (int i = 0; i < mesh->mNumFaces; i++) {
|
||||||
|
aiFace face = mesh->mFaces[i];
|
||||||
|
|
||||||
const int texture_id = 0;
|
for (int j = 0; j < face.mNumIndices; j++) {
|
||||||
|
indices.push_back(face.mIndices[j]);
|
||||||
std::cout << "Texture ID: " << texture_id << std::endl;
|
|
||||||
|
|
||||||
// Insert everything into lit_vertices.
|
|
||||||
for (int i = 0; i < obj_vertices.size(); i++) {
|
|
||||||
vertices.emplace_back(simpleengine::Vectorf(obj_vertices.at(i)), glm::vec3(1.f), textures.at(i), normals.at(i), texture_id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::process_vertex(const std::vector<std::string>& vertex_data, const std::vector<glm::vec2>& in_textures,
|
std::optional<gfx::Material> op_mat;
|
||||||
const std::vector<glm::vec3>& in_normals, std::vector<GLuint>& out_indicies,
|
|
||||||
std::vector<glm::vec2>& out_textures, std::vector<glm::vec3>& out_normals) {
|
|
||||||
|
|
||||||
// Get the index the current vertex and put it in indicies
|
// TODO: Process material
|
||||||
int currentVertexIndex = stoi(vertex_data[0]) - 1;
|
if(mesh->mMaterialIndex >= 0) {
|
||||||
out_indicies.push_back(currentVertexIndex);
|
std::cout << "TODO: Process model materials!" << std::endl;
|
||||||
|
|
||||||
// Read texture coords
|
/* aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex];
|
||||||
glm::vec2 current_tex = in_textures.at(stoi(vertex_data[1]) - 1);
|
std::vector<Texture> diffuseMaps = load_material_textures(material,
|
||||||
current_tex.y = 1 - current_tex.y;
|
aiTextureType_DIFFUSE, "texture_diffuse");
|
||||||
out_textures.at(currentVertexIndex) = current_tex;
|
|
||||||
|
|
||||||
// Read normals
|
textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
|
||||||
glm::vec3 current_norm = in_normals.at(stoi(vertex_data[2]) - 1);
|
|
||||||
out_normals.at(currentVertexIndex) = current_norm;
|
std::vector<Texture> specularMaps = load_material_textures(material,
|
||||||
|
aiTextureType_SPECULAR, "texture_specular");
|
||||||
|
textures.insert(textures.end(), specularMaps.begin(), specularMaps.end()); */
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::destroy() {
|
// TODO: After we start processing materials, this can be put in the else statement as a fallback.
|
||||||
this->ebo.destroy();
|
|
||||||
this->vbo.destroy();
|
auto white_texture = gfx::Texture::white_texture();
|
||||||
this->vao.destroy();
|
//gfx::Material mat(white_texture);
|
||||||
|
|
||||||
|
//gfx::Texture white_texture("examples/dev_testing/resources/white_texture.png");
|
||||||
|
gfx::Material mat(white_texture, 1.f, 0.f, 0.f, 0.f, 0.f);
|
||||||
|
|
||||||
|
op_mat = std::optional<gfx::Material>(mat);
|
||||||
|
|
||||||
|
//return Mesh(vertices, indices, textures);
|
||||||
|
return Mesh(vertices, indices, op_mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::update(const float& delta_time) {
|
std::vector<Texture> Model::load_material_textures(aiMaterial* material, aiTextureType* type, std::string type_name) {
|
||||||
this->rotate_y(1.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 Model::compute_face_normal(const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& p3) {
|
|
||||||
// Uses p2 as a new origin for p1,p3
|
|
||||||
auto a = p3 - p2;
|
|
||||||
auto b = p1 - p2;
|
|
||||||
|
|
||||||
// Compute the cross product a X b to get the face normal
|
|
||||||
return glm::normalize(glm::cross(a, b));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Model::calculate_normals() {
|
|
||||||
std::vector<glm::vec3> normals = std::vector<glm::vec3>(vertices.size());
|
|
||||||
|
|
||||||
for (int i = 0; i < indicies.size(); i+=3) {
|
|
||||||
const glm::vec3& a = vertices[indicies[i]].position;
|
|
||||||
const glm::vec3& b = vertices[indicies[i + 1]].position;
|
|
||||||
const glm::vec3& c = vertices[indicies[i + 2]].position;
|
|
||||||
glm::vec3 normal = compute_face_normal(a, b, c);
|
|
||||||
|
|
||||||
normals[indicies[i]] += normal;
|
|
||||||
normals[indicies[i + 1]] += normal;
|
|
||||||
normals[indicies[i + 2]] += normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < normals.size(); i++) {
|
|
||||||
normals[i] = glm::normalize(normals[i]);
|
|
||||||
|
|
||||||
vertices[i].normal = normals[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} // namespace simpleengine::gfx
|
|
@ -1,52 +1,17 @@
|
||||||
#include "gfx/renderer.h"
|
#include "gfx/renderer.h"
|
||||||
#include "ecs/component/component.h"
|
#include "ecs/component/component.h"
|
||||||
#include "ecs/entity.h"
|
#include "ecs/entity.h"
|
||||||
#include "gfx/model.h"
|
#include "gfx/mesh.h"
|
||||||
#include "gfx/vao.h"
|
#include "gfx/vao.h"
|
||||||
#include "renderable.h"
|
#include "renderable.h"
|
||||||
|
|
||||||
#include "ecs/component/model_componenet.h"
|
#include "ecs/component/mesh_component.h"
|
||||||
|
#include "ecs/component/model_component.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace simpleengine::gfx {
|
namespace simpleengine::gfx {
|
||||||
void Renderer::RenderingModel::update_buffers() {
|
void create_mesh_buffers(std::shared_ptr<simpleengine::Component> comp, simpleengine::gfx::Mesh& mesh);
|
||||||
if (std::shared_ptr<ModelComponent> comp = entity->get_component<simpleengine::ModelComponent>()) {
|
|
||||||
auto iter = component_models.find(comp->get_handle());
|
|
||||||
if (iter == component_models.end()) {
|
|
||||||
std::cout << "Enabling buffer attributes for ModelComponent (" << comp->get_handle() << ")..." << std::endl;
|
|
||||||
|
|
||||||
//iter->second = comp->model;
|
|
||||||
gfx::Model& model = comp->model;
|
|
||||||
gfx::VBO& vbo = model.vbo;
|
|
||||||
gfx::VBO& ebo = model.ebo;
|
|
||||||
gfx::VAO& vao = model.vao;
|
|
||||||
|
|
||||||
vao.bind();
|
|
||||||
vbo.buffer(model.vertices.data(), 0, sizeof(LitVertex) * model.vertices.size());
|
|
||||||
|
|
||||||
if (!model.indicies.empty()) {
|
|
||||||
ebo.buffer(model.indicies.data(), 0, model.indicies.size() * sizeof(GLuint));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable VAO attributes
|
|
||||||
vao.enable_attrib(vbo, 0, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, position), false);
|
|
||||||
vao.enable_attrib(vbo, 1, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, color), false);
|
|
||||||
vao.enable_attrib(vbo, 2, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, normal), false);
|
|
||||||
vao.enable_attrib(vbo, 3, 2, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, tex_coord), false);
|
|
||||||
vao.enable_attrib(vbo, 4, 1, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, texture_id), false);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
||||||
glBindVertexArray(0);
|
|
||||||
|
|
||||||
component_models.emplace(comp->get_handle(), model);
|
|
||||||
|
|
||||||
std::cout << "Enabled all buffer attributes for ModelComponent" << std::endl;
|
|
||||||
} else {
|
|
||||||
std::cout << "Already exists" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::RenderingModel::destroy_buffers() {
|
void Renderer::RenderingModel::destroy_buffers() {
|
||||||
std::cout << "Destroying entity models..." << std::endl;
|
std::cout << "Destroying entity models..." << std::endl;
|
||||||
|
@ -119,13 +84,13 @@ namespace simpleengine::gfx {
|
||||||
shader.use();
|
shader.use();
|
||||||
|
|
||||||
for (auto& [handle, rendering] : rendering_models) {
|
for (auto& [handle, rendering] : rendering_models) {
|
||||||
if (rendering.component_models.size() > 0) {
|
if (rendering.component_models.size() >= 0) {
|
||||||
std::shared_ptr<Entity>& entity = rendering.entity;
|
std::shared_ptr<Entity>& entity = rendering.entity;
|
||||||
|
|
||||||
shader.set_uniform_matrix_4f("transform_matrix", entity->transform_matrix, false);
|
shader.set_uniform_matrix_4f("transform_matrix", entity->transform_matrix, false);
|
||||||
|
|
||||||
for (const auto& pair : rendering.component_models) {
|
for (const auto& pair : rendering.component_models) {
|
||||||
Model& model = pair.second;
|
Mesh& model = pair.second;
|
||||||
std::optional<Material>& material = model.material;
|
std::optional<Material>& material = model.material;
|
||||||
|
|
||||||
shader.set_uniform_int("u_textures", 0, false);
|
shader.set_uniform_int("u_textures", 0, false);
|
||||||
|
@ -151,4 +116,64 @@ namespace simpleengine::gfx {
|
||||||
|
|
||||||
shader.unuse();
|
shader.unuse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer::RenderingModel::update_buffers() {
|
||||||
|
if (entity->has_component<simpleengine::MeshComponent>()) {
|
||||||
|
std::shared_ptr<MeshComponent> comp = entity->get_component<simpleengine::MeshComponent>();
|
||||||
|
auto iter = component_models.find(comp->get_handle());
|
||||||
|
if (iter == component_models.end()) {
|
||||||
|
std::cout << "Enabling buffer attributes for MeshComponent (" << comp->get_handle() << ")..." << std::endl;
|
||||||
|
|
||||||
|
//iter->second = comp->model;
|
||||||
|
gfx::Mesh& mesh = comp->model;
|
||||||
|
create_mesh_buffers(comp, mesh);
|
||||||
|
component_models.emplace(comp->get_handle(), mesh);
|
||||||
|
|
||||||
|
std::cout << "Enabled all buffer attributes for MeshComponent" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "Already exists" << std::endl;
|
||||||
|
}
|
||||||
|
} else if (entity->has_component<simpleengine::ModelComponent>()) {
|
||||||
|
std::shared_ptr<ModelComponent> comp = entity->get_component<simpleengine::ModelComponent>();
|
||||||
|
|
||||||
|
auto iter = component_models.find(comp->get_handle());
|
||||||
|
if (iter == component_models.end()) {
|
||||||
|
std::cout << "Enabling buffer attributes for ModelComponent (" << comp->get_handle() << ")..." << std::endl;
|
||||||
|
|
||||||
|
// Store all the model's meshes
|
||||||
|
for (auto& mesh : comp->model.meshes) {
|
||||||
|
create_mesh_buffers(comp, mesh);
|
||||||
|
|
||||||
|
component_models.emplace(comp->get_handle(), mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Enabled all buffer attributes for ModelComponent" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "Already exists" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_mesh_buffers(std::shared_ptr<Component> comp, gfx::Mesh& mesh) {
|
||||||
|
gfx::VBO& vbo = mesh.vbo;
|
||||||
|
gfx::VBO& ebo = mesh.ebo;
|
||||||
|
gfx::VAO& vao = mesh.vao;
|
||||||
|
|
||||||
|
vao.bind();
|
||||||
|
vbo.buffer(mesh.vertices.data(), 0, sizeof(LitVertex) * mesh.vertices.size());
|
||||||
|
|
||||||
|
if (!mesh.indicies.empty()) {
|
||||||
|
ebo.buffer(mesh.indicies.data(), 0, mesh.indicies.size() * sizeof(GLuint));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable VAO attributes
|
||||||
|
vao.enable_attrib(vbo, 0, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, position), false);
|
||||||
|
vao.enable_attrib(vbo, 1, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, color), false);
|
||||||
|
vao.enable_attrib(vbo, 2, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, normal), false);
|
||||||
|
vao.enable_attrib(vbo, 3, 2, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, tex_coord), false);
|
||||||
|
vao.enable_attrib(vbo, 4, 1, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, texture_id), false);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -4,16 +4,18 @@
|
||||||
#include <stb_image.h>
|
#include <stb_image.h>
|
||||||
|
|
||||||
namespace simpleengine::gfx {
|
namespace simpleengine::gfx {
|
||||||
Texture::Texture(const char* path, bool img_2d, bool mipmap) {
|
Texture::Texture(const char* path, Type type, bool img_2d, bool mipmap): type(type) {
|
||||||
image_type = img_2d ? GL_TEXTURE_2D : GL_TEXTURE_3D;
|
image_type_gl = img_2d ? GL_TEXTURE_2D : GL_TEXTURE_3D;
|
||||||
|
|
||||||
glGenTextures(1, &texture_id);
|
glGenTextures(1, &texture_id);
|
||||||
bind();
|
bind();
|
||||||
|
|
||||||
glTexParameteri(image_type, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
int linear_param = mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
|
||||||
glTexParameteri(image_type, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
||||||
glTexParameteri(image_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
glTexParameteri(image_type_gl, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
glTexParameteri(image_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(image_type_gl, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
glTexParameteri(image_type_gl, GL_TEXTURE_MIN_FILTER, linear_param);
|
||||||
|
glTexParameteri(image_type_gl, GL_TEXTURE_MAG_FILTER, linear_param);
|
||||||
|
|
||||||
// Read 4 channels (RGBA)
|
// Read 4 channels (RGBA)
|
||||||
img_data = stbi_load(path, &width, &height, &channels, 4);
|
img_data = stbi_load(path, &width, &height, &channels, 4);
|
||||||
|
@ -24,33 +26,27 @@ namespace simpleengine::gfx {
|
||||||
}
|
}
|
||||||
std::cout << "Loaded image with a width of " << width << "px, a height of " << height << "px and " << channels << " channels" << std::endl;
|
std::cout << "Loaded image with a width of " << width << "px, a height of " << height << "px and " << channels << " channels" << std::endl;
|
||||||
|
|
||||||
glTexImage2D(image_type, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data);
|
glTexImage2D(image_type_gl, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data);
|
||||||
|
|
||||||
if (mipmap) {
|
if (mipmap) {
|
||||||
glGenerateMipmap(image_type);
|
glGenerateMipmap(image_type_gl);
|
||||||
}
|
}
|
||||||
|
|
||||||
unbind();
|
unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
Texture::Texture(const unsigned char *const buffer, int buffer_length, Type type, bool img_2d, bool mipmap): type(type) {
|
||||||
* @brief Construct a new Texture object from the loaded file buffer.
|
image_type_gl = img_2d ? GL_TEXTURE_2D : GL_TEXTURE_3D;
|
||||||
*
|
|
||||||
* @param buffer The bytes of the loaded file.
|
|
||||||
* @param buffer_length The length of the buffer.
|
|
||||||
* @param img_2d Whether or not the texture is 2D.
|
|
||||||
* @param mipmap Whether or not to generate mipmaps for this texture.
|
|
||||||
*/
|
|
||||||
Texture::Texture(const unsigned char *const buffer, int buffer_length, bool img_2d, bool mipmap) {
|
|
||||||
image_type = img_2d ? GL_TEXTURE_2D : GL_TEXTURE_3D;
|
|
||||||
|
|
||||||
glGenTextures(1, &texture_id);
|
glGenTextures(1, &texture_id);
|
||||||
bind();
|
bind();
|
||||||
|
|
||||||
glTexParameteri(image_type, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
int linear_param = mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
|
||||||
glTexParameteri(image_type, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
||||||
glTexParameteri(image_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
glTexParameteri(image_type_gl, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
glTexParameteri(image_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(image_type_gl, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
glTexParameteri(image_type_gl, GL_TEXTURE_MIN_FILTER, linear_param);
|
||||||
|
glTexParameteri(image_type_gl, GL_TEXTURE_MAG_FILTER, linear_param);
|
||||||
|
|
||||||
// Read 4 channels (RGBA)
|
// Read 4 channels (RGBA)
|
||||||
img_data = stbi_load_from_memory(buffer, buffer_length, &width, &height, &channels, 4);
|
img_data = stbi_load_from_memory(buffer, buffer_length, &width, &height, &channels, 4);
|
||||||
|
@ -61,33 +57,61 @@ namespace simpleengine::gfx {
|
||||||
}
|
}
|
||||||
std::cout << "Loaded image with a width of " << width << "px, a height of " << height << "px and " << channels << " channels" << std::endl;
|
std::cout << "Loaded image with a width of " << width << "px, a height of " << height << "px and " << channels << " channels" << std::endl;
|
||||||
|
|
||||||
glTexImage2D(image_type, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data);
|
glTexImage2D(image_type_gl, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data);
|
||||||
|
|
||||||
if (mipmap) {
|
if (mipmap) {
|
||||||
glGenerateMipmap(image_type);
|
glGenerateMipmap(image_type_gl);
|
||||||
}
|
}
|
||||||
|
|
||||||
unbind();
|
unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
Texture::Texture(std::vector<unsigned char> buffer, Type type, bool img_2d, bool mipmap) :
|
||||||
* @brief Construct a new Texture object from the loaded file buffer.
|
Texture(buffer.data(), buffer.size(), type, img_2d, mipmap) {
|
||||||
*
|
|
||||||
* @param buffer The bytes of the loaded file.
|
|
||||||
* @param img_2d Whether or not the texture is 2D.
|
|
||||||
* @param mipmap Whether or not to generate mipmaps for this texture.
|
|
||||||
*/
|
|
||||||
Texture::Texture(std::vector<unsigned char> buffer, bool img_2d, bool mipmap) :
|
|
||||||
Texture(buffer.data(), buffer.size(), img_2d, mipmap) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Texture Texture::white_texture() {
|
||||||
|
// Create the texture
|
||||||
|
int width = 128, height = 128;
|
||||||
|
int size = width * height * sizeof(unsigned char) * 4;
|
||||||
|
unsigned char* data = (unsigned char*) malloc(size);
|
||||||
|
|
||||||
|
for(int i = 0; i < size; i++) {
|
||||||
|
data[i] = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture texture;
|
||||||
|
texture.image_type_gl = GL_TEXTURE_2D;
|
||||||
|
texture.width = width;
|
||||||
|
texture.height = height;
|
||||||
|
texture.channels = 4;
|
||||||
|
texture.type = Texture::Type::TexT_DIFFUSE;
|
||||||
|
texture.img_data = data;
|
||||||
|
|
||||||
|
glGenTextures(1, &texture.texture_id);
|
||||||
|
texture.bind();
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture.img_data);
|
||||||
|
|
||||||
|
texture.unbind();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
void Texture::bind() const {
|
void Texture::bind() const {
|
||||||
glBindTexture(image_type, texture_id);
|
glBindTexture(image_type_gl, texture_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::unbind() const {
|
void Texture::unbind() const {
|
||||||
glBindTexture(image_type, 0);
|
glBindTexture(image_type_gl, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Texture::get_texture_id() const {
|
unsigned int Texture::get_texture_id() const {
|
||||||
|
|
Loading…
Reference in New Issue