Compare commits
26 Commits
assignment
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 50a4f56e75 | |||
| c34d3f803f | |||
| 3b96b5008e | |||
| 9f0f8667ec | |||
| 58c761cb99 | |||
| 2d5f145c34 | |||
| 0931f3ce91 | |||
| 97606d398c | |||
| c30419899d | |||
| c1a5be6d90 | |||
| cf725c4c69 | |||
| d084ce8799 | |||
| 95275f9183 | |||
| 9124618ab6 | |||
| 1089861aa3 | |||
| 49219fc597 | |||
| db6e548476 | |||
| 22c46053c0 | |||
| 41c9b68eb9 | |||
| 74a0bfca41 | |||
| 4e2c62aaf4 | |||
| f1a24f576b | |||
| f981cee4e0 | |||
| 986e31dbef | |||
| 253bc47a5f | |||
| e07cdefacc |
56
.clang-format
Normal file
56
.clang-format
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
|
||||||
|
AccessModifierOffset: -8
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveAssignments: Consecutive
|
||||||
|
AlignConsecutiveDeclarations: Consecutive
|
||||||
|
AlignConsecutiveMacros: Consecutive
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
AlignOperands: DontAlign
|
||||||
|
AlignTrailingComments: Always
|
||||||
|
AllowShortBlocksOnASingleLine: Never
|
||||||
|
AllowShortEnumsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
AllowShortLambdasOnASingleLine: None
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: false
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: false
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: true
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
BeforeLambdaBody: false
|
||||||
|
BeforeWhile: false
|
||||||
|
IndentBraces: false
|
||||||
|
BreakBeforeBinaryOperators: NonAssignment
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
BreakInheritanceList: AfterColon
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializers: BeforeComma
|
||||||
|
BreakStringLiterals: false
|
||||||
|
ColumnLimit: 80
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
EmptyLineBeforeAccessModifier: Always
|
||||||
|
IndentAccessModifiers: false
|
||||||
|
IndentCaseBlocks: false
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentGotoLabels: false
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentWidth: 8
|
||||||
|
InsertNewlineAtEOF: true
|
||||||
|
InsertTrailingCommas: None
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
PackConstructorInitializers: NextLineOnly
|
||||||
|
PointerAlignment: Left
|
||||||
|
SortIncludes: Never
|
||||||
|
SpaceBeforeCaseColon: false
|
||||||
|
TabWidth: 8
|
||||||
|
UseTab: Always
|
||||||
64
.clang-tidy
Normal file
64
.clang-tidy
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
---
|
||||||
|
# C++ Core Guidelines style (CppCoreGuidelines)
|
||||||
|
Checks: >
|
||||||
|
cppcoreguidelines-*,
|
||||||
|
readability-identifier-naming,
|
||||||
|
readability-*,
|
||||||
|
modernize-*,
|
||||||
|
performance-*,
|
||||||
|
bugprone-*,
|
||||||
|
-modernize-use-trailing-return-type,
|
||||||
|
-readability-magic-numbers,
|
||||||
|
-cppcoreguidelines-avoid-magic-numbers,
|
||||||
|
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
|
||||||
|
-cppcoreguidelines-pro-type-reinterpret-cast
|
||||||
|
|
||||||
|
CheckOptions:
|
||||||
|
# C++ Core Guidelines: Types use PascalCase
|
||||||
|
- { key: readability-identifier-naming.ClassCase, value: CamelCase }
|
||||||
|
- { key: readability-identifier-naming.StructCase, value: CamelCase }
|
||||||
|
- { key: readability-identifier-naming.EnumCase, value: CamelCase }
|
||||||
|
- { key: readability-identifier-naming.UnionCase, value: CamelCase }
|
||||||
|
|
||||||
|
# C++ Core Guidelines: Functions use snake_case (STL style)
|
||||||
|
- { key: readability-identifier-naming.FunctionCase, value: lower_case }
|
||||||
|
- { key: readability-identifier-naming.MethodCase, value: lower_case }
|
||||||
|
|
||||||
|
# Member variables: snake_case with trailing underscore
|
||||||
|
- { key: readability-identifier-naming.PrivateMemberCase, value: lower_case }
|
||||||
|
- { key: readability-identifier-naming.PrivateMemberSuffix, value: '_' }
|
||||||
|
- { key: readability-identifier-naming.ProtectedMemberCase, value: lower_case }
|
||||||
|
- { key: readability-identifier-naming.ProtectedMemberSuffix, value: '_' }
|
||||||
|
- { key: readability-identifier-naming.PublicMemberCase, value: lower_case }
|
||||||
|
|
||||||
|
# Parameters and local variables: snake_case
|
||||||
|
- { key: readability-identifier-naming.ParameterCase, value: lower_case }
|
||||||
|
- { key: readability-identifier-naming.VariableCase, value: lower_case }
|
||||||
|
- { key: readability-identifier-naming.LocalVariableCase, value: lower_case }
|
||||||
|
|
||||||
|
# Constants and macros: UPPER_CASE
|
||||||
|
- { key: readability-identifier-naming.ConstantCase, value: UPPER_CASE }
|
||||||
|
- { key: readability-identifier-naming.ConstexprVariableCase, value: UPPER_CASE }
|
||||||
|
- { key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE }
|
||||||
|
- { key: readability-identifier-naming.EnumConstantCase, value: UPPER_CASE }
|
||||||
|
|
||||||
|
# Global variables: snake_case (Core Guidelines: avoid globals when possible)
|
||||||
|
- { key: readability-identifier-naming.GlobalVariableCase, value: lower_case }
|
||||||
|
|
||||||
|
# Namespaces: snake_case
|
||||||
|
- { key: readability-identifier-naming.NamespaceCase, value: lower_case }
|
||||||
|
|
||||||
|
# Template parameters: PascalCase (following STL conventions)
|
||||||
|
- { key: readability-identifier-naming.TypeTemplateParameterCase, value: CamelCase }
|
||||||
|
- { key: readability-identifier-naming.ValueTemplateParameterCase, value: lower_case }
|
||||||
|
|
||||||
|
# Type aliases: PascalCase (modern C++ style with 'using')
|
||||||
|
- { key: readability-identifier-naming.TypeAliasCase, value: CamelCase }
|
||||||
|
|
||||||
|
# Function size limits
|
||||||
|
- { key: readability-function-size.LineThreshold, value: 100 }
|
||||||
|
- { key: readability-function-size.StatementThreshold, value: 50 }
|
||||||
|
|
||||||
|
WarningsAsErrors: ''
|
||||||
|
HeaderFilterRegex: 'src/.*\.h$'
|
||||||
|
FormatStyle: file
|
||||||
176
.gitattributes
vendored
176
.gitattributes
vendored
@@ -43,7 +43,7 @@
|
|||||||
*.udk lock
|
*.udk lock
|
||||||
*.upk lock
|
*.upk lock
|
||||||
# Anything in `/RawContent` dir
|
# Anything in `/RawContent` dir
|
||||||
/RowContent/**/* lfs
|
/RawContent/**/* lfs
|
||||||
# Common files
|
# Common files
|
||||||
*.3ds lock
|
*.3ds lock
|
||||||
*.3DS lock
|
*.3DS lock
|
||||||
@@ -167,6 +167,8 @@
|
|||||||
*.TAR lfs
|
*.TAR lfs
|
||||||
*.tar.gz lfs
|
*.tar.gz lfs
|
||||||
*.TAR.GZ lfs
|
*.TAR.GZ lfs
|
||||||
|
*.tga lfs
|
||||||
|
*.TGA lfs
|
||||||
*.tif lfs
|
*.tif lfs
|
||||||
*.TIF lfs
|
*.TIF lfs
|
||||||
*.tiff lfs
|
*.tiff lfs
|
||||||
@@ -210,175 +212,3 @@
|
|||||||
*.DYLIB lfs
|
*.DYLIB lfs
|
||||||
*.pdb lfs
|
*.pdb lfs
|
||||||
*.PDB lfs
|
*.PDB lfs
|
||||||
*.locres filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.locmeta filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.ico filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.uasset filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.umap filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.udk filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.upk filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.3DS filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.ABC filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.AEP filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.AFDESIGN filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.AFPHOTO filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.AI filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.AIF filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.AVI filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.BANK filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.BGEO filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.BIN filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.BLEND filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.BMP filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.BPOLY filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.C4D filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.DOC filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.DOCX filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.DWG filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.DXF filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.EXR filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.FBX filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.GEO filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.GI filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.GI2 filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.GIF filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.GLB filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.GLTF filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.HDR filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.HIP filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.HIPLC filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.HIPNC filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.JPEG filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.JPG filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.MA filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.MAX filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.MB filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.MOV filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.MP3 filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.MP4 filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.MPEG filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.MPG filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.OBJ filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.PDF filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.PFM filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.PIC filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.PMB filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.PNG filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.POLY filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.PPT filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.PPTX filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.PROFRAW filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.PRPROJ filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.PSB filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.PSD filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.RAR filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.RAT filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.RIB filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.SKETCH filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.STL filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.TAR filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.TAR.GZ filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.TIF filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.TIFF filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.TMP filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.UEXP filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.USD filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.USDC filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.USDZ filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.VDB filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.VOX filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.WAV filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.XCF filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.XLS filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.XLSX filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.ZIP filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.3ds filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.abc filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.aep filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.afdesign filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.afphoto filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.ai filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.aif filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.avi filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.bank filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.bgeo filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.bin filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.blend filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.bmp filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.bpoly filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.c4d filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.doc filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.docx filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.dwg filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.dxf filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.exr filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.fbx filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.geo filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.gi filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.gi2 filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.gif filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.glb filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.gltf filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.hdr filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.hip filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.hiplc filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.hipnc filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.jpeg filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.ma filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.max filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.mb filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.mov filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.mp3 filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.mp4 filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.mpeg filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.mpg filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.obj filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.pdf filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.pfm filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.pic filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.pmb filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.png filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.poly filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.ppt filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.pptx filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.profraw filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.prproj filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.psb filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.psd filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.rar filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.rat filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.rib filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.sketch filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.stl filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.tar filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.tar.gz filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.tif filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.tiff filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.tmp filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.uexp filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.usd filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.usdc filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.usdz filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.vdb filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.vox filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.wav filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.xcf filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.xls filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.xlsx filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.a filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.A filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.lib filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.LIB filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.exe filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.EXE filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.dll filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.DLL filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.so filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.SO filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.dylib filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.DYLIB filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.pdb filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.PDB filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.tga filter=lfs diff=lfs merge=lfs -text
|
|
||||||
|
|||||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -90,5 +90,9 @@ Mkfile.old
|
|||||||
dkms.conf
|
dkms.conf
|
||||||
|
|
||||||
# Build directory
|
# Build directory
|
||||||
Build/
|
build/
|
||||||
**/Build/
|
**/build/
|
||||||
|
|
||||||
|
# Asset directory
|
||||||
|
!data/
|
||||||
|
!data/**
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
# U-Tad: 3D Programming
|
# U-Tad - 3D Programming
|
||||||
|
|
||||||
"3D Programming" subject assignments from the U-Tad's Master Degree in Video Game Programming.
|
"3D Programming" subject assignments from the U-Tad's Master Degree in Video Game Programming.
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
varying vec3 fcolor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_FragColor = vec4(fcolor, 1);
|
|
||||||
}
|
|
||||||
35
data/models/box_stack.mtl
Normal file
35
data/models/box_stack.mtl
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Blender MTL File: 'box_stack.blend'
|
||||||
|
# Material Count: 3
|
||||||
|
|
||||||
|
newmtl mat_bot
|
||||||
|
Ns 96.078431
|
||||||
|
Ka 0.000000 1.000000 1.000000
|
||||||
|
Kd 0.640000 0.640000 0.640000
|
||||||
|
Ks 0.500000 0.500000 0.500000
|
||||||
|
Ke 0.000000 0.000000 0.000000
|
||||||
|
Ni 1.000000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
map_Ka top.png
|
||||||
|
|
||||||
|
newmtl mat_mid
|
||||||
|
Ns 96.078431
|
||||||
|
Ka 0.600000 0.600000 0.000000
|
||||||
|
Kd 0.640000 0.640000 0.000000
|
||||||
|
Ks 0.500000 0.500000 0.500000
|
||||||
|
Ke 0.000000 0.000000 0.000000
|
||||||
|
Ni 1.000000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
map_Ka front.png
|
||||||
|
|
||||||
|
newmtl mat_top
|
||||||
|
Ns 96.078431
|
||||||
|
Ka 1.000000 0.000000 1.000000
|
||||||
|
Kd 0.640000 0.640000 0.640000
|
||||||
|
Ks 0.500000 0.500000 0.500000
|
||||||
|
Ke 0.000000 0.000000 0.000000
|
||||||
|
Ni 1.000000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
map_Ka top.png
|
||||||
BIN
data/models/box_stack.obj
(Stored with Git LFS)
Normal file
BIN
data/models/box_stack.obj
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
data/models/front.png
(Stored with Git LFS)
Normal file
BIN
data/models/front.png
(Stored with Git LFS)
Normal file
Binary file not shown.
32
data/models/gunslinger.mtl
Normal file
32
data/models/gunslinger.mtl
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware
|
||||||
|
# File Created: 21.07.2015 23:00:44
|
||||||
|
|
||||||
|
newmtl revolver
|
||||||
|
Ns 30.0000
|
||||||
|
Ni 1.5000
|
||||||
|
d 1.0000
|
||||||
|
Tr 0.0000
|
||||||
|
Tf 1.0000 1.0000 1.0000
|
||||||
|
illum 2
|
||||||
|
Ka 0.5500 0.5500 0.5500
|
||||||
|
Kd 0.5500 0.5500 0.5500
|
||||||
|
Ks 0.0000 0.0000 0.0000
|
||||||
|
Ke 0.0000 0.0000 0.0000
|
||||||
|
map_Ka revolver_dfs.tga
|
||||||
|
map_Kd revolver_dfs.tga
|
||||||
|
map_bump revolver_nrm.tga
|
||||||
|
bump revolver_nrm.tga
|
||||||
|
|
||||||
|
newmtl gunslinger
|
||||||
|
Ns 30.0000
|
||||||
|
Ni 1.5000
|
||||||
|
d 1.0000
|
||||||
|
Tr 0.0000
|
||||||
|
Tf 1.0000 1.0000 1.0000
|
||||||
|
illum 2
|
||||||
|
Ka 0.5500 0.5500 0.5500
|
||||||
|
Kd 0.5500 0.5500 0.5500
|
||||||
|
Ks 0.0000 0.0000 0.0000
|
||||||
|
Ke 0.0000 0.0000 0.0000
|
||||||
|
map_Ka gunslinger_dfs.tga
|
||||||
|
map_Kd gunslinger_dfs.tga
|
||||||
BIN
data/models/gunslinger.obj
(Stored with Git LFS)
Normal file
BIN
data/models/gunslinger.obj
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
data/models/gunslinger_dfs.bmp
(Stored with Git LFS)
Normal file
BIN
data/models/gunslinger_dfs.bmp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
data/models/gunslinger_dfs.tga
(Stored with Git LFS)
Normal file
BIN
data/models/gunslinger_dfs.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
data/models/gunslinger_nrm.tga
(Stored with Git LFS)
Normal file
BIN
data/models/gunslinger_nrm.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
data/models/gunslinger_spc.tga
(Stored with Git LFS)
Normal file
BIN
data/models/gunslinger_spc.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
data/models/revolver_dfs.tga
(Stored with Git LFS)
Normal file
BIN
data/models/revolver_dfs.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
data/models/revolver_nrm.tga
(Stored with Git LFS)
Normal file
BIN
data/models/revolver_nrm.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
data/models/revolver_spc.tga
(Stored with Git LFS)
Normal file
BIN
data/models/revolver_spc.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
data/models/top.png
(Stored with Git LFS)
Normal file
BIN
data/models/top.png
(Stored with Git LFS)
Normal file
Binary file not shown.
68
data/shaders/fragment.glsl
Normal file
68
data/shaders/fragment.glsl
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
uniform int useTexture;
|
||||||
|
uniform sampler2D texSampler;
|
||||||
|
uniform int numLights;
|
||||||
|
uniform vec4 materialColor;
|
||||||
|
uniform float shininess;
|
||||||
|
uniform vec3 ambientLight;
|
||||||
|
|
||||||
|
struct Light {
|
||||||
|
vec4 vector;
|
||||||
|
vec3 color;
|
||||||
|
float intensity;
|
||||||
|
float linear_att;
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform Light lights[10];
|
||||||
|
|
||||||
|
varying vec3 fcolor;
|
||||||
|
varying vec2 ftexcoord;
|
||||||
|
varying vec3 fnormal;
|
||||||
|
varying vec4 fposition;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec3 diffuseAccum = vec3(0.0, 0.0, 0.0);
|
||||||
|
vec3 specularAccum = vec3(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
if (numLights > 0) {
|
||||||
|
diffuseAccum = ambientLight;
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
if (i >= numLights) break;
|
||||||
|
|
||||||
|
vec3 N = normalize(fnormal);
|
||||||
|
vec3 L = lights[i].vector.xyz;
|
||||||
|
float attenuation = 1.0;
|
||||||
|
|
||||||
|
if (lights[i].vector.w == 1.0) {
|
||||||
|
L = L - fposition.xyz;
|
||||||
|
float distance = length(L);
|
||||||
|
attenuation = 1.0 / (1.0 + lights[i].linear_att * distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
L = normalize(L);
|
||||||
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
|
|
||||||
|
diffuseAccum += NdotL * lights[i].color * lights[i].intensity * attenuation;
|
||||||
|
|
||||||
|
if (shininess > 0.0 && NdotL > 0.0) {
|
||||||
|
vec3 V = normalize(-fposition.xyz);
|
||||||
|
vec3 H = normalize(L + V);
|
||||||
|
float NdotH = max(dot(N, H), 0.0);
|
||||||
|
specularAccum += pow(NdotH, shininess) * attenuation * lights[i].color * lights[i].intensity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 fragmentColor;
|
||||||
|
if (useTexture == 1) {
|
||||||
|
fragmentColor = texture2D(texSampler, ftexcoord);
|
||||||
|
} else {
|
||||||
|
fragmentColor = materialColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numLights > 0) {
|
||||||
|
gl_FragColor = vec4(fragmentColor.rgb * diffuseAccum + specularAccum, fragmentColor.a);
|
||||||
|
} else {
|
||||||
|
gl_FragColor = fragmentColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
19
data/shaders/vertex.glsl
Normal file
19
data/shaders/vertex.glsl
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
uniform mat4 mvp;
|
||||||
|
uniform mat4 modelView;
|
||||||
|
uniform mat4 normalMatrix;
|
||||||
|
attribute vec3 vpos;
|
||||||
|
attribute vec3 vcolor;
|
||||||
|
attribute vec2 vtexcoord;
|
||||||
|
attribute vec3 vnormal;
|
||||||
|
varying vec3 fcolor;
|
||||||
|
varying vec2 ftexcoord;
|
||||||
|
varying vec3 fnormal;
|
||||||
|
varying vec4 fposition;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = mvp * vec4(vpos, 1);
|
||||||
|
fcolor = vcolor;
|
||||||
|
ftexcoord = vtexcoord;
|
||||||
|
fnormal = vec3(normalMatrix * vec4(vnormal, 0.0));
|
||||||
|
fposition = modelView * vec4(vpos, 1);
|
||||||
|
}
|
||||||
BIN
data/textures/front.png
(Stored with Git LFS)
Normal file
BIN
data/textures/front.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
data/textures/top.png
(Stored with Git LFS)
Normal file
BIN
data/textures/top.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@@ -1,9 +0,0 @@
|
|||||||
uniform mat4 mvp;
|
|
||||||
attribute vec3 vpos;
|
|
||||||
attribute vec3 vcolor;
|
|
||||||
varying vec3 fcolor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = mvp * vec4(vpos, 1);
|
|
||||||
fcolor = vcolor;
|
|
||||||
}
|
|
||||||
7187
lib/stb_image.h
Normal file
7187
lib/stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
2029
lib/tiny_obj_loader.h
Normal file
2029
lib/tiny_obj_loader.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,71 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<Filter Include="Source Files">
|
|
||||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
|
||||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Header Files">
|
|
||||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
|
||||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Resource Files">
|
|
||||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
|
||||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="glfw">
|
|
||||||
<UniqueIdentifier>{422e20da-2cf0-4bda-9833-a89b7ab453a1}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="glew">
|
|
||||||
<UniqueIdentifier>{296e1ba9-28bc-4e0b-8d4e-413551edca96}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Shaders">
|
|
||||||
<UniqueIdentifier>{0628083b-a31c-4825-822c-11b6f933e7bd}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="..\lib\glfw\glfw3.h">
|
|
||||||
<Filter>glfw</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\lib\glfw\glfw3native.h">
|
|
||||||
<Filter>glfw</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\lib\glew\GL\glew.h">
|
|
||||||
<Filter>glew</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\src\vertex.h">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\src\shader.h">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\src\buffer.h">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="..\src\main.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\lib\glew\glew.c">
|
|
||||||
<Filter>glew</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\src\vertex.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\src\shader.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\src\buffer.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="..\data\fragment.glsl">
|
|
||||||
<Filter>Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="..\data\vertex.glsl">
|
|
||||||
<Filter>Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "../lib/glew/GL/glew.h"
|
#include "../lib/glew/GL/glew.h"
|
||||||
#include "../lib/glfw/glfw3.h"
|
#include "../lib/glfw/glfw3.h"
|
||||||
|
|
||||||
|
#include "logger.h"
|
||||||
#include "vertex.h"
|
#include "vertex.h"
|
||||||
|
|
||||||
Buffer::Buffer(const std::vector<Vertex>& vertices, const std::vector<uint16_t>& indices)
|
Buffer::Buffer(const std::vector<Vertex>& vertices,
|
||||||
|
const std::vector<uint16_t>& indices)
|
||||||
{
|
{
|
||||||
index_count_ = static_cast<GLsizei>(indices.size());
|
index_count_ = static_cast<GLsizei>(indices.size());
|
||||||
|
|
||||||
@@ -19,13 +20,18 @@ Buffer::Buffer(const std::vector<Vertex>& vertices, const std::vector<uint16_t>&
|
|||||||
glBindVertexArray(vao_);
|
glBindVertexArray(vao_);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
|
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
|
||||||
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex),
|
||||||
|
vertices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(uint16_t), indices.data(), GL_STATIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(uint16_t),
|
||||||
|
indices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);
|
// Note: Vertex attributes are set up by Shader::setup_attribs() during rendering
|
||||||
glEnableVertexAttribArray(0);
|
// This allows the shader to dynamically query and set the correct attribute locations
|
||||||
|
|
||||||
|
Logger::info(sstr("Buffer created with ", vertices.size(),
|
||||||
|
" vertices and ", indices.size(), " indices"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer::~Buffer()
|
Buffer::~Buffer()
|
||||||
@@ -33,13 +39,14 @@ Buffer::~Buffer()
|
|||||||
glDeleteVertexArrays(1, &vao_);
|
glDeleteVertexArrays(1, &vao_);
|
||||||
glDeleteBuffers(1, &vbo_);
|
glDeleteBuffers(1, &vbo_);
|
||||||
glDeleteBuffers(1, &ebo_);
|
glDeleteBuffers(1, &ebo_);
|
||||||
|
Logger::info("Buffer destroyed");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::Draw(const Shader& shader) const
|
void Buffer::draw(const Shader& shader) const
|
||||||
{
|
{
|
||||||
glBindVertexArray(vao_);
|
glBindVertexArray(vao_);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
|
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_);
|
||||||
shader.SetupAttribs();
|
shader.setup_attribs();
|
||||||
glDrawElements(GL_TRIANGLES, index_count_, GL_UNSIGNED_SHORT, nullptr);
|
glDrawElements(GL_TRIANGLES, index_count_, GL_UNSIGNED_SHORT, nullptr);
|
||||||
}
|
}
|
||||||
@@ -10,10 +10,11 @@
|
|||||||
|
|
||||||
class Buffer {
|
class Buffer {
|
||||||
public:
|
public:
|
||||||
Buffer(const std::vector<Vertex>& vertices, const std::vector<uint16_t>& indices);
|
Buffer(const std::vector<Vertex>& vertices,
|
||||||
|
const std::vector<uint16_t>& indices);
|
||||||
~Buffer();
|
~Buffer();
|
||||||
|
|
||||||
void Draw(const Shader& shader) const;
|
void draw(const Shader& shader) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t vao_, vbo_, ebo_;
|
uint32_t vao_, vbo_, ebo_;
|
||||||
|
|||||||
41
src/camera.cpp
Normal file
41
src/camera.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include "camera.h"
|
||||||
|
#include "state.h"
|
||||||
|
#include "../lib/glew/GL/glew.h"
|
||||||
|
#include "../lib/glm/gtc/matrix_transform.hpp"
|
||||||
|
|
||||||
|
Camera::Camera()
|
||||||
|
: projection_(glm::mat4(1.0f))
|
||||||
|
, viewport_(0, 0, 800, 600)
|
||||||
|
, clear_color_(0.0f, 0.0f, 0.0f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Camera::prepare()
|
||||||
|
{
|
||||||
|
// Set projection matrix
|
||||||
|
state::projection_matrix = projection_;
|
||||||
|
|
||||||
|
// Calculate view matrix
|
||||||
|
// For a camera, we need the inverse transformation:
|
||||||
|
// View = inverse(Translation * Rotation)
|
||||||
|
// Which is: Rotation^-1 * Translation^-1
|
||||||
|
glm::mat4 view = glm::mat4(1.0f);
|
||||||
|
|
||||||
|
// Inverse rotation (rotate in opposite direction)
|
||||||
|
view = glm::rotate(view, -rotation_.z, glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
|
view = glm::rotate(view, -rotation_.y, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
view = glm::rotate(view, -rotation_.x, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||||
|
|
||||||
|
// Inverse translation (translate in opposite direction)
|
||||||
|
view = glm::translate(view, -position_);
|
||||||
|
|
||||||
|
state::view_matrix = view;
|
||||||
|
|
||||||
|
// Set viewport
|
||||||
|
glViewport(viewport_.x, viewport_.y, viewport_.z, viewport_.w);
|
||||||
|
glScissor(viewport_.x, viewport_.y, viewport_.z, viewport_.w);
|
||||||
|
|
||||||
|
// Set clear color and clear buffers
|
||||||
|
glClearColor(clear_color_.r, clear_color_.g, clear_color_.b, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
}
|
||||||
46
src/camera.h
Normal file
46
src/camera.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#ifndef CAMERA_H_
|
||||||
|
#define CAMERA_H_
|
||||||
|
|
||||||
|
#include "entity.h"
|
||||||
|
#include "../lib/glm/glm.hpp"
|
||||||
|
|
||||||
|
class Camera : public Entity {
|
||||||
|
public:
|
||||||
|
Camera();
|
||||||
|
|
||||||
|
[[nodiscard]] const glm::mat4& projection() const
|
||||||
|
{
|
||||||
|
return projection_;
|
||||||
|
}
|
||||||
|
void set_projection(const glm::mat4& proj)
|
||||||
|
{
|
||||||
|
projection_ = proj;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const glm::ivec4& viewport() const
|
||||||
|
{
|
||||||
|
return viewport_;
|
||||||
|
}
|
||||||
|
void set_viewport(const glm::ivec4& vp)
|
||||||
|
{
|
||||||
|
viewport_ = vp;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const glm::vec3& clear_color() const
|
||||||
|
{
|
||||||
|
return clear_color_;
|
||||||
|
}
|
||||||
|
void set_clear_color(const glm::vec3& color)
|
||||||
|
{
|
||||||
|
clear_color_ = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepare();
|
||||||
|
|
||||||
|
private:
|
||||||
|
glm::mat4 projection_;
|
||||||
|
glm::ivec4 viewport_;
|
||||||
|
glm::vec3 clear_color_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CAMERA_H_
|
||||||
283
src/engine.cpp
Normal file
283
src/engine.cpp
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
#include "engine.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../lib/glew/GL/glew.h"
|
||||||
|
#include "../lib/glfw/glfw3.h"
|
||||||
|
#include "../lib/glm/glm.hpp"
|
||||||
|
#include "../lib/glm/gtc/matrix_transform.hpp"
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "camera.h"
|
||||||
|
#include "light.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "material.h"
|
||||||
|
#include "mesh.h"
|
||||||
|
#include "model.h"
|
||||||
|
#include "shader.h"
|
||||||
|
#include "state.h"
|
||||||
|
#include "texture.h"
|
||||||
|
#include "vertex.h"
|
||||||
|
#include "world.h"
|
||||||
|
|
||||||
|
// Instance variables
|
||||||
|
std::shared_ptr<Light> point_light;
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
constexpr int screen_width = 800;
|
||||||
|
constexpr int screen_height = 600;
|
||||||
|
constexpr double fps_limit = 1.0 / 60.0;
|
||||||
|
|
||||||
|
Engine::Engine()
|
||||||
|
: window_(nullptr)
|
||||||
|
, screen_width_(screen_width)
|
||||||
|
, screen_height_(screen_height)
|
||||||
|
, last_update_time_(0.0)
|
||||||
|
, last_frame_time_(0.0)
|
||||||
|
, angle_(0.0)
|
||||||
|
{
|
||||||
|
Logger::info("Engine created");
|
||||||
|
}
|
||||||
|
|
||||||
|
Engine::~Engine()
|
||||||
|
{
|
||||||
|
Logger::info("Engine destroyed");
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::initialize()
|
||||||
|
{
|
||||||
|
Logger::info("Initializing engine...");
|
||||||
|
|
||||||
|
// Initialize GLFW
|
||||||
|
if (!glfwInit()) {
|
||||||
|
Logger::error("Failed to initialize GLFW");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Logger::info("GLFW initialized successfully");
|
||||||
|
|
||||||
|
glfwWindowHint(GLFW_RESIZABLE, false);
|
||||||
|
glfwWindowHint(GLFW_SAMPLES, 8);
|
||||||
|
|
||||||
|
// Create window
|
||||||
|
window_ = glfwCreateWindow(screen_width_, screen_height_,
|
||||||
|
"Daniel Poveda", nullptr, nullptr);
|
||||||
|
if (window_ == nullptr) {
|
||||||
|
Logger::error("Failed to create OpenGL window");
|
||||||
|
glfwTerminate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
glfwMakeContextCurrent(window_);
|
||||||
|
|
||||||
|
// Enable OpenGL features
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
Logger::info(
|
||||||
|
sstr("OpenGL initialized, version: ",
|
||||||
|
reinterpret_cast<const char*>(glGetString(GL_VERSION))));
|
||||||
|
|
||||||
|
// Initialize GLEW
|
||||||
|
glewExperimental = GL_TRUE;
|
||||||
|
GLenum err = glewInit();
|
||||||
|
if (err != GLEW_OK) {
|
||||||
|
Logger::error(sstr(
|
||||||
|
"Failed to initialize GLEW: ",
|
||||||
|
reinterpret_cast<const char*>(glewGetErrorString(err))));
|
||||||
|
glfwTerminate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize default shader
|
||||||
|
Logger::info("Loading default shaders...");
|
||||||
|
state::default_shader = std::make_shared<Shader>(
|
||||||
|
"data/shaders/vertex.glsl", "data/shaders/fragment.glsl");
|
||||||
|
if (std::strlen(state::default_shader->error()) > 0) {
|
||||||
|
Logger::error(sstr("Failed to initialize shaders: ",
|
||||||
|
state::default_shader->error()));
|
||||||
|
} else {
|
||||||
|
Logger::info("Default shaders loaded successfully");
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::info("Engine initialization complete");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::run()
|
||||||
|
{
|
||||||
|
Logger::info("Starting game loop...");
|
||||||
|
|
||||||
|
setup();
|
||||||
|
start();
|
||||||
|
|
||||||
|
last_update_time_ = glfwGetTime();
|
||||||
|
last_frame_time_ = glfwGetTime();
|
||||||
|
|
||||||
|
while (is_running()) {
|
||||||
|
const double now = glfwGetTime();
|
||||||
|
const double delta_time = now - last_update_time_;
|
||||||
|
|
||||||
|
process_input(delta_time);
|
||||||
|
update(delta_time);
|
||||||
|
|
||||||
|
if (now - last_frame_time_ >= fps_limit) {
|
||||||
|
render();
|
||||||
|
last_frame_time_ = now;
|
||||||
|
}
|
||||||
|
last_update_time_ = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::info("Game loop ended");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::destroy()
|
||||||
|
{
|
||||||
|
if (window_) {
|
||||||
|
Logger::info("Shutting down engine...");
|
||||||
|
glfwTerminate();
|
||||||
|
window_ = nullptr;
|
||||||
|
Logger::info("Engine shutdown complete");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::setup()
|
||||||
|
{
|
||||||
|
Logger::info("Setting up scene...");
|
||||||
|
|
||||||
|
// Create world
|
||||||
|
world_ = std::make_unique<World>();
|
||||||
|
world_->set_ambient(glm::vec3(0.2f, 0.2f, 0.2f));
|
||||||
|
Logger::info("World created");
|
||||||
|
|
||||||
|
// Create camera
|
||||||
|
camera_ = std::make_shared<Camera>();
|
||||||
|
camera_->set_position(glm::vec3(0.0f, 4.0f, 12.0f));
|
||||||
|
camera_->set_rotation(glm::vec3(glm::radians(-20.0f), 0.0f, 0.0f));
|
||||||
|
camera_->set_projection(
|
||||||
|
glm::perspective(glm::radians(45.0f),
|
||||||
|
static_cast<float>(screen_width_)
|
||||||
|
/ static_cast<float>(screen_height_),
|
||||||
|
0.1f, 100.0f));
|
||||||
|
camera_->set_viewport(glm::ivec4(0, 0, screen_width_, screen_height_));
|
||||||
|
camera_->set_clear_color(glm::vec3(0.1f, 0.1f, 0.1f));
|
||||||
|
world_->add_entity(camera_);
|
||||||
|
Logger::info("Camera created and added to world");
|
||||||
|
|
||||||
|
// Load the box_stack model
|
||||||
|
auto box_stack_mesh = Mesh::load("data/models/box_stack.obj");
|
||||||
|
if (box_stack_mesh) {
|
||||||
|
auto box_stack_model = std::make_shared<Model>(box_stack_mesh);
|
||||||
|
box_stack_model->set_position(glm::vec3(-2.0f, -1.25f, 0.0f));
|
||||||
|
models_.push_back(box_stack_model);
|
||||||
|
world_->add_entity(box_stack_model);
|
||||||
|
Logger::info("Box stack model loaded and added to world");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the gunslinger model
|
||||||
|
auto gunslinger_mesh = Mesh::load("data/models/gunslinger.obj");
|
||||||
|
if (gunslinger_mesh) {
|
||||||
|
auto gunslinger_model =
|
||||||
|
std::make_shared<Model>(gunslinger_mesh);
|
||||||
|
gunslinger_model->set_position(glm::vec3(2.0f, 0.0f, 0.0f));
|
||||||
|
gunslinger_model->set_rotation(
|
||||||
|
glm::vec3(0.0f, glm::radians(-30.0f), 0.0f));
|
||||||
|
gunslinger_model->set_scale(glm::vec3(0.1f, 0.1f, 0.1f));
|
||||||
|
models_.push_back(gunslinger_model);
|
||||||
|
world_->add_entity(gunslinger_model);
|
||||||
|
Logger::info("Gunslinger model loaded and added to world");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create directional light
|
||||||
|
auto directional_light = std::make_shared<Light>();
|
||||||
|
directional_light->set_type(Light::Type::DIRECTIONAL);
|
||||||
|
directional_light->set_color(glm::vec3(1.0f, 1.0f, 1.0f));
|
||||||
|
directional_light->set_intensity(1.0f);
|
||||||
|
directional_light->set_position(glm::normalize(
|
||||||
|
glm::vec3(1.0f, 1.0f, 1.0f))); // Use position as direction
|
||||||
|
world_->add_entity(directional_light);
|
||||||
|
Logger::info("Directional light created and added to world");
|
||||||
|
|
||||||
|
// Create point light
|
||||||
|
point_light = std::make_shared<Light>();
|
||||||
|
point_light->set_type(Light::Type::POINT);
|
||||||
|
point_light->set_color(glm::vec3(1.0f, 0.0f, 0.0f));
|
||||||
|
point_light->set_intensity(2.0f);
|
||||||
|
point_light->set_linear_attenuation(0.2f);
|
||||||
|
point_light->set_position(glm::vec3(5.0f, 0.0f, 0.0f));
|
||||||
|
world_->add_entity(point_light);
|
||||||
|
Logger::info("Point light created and added to world");
|
||||||
|
|
||||||
|
Logger::info("Scene setup complete");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::start()
|
||||||
|
{
|
||||||
|
// Called once after setup, before the main loop
|
||||||
|
// Can be used for initialization that needs the scene to be ready
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::process_input(const double delta_time)
|
||||||
|
{
|
||||||
|
glfwPollEvents();
|
||||||
|
|
||||||
|
if (!camera_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr float camera_speed = 7.5f;
|
||||||
|
|
||||||
|
glm::vec3 forward = glm::vec3(0.0f, 0.0f, -1.0f);
|
||||||
|
glm::vec3 right = glm::vec3(1.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
glm::mat4 rotation = glm::mat4(1.0f);
|
||||||
|
rotation = glm::rotate(rotation, camera_->rotation().y,
|
||||||
|
glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
rotation = glm::rotate(rotation, camera_->rotation().x,
|
||||||
|
glm::vec3(1.0f, 0.0f, 0.0f));
|
||||||
|
forward = glm::vec3(rotation * glm::vec4(forward, 0.0f));
|
||||||
|
right = glm::vec3(rotation * glm::vec4(right, 0.0f));
|
||||||
|
|
||||||
|
const float movement = camera_speed * static_cast<float>(delta_time);
|
||||||
|
if (glfwGetKey(window_, GLFW_KEY_UP) == GLFW_PRESS) {
|
||||||
|
camera_->set_position(camera_->position() + forward * movement);
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window_, GLFW_KEY_DOWN) == GLFW_PRESS) {
|
||||||
|
camera_->set_position(camera_->position() - forward * movement);
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window_, GLFW_KEY_LEFT) == GLFW_PRESS) {
|
||||||
|
camera_->set_position(camera_->position() - right * movement);
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window_, GLFW_KEY_RIGHT) == GLFW_PRESS) {
|
||||||
|
camera_->set_position(camera_->position() + right * movement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::update(const double delta_time)
|
||||||
|
{
|
||||||
|
// Update angle for orbiting light
|
||||||
|
angle_ += delta_time;
|
||||||
|
|
||||||
|
// Make point light orbit around the model
|
||||||
|
if (point_light) {
|
||||||
|
constexpr float radius = 7.5f;
|
||||||
|
point_light->set_position(glm::vec3(radius * cos(angle_), 2.0f,
|
||||||
|
radius * sin(angle_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update world
|
||||||
|
world_->update(static_cast<float>(delta_time));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::render()
|
||||||
|
{
|
||||||
|
// Draw world
|
||||||
|
world_->draw();
|
||||||
|
|
||||||
|
// Swap buffers
|
||||||
|
glfwSwapBuffers(window_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Engine::is_running() const
|
||||||
|
{
|
||||||
|
return window_ && !glfwWindowShouldClose(window_)
|
||||||
|
&& !glfwGetKey(window_, GLFW_KEY_ESCAPE);
|
||||||
|
}
|
||||||
51
src/engine.h
Normal file
51
src/engine.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#ifndef ENGINE_H_
|
||||||
|
#define ENGINE_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../lib/glew/GL/glew.h"
|
||||||
|
#include "../lib/glfw/glfw3.h"
|
||||||
|
|
||||||
|
class World;
|
||||||
|
class Camera;
|
||||||
|
class Model;
|
||||||
|
class Mesh;
|
||||||
|
|
||||||
|
class Engine {
|
||||||
|
public:
|
||||||
|
Engine();
|
||||||
|
~Engine();
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
void run();
|
||||||
|
void destroy();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Lifecycle methods
|
||||||
|
void setup();
|
||||||
|
void start();
|
||||||
|
void process_input(const double delta_time);
|
||||||
|
void update(const double delta_time);
|
||||||
|
void render();
|
||||||
|
|
||||||
|
[[nodiscard]] bool is_running() const;
|
||||||
|
|
||||||
|
// Window and OpenGL
|
||||||
|
GLFWwindow* window_;
|
||||||
|
int screen_width_;
|
||||||
|
int screen_height_;
|
||||||
|
|
||||||
|
// Game objects
|
||||||
|
std::unique_ptr<World> world_;
|
||||||
|
std::shared_ptr<Camera> camera_;
|
||||||
|
std::vector<std::shared_ptr<Model>> models_;
|
||||||
|
std::shared_ptr<Mesh> mesh_;
|
||||||
|
|
||||||
|
// Game loop timing
|
||||||
|
double last_update_time_;
|
||||||
|
double last_frame_time_;
|
||||||
|
double angle_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ENGINE_H_
|
||||||
13
src/entity.cpp
Normal file
13
src/entity.cpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include "entity.h"
|
||||||
|
|
||||||
|
Entity::Entity()
|
||||||
|
: position_(0.0f, 0.0f, 0.0f)
|
||||||
|
, rotation_(0.0f, 0.0f, 0.0f)
|
||||||
|
, scale_(1.0f, 1.0f, 1.0f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entity::move(const glm::vec3& vec)
|
||||||
|
{
|
||||||
|
position_ += vec;
|
||||||
|
}
|
||||||
55
src/entity.h
Normal file
55
src/entity.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#ifndef ENTITY_H_
|
||||||
|
#define ENTITY_H_
|
||||||
|
|
||||||
|
#include "../lib/glm/glm.hpp"
|
||||||
|
|
||||||
|
class Entity {
|
||||||
|
public:
|
||||||
|
Entity();
|
||||||
|
virtual ~Entity() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] const glm::vec3& position() const
|
||||||
|
{
|
||||||
|
return position_;
|
||||||
|
}
|
||||||
|
void set_position(const glm::vec3& pos)
|
||||||
|
{
|
||||||
|
position_ = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const glm::vec3& rotation() const
|
||||||
|
{
|
||||||
|
return rotation_;
|
||||||
|
}
|
||||||
|
void set_rotation(const glm::vec3& rot)
|
||||||
|
{
|
||||||
|
rotation_ = rot;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const glm::vec3& scale() const
|
||||||
|
{
|
||||||
|
return scale_;
|
||||||
|
}
|
||||||
|
void set_scale(const glm::vec3& scale)
|
||||||
|
{
|
||||||
|
scale_ = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
void move(const glm::vec3& vec);
|
||||||
|
|
||||||
|
virtual void update(const float delta_time)
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
virtual void draw()
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
glm::vec3 position_;
|
||||||
|
glm::vec3 rotation_;
|
||||||
|
glm::vec3 scale_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ENTITY_H_
|
||||||
56
src/light.cpp
Normal file
56
src/light.cpp
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#include "light.h"
|
||||||
|
|
||||||
|
#include "../lib/glm/gtc/matrix_transform.hpp"
|
||||||
|
|
||||||
|
#include "shader.h"
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
Light::Light()
|
||||||
|
: Entity()
|
||||||
|
, type_(Type::DIRECTIONAL)
|
||||||
|
, color_(1.0f, 1.0f, 1.0f)
|
||||||
|
, intensity_(1.0f)
|
||||||
|
, linear_attenuation_(0.0f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::prepare(int index, std::shared_ptr<Shader>& shader) const
|
||||||
|
{
|
||||||
|
if (!shader)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Build uniform names for this light index
|
||||||
|
std::string light_vector =
|
||||||
|
"lights[" + std::to_string(index) + "].vector";
|
||||||
|
std::string light_color = "lights[" + std::to_string(index) + "].color";
|
||||||
|
std::string light_intensity =
|
||||||
|
"lights[" + std::to_string(index) + "].intensity";
|
||||||
|
std::string light_linear_att =
|
||||||
|
"lights[" + std::to_string(index) + "].linear_att";
|
||||||
|
|
||||||
|
// Get uniform locations
|
||||||
|
int vector_loc = shader->uniform_location(light_vector.c_str());
|
||||||
|
int color_loc = shader->uniform_location(light_color.c_str());
|
||||||
|
int intensity_loc = shader->uniform_location(light_intensity.c_str());
|
||||||
|
int linear_att_loc = shader->uniform_location(light_linear_att.c_str());
|
||||||
|
|
||||||
|
// Calculate light vector in view space
|
||||||
|
glm::vec4 light_vector_view;
|
||||||
|
if (type_ == Type::DIRECTIONAL) {
|
||||||
|
// For directional lights, w = 0
|
||||||
|
glm::vec3 direction =
|
||||||
|
glm::normalize(position_); // Use position as direction
|
||||||
|
light_vector_view =
|
||||||
|
state::view_matrix * glm::vec4(direction, 0.0f);
|
||||||
|
} else {
|
||||||
|
// For point lights, w = 1
|
||||||
|
light_vector_view =
|
||||||
|
state::view_matrix * glm::vec4(position_, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set uniforms
|
||||||
|
Shader::set_vec4(vector_loc, light_vector_view);
|
||||||
|
Shader::set_vec3(color_loc, color_);
|
||||||
|
Shader::set_float(intensity_loc, intensity_);
|
||||||
|
Shader::set_float(linear_att_loc, linear_attenuation_);
|
||||||
|
}
|
||||||
67
src/light.h
Normal file
67
src/light.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#ifndef LIGHT_H_
|
||||||
|
#define LIGHT_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "../lib/glm/glm.hpp"
|
||||||
|
|
||||||
|
#include "entity.h"
|
||||||
|
|
||||||
|
class Shader;
|
||||||
|
|
||||||
|
class Light : public Entity {
|
||||||
|
public:
|
||||||
|
enum class Type {
|
||||||
|
DIRECTIONAL,
|
||||||
|
POINT
|
||||||
|
};
|
||||||
|
|
||||||
|
Light();
|
||||||
|
~Light() override = default;
|
||||||
|
|
||||||
|
[[nodiscard]] Type type() const
|
||||||
|
{
|
||||||
|
return type_;
|
||||||
|
}
|
||||||
|
void set_type(Type type)
|
||||||
|
{
|
||||||
|
type_ = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const glm::vec3& color() const
|
||||||
|
{
|
||||||
|
return color_;
|
||||||
|
}
|
||||||
|
void set_color(const glm::vec3& color)
|
||||||
|
{
|
||||||
|
color_ = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] float intensity() const
|
||||||
|
{
|
||||||
|
return intensity_;
|
||||||
|
}
|
||||||
|
void set_intensity(float intensity)
|
||||||
|
{
|
||||||
|
intensity_ = intensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] float linear_attenuation() const
|
||||||
|
{
|
||||||
|
return linear_attenuation_;
|
||||||
|
}
|
||||||
|
void set_linear_attenuation(float att)
|
||||||
|
{
|
||||||
|
linear_attenuation_ = att;
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepare(int index, std::shared_ptr<Shader>& shader) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type type_;
|
||||||
|
glm::vec3 color_;
|
||||||
|
float intensity_;
|
||||||
|
float linear_attenuation_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LIGHT_H_
|
||||||
57
src/logger.cpp
Normal file
57
src/logger.cpp
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#include "logger.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
std::string current_datetime_string()
|
||||||
|
{
|
||||||
|
auto now = std::chrono::system_clock::now();
|
||||||
|
auto now_time_t = std::chrono::system_clock::to_time_t(now);
|
||||||
|
struct tm now_tm {};
|
||||||
|
#ifdef _WIN32
|
||||||
|
localtime_s(&now_tm, &now_time_t);
|
||||||
|
#else
|
||||||
|
localtime_r(&now_time_t, &now_tm);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char buffer[30];
|
||||||
|
std::strftime(buffer, sizeof(buffer) / sizeof(char), "%Y-%m-%d %H:%M:%S",
|
||||||
|
&now_tm);
|
||||||
|
return std::string{buffer};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void Logger::info(const std::string& message)
|
||||||
|
{
|
||||||
|
LogEntry entry;
|
||||||
|
entry.type = LogType::info;
|
||||||
|
entry.message =
|
||||||
|
"[" + current_datetime_string() + "] [INFO]: " + message;
|
||||||
|
|
||||||
|
std::cout << "\x1B[32m" << entry.message << "\033[0m" << std::endl;
|
||||||
|
messages_.push_back(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::warn(const std::string& message)
|
||||||
|
{
|
||||||
|
LogEntry entry;
|
||||||
|
entry.type = LogType::warn;
|
||||||
|
entry.message =
|
||||||
|
"[" + current_datetime_string() + "] [WARN]: " + message;
|
||||||
|
|
||||||
|
std::cout << "\x1B[93m" << entry.message << "\033[0m" << std::endl;
|
||||||
|
messages_.push_back(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::error(const std::string& message)
|
||||||
|
{
|
||||||
|
LogEntry entry;
|
||||||
|
entry.type = LogType::error;
|
||||||
|
entry.message = "[" + current_datetime_string() + "] [ERROR]: " + message;
|
||||||
|
|
||||||
|
std::cerr << "\x1B[91m" << entry.message << "\033[0m" << std::endl;
|
||||||
|
messages_.push_back(entry);
|
||||||
|
}
|
||||||
48
src/logger.h
Normal file
48
src/logger.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#ifndef LOGGER_H_
|
||||||
|
#define LOGGER_H_
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Utility: Concatenate any types into a string
|
||||||
|
template <typename... Args>
|
||||||
|
std::string sstr(Args&&... args)
|
||||||
|
{
|
||||||
|
std::ostringstream stream;
|
||||||
|
stream << std::dec;
|
||||||
|
((stream << args), ...);
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log types
|
||||||
|
enum class LogType {
|
||||||
|
info = 0,
|
||||||
|
warn,
|
||||||
|
error
|
||||||
|
};
|
||||||
|
|
||||||
|
// Log entry structure
|
||||||
|
struct LogEntry {
|
||||||
|
LogType type{LogType::info};
|
||||||
|
std::string message{};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Logger class
|
||||||
|
class Logger {
|
||||||
|
public:
|
||||||
|
static void info(const std::string& message);
|
||||||
|
static void warn(const std::string& message);
|
||||||
|
static void error(const std::string& message);
|
||||||
|
|
||||||
|
[[nodiscard]] static const std::vector<LogEntry>& messages()
|
||||||
|
{
|
||||||
|
return messages_;
|
||||||
|
}
|
||||||
|
static void clear() { messages_.clear(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline static std::vector<LogEntry> messages_{};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LOGGER_H_
|
||||||
126
src/main.cpp
126
src/main.cpp
@@ -1,118 +1,26 @@
|
|||||||
/*#ifdef _MSC_VER
|
// #ifdef _MSC_VER
|
||||||
#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")
|
// #pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")
|
||||||
#endif*/
|
// #endif
|
||||||
|
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "../lib/stb_image.h"
|
||||||
|
|
||||||
#include <iostream>
|
#define TINYOBJLOADER_IMPLEMENTATION
|
||||||
#include <vector>
|
#include "../lib/tiny_obj_loader.h"
|
||||||
|
|
||||||
#include "../lib/glew/GL/glew.h"
|
#include "engine.h"
|
||||||
#include "../lib/glfw/glfw3.h"
|
|
||||||
#include "../lib/glm/glm.hpp"
|
|
||||||
#include "../lib/glm/gtc/matrix_transform.hpp"
|
|
||||||
|
|
||||||
#include "vertex.h"
|
int main()
|
||||||
#include "shader.h"
|
{
|
||||||
#include "buffer.h"
|
Engine engine;
|
||||||
|
|
||||||
#define SCREEN_WIDTH 800
|
engine.initialize();
|
||||||
#define SCREEN_HEIGHT 600
|
engine.run();
|
||||||
|
engine.destroy();
|
||||||
|
|
||||||
int main() {
|
// _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
|
||||||
// Initialize OpenGL
|
// _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
|
||||||
if (!glfwInit()) {
|
// _CrtDumpMemoryLeaks();
|
||||||
std::cerr << "Failed to initialize glfw\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwWindowHint(GLFW_RESIZABLE, false);
|
|
||||||
glfwWindowHint(GLFW_SAMPLES, 8);
|
|
||||||
|
|
||||||
//glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
|
||||||
//glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
|
||||||
//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
|
||||||
|
|
||||||
GLFWwindow* win = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Daniel Poveda", nullptr, nullptr);
|
|
||||||
if (win == nullptr) {
|
|
||||||
std::cerr << "Failed to create opengl window\n";
|
|
||||||
glfwTerminate();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
glfwMakeContextCurrent(win);
|
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
|
||||||
glEnable(GL_SCISSOR_TEST);
|
|
||||||
|
|
||||||
std::cout << "OpenGL initialized, version: " << glGetString(GL_VERSION) << "\n";
|
|
||||||
|
|
||||||
// Initialize GLEW
|
|
||||||
glewExperimental = GL_TRUE;
|
|
||||||
GLenum err = glewInit();
|
|
||||||
if (err != GLEW_OK) {
|
|
||||||
std::cerr << "Failed to initialize GLEW: " << glewGetErrorString(err) << "\n";
|
|
||||||
glfwTerminate();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Logic
|
|
||||||
std::vector<Vertex> vertices = {
|
|
||||||
{{0.0f, 0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}},
|
|
||||||
{{-0.5f, -0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}},
|
|
||||||
{{0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}}
|
|
||||||
};
|
|
||||||
std::vector<uint16_t> indices = { 0, 1, 2 };
|
|
||||||
|
|
||||||
Buffer buffer(vertices, indices);
|
|
||||||
Shader shader("data/vertex.glsl", "data/fragment.glsl");
|
|
||||||
if (std::strlen(shader.getError()) > 0) {
|
|
||||||
std::cerr << "Failed to initialize shaders: " << shader.getError() << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::mat4 projection = glm::perspective(glm::radians(45.0f), static_cast<float>(SCREEN_WIDTH) / SCREEN_HEIGHT, 0.1f, 100.0f);
|
|
||||||
//glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 6));
|
|
||||||
glm::mat4 view = glm::lookAt(glm::vec3(0, 0, 6), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
|
|
||||||
|
|
||||||
// main loop
|
|
||||||
double angle = 0.0;
|
|
||||||
double lastTime = glfwGetTime();
|
|
||||||
while (!glfwWindowShouldClose(win) && !glfwGetKey(win, GLFW_KEY_ESCAPE)) {
|
|
||||||
// Delta
|
|
||||||
double delta_time = glfwGetTime() - lastTime;
|
|
||||||
lastTime = glfwGetTime();
|
|
||||||
|
|
||||||
// Reset window
|
|
||||||
int screenWidth, screenHeight;
|
|
||||||
glfwGetWindowSize(win, &screenWidth, &screenHeight);
|
|
||||||
glViewport(0, 0, screenWidth, screenHeight);
|
|
||||||
|
|
||||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
|
|
||||||
shader.Use();
|
|
||||||
|
|
||||||
// Logic
|
|
||||||
angle += 32.0 * delta_time;
|
|
||||||
|
|
||||||
for (int row = 0; row < 3; ++row) {
|
|
||||||
for (int col = 0; col < 3; ++col) {
|
|
||||||
glm::mat4 model = glm::translate(glm::mat4(1.0), glm::vec3(-3.0f + static_cast<float>(col) * 3.0f, 0.0f, static_cast<float>(-row) * 3.0f));
|
|
||||||
model = glm::rotate(model, glm::radians(static_cast<float>(angle)), glm::vec3(0, 1, 0));
|
|
||||||
|
|
||||||
glm::mat4 mvp = projection * view * model;
|
|
||||||
|
|
||||||
Shader::setMat4(shader.getLocation("mvp"), mvp);
|
|
||||||
|
|
||||||
buffer.Draw(shader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refresh screen
|
|
||||||
glfwSwapBuffers(win);
|
|
||||||
glfwPollEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shutdown
|
|
||||||
glfwTerminate();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
99
src/material.cpp
Normal file
99
src/material.cpp
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
#include "material.h"
|
||||||
|
|
||||||
|
#include "../lib/glm/glm.hpp"
|
||||||
|
#include "../lib/glm/gtc/matrix_transform.hpp"
|
||||||
|
|
||||||
|
#include "light.h"
|
||||||
|
#include "shader.h"
|
||||||
|
#include "state.h"
|
||||||
|
#include "texture.h"
|
||||||
|
|
||||||
|
Material::Material(const std::shared_ptr<Texture>& tex,
|
||||||
|
const std::shared_ptr<Shader>& shader)
|
||||||
|
: shader_(shader)
|
||||||
|
, texture_(tex)
|
||||||
|
, color_(1.0f, 1.0f, 1.0f, 1.0f)
|
||||||
|
, shininess_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::shared_ptr<Shader>& Material::shader() const
|
||||||
|
{
|
||||||
|
return shader_ ? shader_ : state::default_shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Shader>& Material::shader()
|
||||||
|
{
|
||||||
|
return shader_ ? shader_ : state::default_shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Material::set_shader(const std::shared_ptr<Shader>& shader)
|
||||||
|
{
|
||||||
|
shader_ = shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Material::prepare()
|
||||||
|
{
|
||||||
|
// Activate shader
|
||||||
|
std::shared_ptr<Shader> active_shader = shader();
|
||||||
|
if (!active_shader)
|
||||||
|
return;
|
||||||
|
|
||||||
|
active_shader->use();
|
||||||
|
|
||||||
|
// Set uniform variables
|
||||||
|
const glm::mat4 mvp =
|
||||||
|
state::projection_matrix * state::view_matrix * state::model_matrix;
|
||||||
|
const int mvp_loc = active_shader->uniform_location("mvp");
|
||||||
|
Shader::set_mat4(mvp_loc, mvp);
|
||||||
|
|
||||||
|
// Set ModelView matrix
|
||||||
|
const glm::mat4 model_view = state::view_matrix * state::model_matrix;
|
||||||
|
const int model_view_loc = active_shader->uniform_location("modelView");
|
||||||
|
Shader::set_mat4(model_view_loc, model_view);
|
||||||
|
|
||||||
|
// Set Normal matrix (transpose of inverse of ModelView)
|
||||||
|
const glm::mat4 normal_matrix =
|
||||||
|
glm::transpose(glm::inverse(model_view));
|
||||||
|
const int normal_matrix_loc =
|
||||||
|
active_shader->uniform_location("normalMatrix");
|
||||||
|
Shader::set_mat4(normal_matrix_loc, normal_matrix);
|
||||||
|
|
||||||
|
// Set material properties
|
||||||
|
const int material_color_loc =
|
||||||
|
active_shader->uniform_location("materialColor");
|
||||||
|
Shader::set_vec4(material_color_loc, color_);
|
||||||
|
|
||||||
|
const int shininess_loc = active_shader->uniform_location("shininess");
|
||||||
|
Shader::set_float(shininess_loc, static_cast<float>(shininess_));
|
||||||
|
|
||||||
|
// Set ambient light
|
||||||
|
const int ambient_loc = active_shader->uniform_location("ambientLight");
|
||||||
|
Shader::set_vec3(ambient_loc, state::ambient);
|
||||||
|
|
||||||
|
// Set number of lights
|
||||||
|
const int num_lights_loc = active_shader->uniform_location("numLights");
|
||||||
|
Shader::set_int(num_lights_loc, static_cast<int>(state::lights.size()));
|
||||||
|
|
||||||
|
// Prepare each light
|
||||||
|
for (size_t i = 0; i < state::lights.size(); ++i) {
|
||||||
|
state::lights[i]->prepare(static_cast<int>(i), active_shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set texture-related uniforms
|
||||||
|
const int use_texture_loc =
|
||||||
|
active_shader->uniform_location("useTexture");
|
||||||
|
if (texture_) {
|
||||||
|
Shader::set_int(use_texture_loc, 1);
|
||||||
|
const int sampler_loc =
|
||||||
|
active_shader->uniform_location("texSampler");
|
||||||
|
Shader::set_int(sampler_loc, 0); // Texture unit 0
|
||||||
|
} else {
|
||||||
|
Shader::set_int(use_texture_loc, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind texture if available
|
||||||
|
if (texture_) {
|
||||||
|
texture_->bind();
|
||||||
|
}
|
||||||
|
}
|
||||||
57
src/material.h
Normal file
57
src/material.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#ifndef MATERIAL_H_
|
||||||
|
#define MATERIAL_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "../lib/glm/glm.hpp"
|
||||||
|
|
||||||
|
class Shader;
|
||||||
|
class Texture;
|
||||||
|
|
||||||
|
class Material {
|
||||||
|
public:
|
||||||
|
Material(const std::shared_ptr<Texture>& tex = nullptr,
|
||||||
|
const std::shared_ptr<Shader>& shader = nullptr);
|
||||||
|
~Material() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] const std::shared_ptr<Shader>& shader() const;
|
||||||
|
[[nodiscard]] std::shared_ptr<Shader>& shader();
|
||||||
|
void set_shader(const std::shared_ptr<Shader>& shader);
|
||||||
|
|
||||||
|
[[nodiscard]] const std::shared_ptr<Texture>& texture() const
|
||||||
|
{
|
||||||
|
return texture_;
|
||||||
|
}
|
||||||
|
void set_texture(const std::shared_ptr<Texture>& tex)
|
||||||
|
{
|
||||||
|
texture_ = tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const glm::vec4& color() const
|
||||||
|
{
|
||||||
|
return color_;
|
||||||
|
}
|
||||||
|
void set_color(const glm::vec4& color)
|
||||||
|
{
|
||||||
|
color_ = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] uint8_t shininess() const
|
||||||
|
{
|
||||||
|
return shininess_;
|
||||||
|
}
|
||||||
|
void set_shininess(uint8_t shininess)
|
||||||
|
{
|
||||||
|
shininess_ = shininess;
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepare();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Shader> shader_;
|
||||||
|
std::shared_ptr<Texture> texture_;
|
||||||
|
glm::vec4 color_;
|
||||||
|
uint8_t shininess_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MATERIAL_H_
|
||||||
202
src/mesh.cpp
Normal file
202
src/mesh.cpp
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
#include "mesh.h"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "../lib/tiny_obj_loader.h"
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "material.h"
|
||||||
|
#include "shader.h"
|
||||||
|
#include "state.h"
|
||||||
|
#include "texture.h"
|
||||||
|
#include "vertex.h"
|
||||||
|
|
||||||
|
// Helper structures and functions for OBJ loading
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct LoadContext {
|
||||||
|
std::string base_dir;
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<Texture>> texture_cache;
|
||||||
|
const std::vector<tinyobj::material_t>* materials;
|
||||||
|
const std::shared_ptr<Shader>& shader;
|
||||||
|
};
|
||||||
|
|
||||||
|
Vertex create_vertex(const tinyobj::attrib_t& attrib,
|
||||||
|
const tinyobj::index_t& idx)
|
||||||
|
{
|
||||||
|
Vertex vertex;
|
||||||
|
|
||||||
|
// Position
|
||||||
|
if (idx.vertex_index >= 0) {
|
||||||
|
vertex.position.x = attrib.vertices[3 * idx.vertex_index + 0];
|
||||||
|
vertex.position.y = attrib.vertices[3 * idx.vertex_index + 1];
|
||||||
|
vertex.position.z = attrib.vertices[3 * idx.vertex_index + 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Color (default to white)
|
||||||
|
vertex.color = glm::vec3(1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
// Texture coordinates
|
||||||
|
vertex.tex_coord = glm::vec2(0.0f, 0.0f);
|
||||||
|
if (idx.texcoord_index >= 0) {
|
||||||
|
vertex.tex_coord.x = attrib.texcoords[2 * idx.texcoord_index + 0];
|
||||||
|
vertex.tex_coord.y = attrib.texcoords[2 * idx.texcoord_index + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal
|
||||||
|
vertex.normal = glm::vec3(0.0f, 0.0f, 1.0f);
|
||||||
|
if (idx.normal_index >= 0) {
|
||||||
|
vertex.normal.x = attrib.normals[3 * idx.normal_index + 0];
|
||||||
|
vertex.normal.y = attrib.normals[3 * idx.normal_index + 1];
|
||||||
|
vertex.normal.z = attrib.normals[3 * idx.normal_index + 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
return vertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_shape(const tinyobj::shape_t& shape,
|
||||||
|
const tinyobj::attrib_t& attrib,
|
||||||
|
std::vector<Vertex>& out_vertices,
|
||||||
|
std::vector<uint16_t>& out_indices)
|
||||||
|
{
|
||||||
|
// Process all indices - create one vertex per index
|
||||||
|
for (size_t i = 0; i < shape.mesh.indices.size(); ++i) {
|
||||||
|
const tinyobj::index_t& idx = shape.mesh.indices[i];
|
||||||
|
Vertex vertex = create_vertex(attrib, idx);
|
||||||
|
|
||||||
|
out_vertices.push_back(vertex);
|
||||||
|
out_indices.push_back(
|
||||||
|
static_cast<uint16_t>(out_vertices.size() - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Texture> load_material_texture(int material_id,
|
||||||
|
LoadContext& context)
|
||||||
|
{
|
||||||
|
if (material_id < 0
|
||||||
|
|| material_id >= static_cast<int>(context.materials->size())) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& mat = (*context.materials)[material_id];
|
||||||
|
std::string texture_name = mat.diffuse_texname;
|
||||||
|
|
||||||
|
// Try ambient texture if diffuse is not available
|
||||||
|
if (texture_name.empty()) {
|
||||||
|
texture_name = mat.ambient_texname;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture_name.empty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check cache first
|
||||||
|
auto it = context.texture_cache.find(texture_name);
|
||||||
|
if (it != context.texture_cache.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load texture
|
||||||
|
std::string texture_path = context.base_dir + texture_name;
|
||||||
|
auto texture = Texture::load(texture_path.c_str());
|
||||||
|
|
||||||
|
if (texture) {
|
||||||
|
context.texture_cache[texture_name] = texture;
|
||||||
|
Logger::info(sstr("Loaded texture: ", texture_path));
|
||||||
|
} else {
|
||||||
|
Logger::warn(sstr("Failed to load texture: ", texture_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_buffer_for_shape(const tinyobj::shape_t& shape,
|
||||||
|
const std::vector<Vertex>& vertices,
|
||||||
|
const std::vector<uint16_t>& indices,
|
||||||
|
LoadContext& context,
|
||||||
|
std::shared_ptr<Mesh>& mesh)
|
||||||
|
{
|
||||||
|
auto buffer = std::make_shared<Buffer>(vertices, indices);
|
||||||
|
|
||||||
|
// Use first material ID from the shape
|
||||||
|
int material_id = -1;
|
||||||
|
if (!shape.mesh.material_ids.empty() && shape.mesh.material_ids[0] >= 0) {
|
||||||
|
material_id = shape.mesh.material_ids[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
auto texture = load_material_texture(material_id, context);
|
||||||
|
auto material_shader =
|
||||||
|
context.shader ? context.shader : state::default_shader;
|
||||||
|
|
||||||
|
Material mat(texture, material_shader);
|
||||||
|
mesh->add_buffer(buffer, mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void Mesh::add_buffer(const std::shared_ptr<Buffer>& buffer,
|
||||||
|
const Material& material)
|
||||||
|
{
|
||||||
|
buffers_.push_back(buffer);
|
||||||
|
materials_.push_back(material);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Mesh> Mesh::load(const char* filename,
|
||||||
|
const std::shared_ptr<Shader>& shader)
|
||||||
|
{
|
||||||
|
Logger::info(sstr("Loading mesh from: ", filename));
|
||||||
|
|
||||||
|
// Load OBJ file
|
||||||
|
tinyobj::attrib_t attrib;
|
||||||
|
std::vector<tinyobj::shape_t> shapes;
|
||||||
|
std::vector<tinyobj::material_t> materials;
|
||||||
|
std::string err;
|
||||||
|
|
||||||
|
std::filesystem::path obj_path(filename);
|
||||||
|
std::string base_dir = obj_path.parent_path().string();
|
||||||
|
if (!base_dir.empty()) {
|
||||||
|
base_dir += "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename,
|
||||||
|
base_dir.c_str())) {
|
||||||
|
Logger::error(
|
||||||
|
sstr("Failed to load OBJ file: ", filename, " - ", err));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!err.empty()) {
|
||||||
|
Logger::warn(sstr("TinyObjLoader warning: ", err));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup load context
|
||||||
|
LoadContext context{base_dir, {}, &materials, shader};
|
||||||
|
|
||||||
|
// Process each shape
|
||||||
|
auto mesh = std::make_shared<Mesh>();
|
||||||
|
for (const auto& shape : shapes) {
|
||||||
|
Logger::info(sstr("Processing shape: ", shape.name));
|
||||||
|
|
||||||
|
std::vector<Vertex> vertices;
|
||||||
|
std::vector<uint16_t> indices;
|
||||||
|
|
||||||
|
process_shape(shape, attrib, vertices, indices);
|
||||||
|
create_buffer_for_shape(shape, vertices, indices, context, mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::info(sstr("Mesh loaded successfully with ", mesh->num_buffers(),
|
||||||
|
" buffers"));
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh::draw()
|
||||||
|
{
|
||||||
|
// Draw each buffer with its material
|
||||||
|
for (size_t i = 0; i < buffers_.size(); ++i) {
|
||||||
|
materials_[i].prepare();
|
||||||
|
buffers_[i]->draw(*materials_[i].shader());
|
||||||
|
}
|
||||||
|
}
|
||||||
53
src/mesh.h
Normal file
53
src/mesh.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#ifndef MESH_H_
|
||||||
|
#define MESH_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "material.h"
|
||||||
|
|
||||||
|
class Buffer;
|
||||||
|
class Shader;
|
||||||
|
|
||||||
|
class Mesh {
|
||||||
|
public:
|
||||||
|
Mesh() = default;
|
||||||
|
~Mesh() = default;
|
||||||
|
|
||||||
|
static std::shared_ptr<Mesh>
|
||||||
|
load(const char* filename,
|
||||||
|
const std::shared_ptr<Shader>& shader = nullptr);
|
||||||
|
|
||||||
|
void add_buffer(const std::shared_ptr<Buffer>& buffer,
|
||||||
|
const Material& material);
|
||||||
|
|
||||||
|
[[nodiscard]] size_t num_buffers() const
|
||||||
|
{
|
||||||
|
return buffers_.size();
|
||||||
|
}
|
||||||
|
[[nodiscard]] const std::shared_ptr<Buffer>& buffer(size_t index) const
|
||||||
|
{
|
||||||
|
return buffers_[index];
|
||||||
|
}
|
||||||
|
[[nodiscard]] std::shared_ptr<Buffer>& buffer(size_t index)
|
||||||
|
{
|
||||||
|
return buffers_[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const Material& material(size_t index) const
|
||||||
|
{
|
||||||
|
return materials_[index];
|
||||||
|
}
|
||||||
|
[[nodiscard]] Material& material(size_t index)
|
||||||
|
{
|
||||||
|
return materials_[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::shared_ptr<Buffer>> buffers_;
|
||||||
|
std::vector<Material> materials_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MESH_H_
|
||||||
35
src/model.cpp
Normal file
35
src/model.cpp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#include "model.h"
|
||||||
|
#include "mesh.h"
|
||||||
|
#include "state.h"
|
||||||
|
#include "../lib/glm/gtc/matrix_transform.hpp"
|
||||||
|
|
||||||
|
Model::Model(const std::shared_ptr<Mesh>& mesh)
|
||||||
|
: mesh_(mesh)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model::draw()
|
||||||
|
{
|
||||||
|
if (!mesh_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Build model matrix: Translation * Rotation * Scale
|
||||||
|
glm::mat4 model = glm::mat4(1.0f);
|
||||||
|
|
||||||
|
// Translation
|
||||||
|
model = glm::translate(model, position_);
|
||||||
|
|
||||||
|
// Rotation (applying X, Y, Z rotations)
|
||||||
|
model = glm::rotate(model, rotation_.x, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||||
|
model = glm::rotate(model, rotation_.y, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
model = glm::rotate(model, rotation_.z, glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
|
|
||||||
|
// Scale
|
||||||
|
model = glm::scale(model, scale_);
|
||||||
|
|
||||||
|
// Set the model matrix in state
|
||||||
|
state::model_matrix = model;
|
||||||
|
|
||||||
|
// Draw the mesh
|
||||||
|
mesh_->draw();
|
||||||
|
}
|
||||||
19
src/model.h
Normal file
19
src/model.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef MODEL_H_
|
||||||
|
#define MODEL_H_
|
||||||
|
|
||||||
|
#include "entity.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class Mesh;
|
||||||
|
|
||||||
|
class Model : public Entity {
|
||||||
|
public:
|
||||||
|
Model(const std::shared_ptr<Mesh>& mesh);
|
||||||
|
|
||||||
|
virtual void draw() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Mesh> mesh_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MODEL_H_
|
||||||
@@ -1,19 +1,20 @@
|
|||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iostream>
|
#include <vector>
|
||||||
|
|
||||||
#include "../lib/glew/GL/glew.h"
|
#include "../lib/glew/GL/glew.h"
|
||||||
#include "../lib/glfw/glfw3.h"
|
#include "../lib/glfw/glfw3.h"
|
||||||
|
|
||||||
|
#include "logger.h"
|
||||||
#include "vertex.h"
|
#include "vertex.h"
|
||||||
|
|
||||||
Shader::Shader(const std::string& vertexPath, const std::string& fragmentPath)
|
Shader::Shader(const std::string& vertex_path, const std::string& fragment_path)
|
||||||
{
|
{
|
||||||
const uint32_t vshader = CompileShader(GL_VERTEX_SHADER, vertexPath);
|
const uint32_t vshader = compile_shader(GL_VERTEX_SHADER, vertex_path);
|
||||||
const uint32_t fshader = CompileShader(GL_FRAGMENT_SHADER, fragmentPath);
|
const uint32_t fshader =
|
||||||
|
compile_shader(GL_FRAGMENT_SHADER, fragment_path);
|
||||||
|
|
||||||
if (vshader == 0 || fshader == 0) {
|
if (vshader == 0 || fshader == 0) {
|
||||||
program_id_ = 0;
|
program_id_ = 0;
|
||||||
@@ -30,7 +31,8 @@ Shader::Shader(const std::string& vertexPath, const std::string& fragmentPath)
|
|||||||
glGetProgramiv(program_id_, GL_LINK_STATUS, &ret);
|
glGetProgramiv(program_id_, GL_LINK_STATUS, &ret);
|
||||||
if (ret == GL_FALSE) {
|
if (ret == GL_FALSE) {
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
glGetProgramInfoLog(program_id_, sizeof(buffer), nullptr, buffer);
|
glGetProgramInfoLog(program_id_, sizeof(buffer), nullptr,
|
||||||
|
buffer);
|
||||||
error_ = buffer;
|
error_ = buffer;
|
||||||
glDeleteProgram(program_id_);
|
glDeleteProgram(program_id_);
|
||||||
program_id_ = 0;
|
program_id_ = 0;
|
||||||
@@ -40,67 +42,88 @@ Shader::Shader(const std::string& vertexPath, const std::string& fragmentPath)
|
|||||||
glDeleteShader(fshader);
|
glDeleteShader(fshader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::Use() const
|
void Shader::use() const
|
||||||
{
|
{
|
||||||
if (program_id_ != 0)
|
if (program_id_ != 0)
|
||||||
glUseProgram(program_id_);
|
glUseProgram(program_id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::SetupAttribs() const
|
void Shader::setup_attribs() const
|
||||||
{
|
{
|
||||||
int loc = glGetAttribLocation(program_id_, "vpos");
|
int loc = glGetAttribLocation(program_id_, "vpos");
|
||||||
if (loc != -1) {
|
if (loc != -1) {
|
||||||
glEnableVertexAttribArray(loc);
|
glEnableVertexAttribArray(loc);
|
||||||
glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const void*>(offsetof(Vertex, position)));
|
glVertexAttribPointer(
|
||||||
|
loc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||||
|
reinterpret_cast<const void*>(offsetof(Vertex, position)));
|
||||||
}
|
}
|
||||||
|
|
||||||
loc = glGetAttribLocation(program_id_, "vcolor");
|
loc = glGetAttribLocation(program_id_, "vcolor");
|
||||||
if (loc != -1) {
|
if (loc != -1) {
|
||||||
glEnableVertexAttribArray(loc);
|
glEnableVertexAttribArray(loc);
|
||||||
glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const void*>(offsetof(Vertex, color)));
|
glVertexAttribPointer(
|
||||||
|
loc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||||
|
reinterpret_cast<const void*>(offsetof(Vertex, color)));
|
||||||
|
}
|
||||||
|
|
||||||
|
loc = glGetAttribLocation(program_id_, "vtexcoord");
|
||||||
|
if (loc != -1) {
|
||||||
|
glEnableVertexAttribArray(loc);
|
||||||
|
glVertexAttribPointer(
|
||||||
|
loc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||||
|
reinterpret_cast<const void*>(offsetof(Vertex, tex_coord)));
|
||||||
|
}
|
||||||
|
|
||||||
|
loc = glGetAttribLocation(program_id_, "vnormal");
|
||||||
|
if (loc != -1) {
|
||||||
|
glEnableVertexAttribArray(loc);
|
||||||
|
glVertexAttribPointer(
|
||||||
|
loc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||||
|
reinterpret_cast<const void*>(offsetof(Vertex, normal)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Shader::getLocation(const char* key) const
|
int Shader::uniform_location(const char* key) const
|
||||||
{
|
{
|
||||||
return glGetUniformLocation(program_id_, key);
|
return glGetUniformLocation(program_id_, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::setInt(int loc, int value)
|
void Shader::set_int(int loc, int value)
|
||||||
{
|
{
|
||||||
if (loc != -1)
|
if (loc != -1)
|
||||||
glUniform1i(loc, value);
|
glUniform1i(loc, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::setFloat(int loc, float value)
|
void Shader::set_float(int loc, float value)
|
||||||
{
|
{
|
||||||
if (loc != -1)
|
if (loc != -1)
|
||||||
glUniform1f(loc, value);
|
glUniform1f(loc, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::setVec3(int loc, const glm::vec3& value)
|
void Shader::set_vec3(int loc, const glm::vec3& value)
|
||||||
{
|
{
|
||||||
if (loc != -1)
|
if (loc != -1)
|
||||||
glUniform3fv(loc, 1, &value[0]);
|
glUniform3fv(loc, 1, &value[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::setVec4(int loc, const glm::vec4& value)
|
void Shader::set_vec4(int loc, const glm::vec4& value)
|
||||||
{
|
{
|
||||||
if (loc != -1)
|
if (loc != -1)
|
||||||
glUniform4fv(loc, 1, &value[0]);
|
glUniform4fv(loc, 1, &value[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::setMat4(int loc, const glm::mat4& value)
|
void Shader::set_mat4(int loc, const glm::mat4& value)
|
||||||
{
|
{
|
||||||
if (loc != -1)
|
if (loc != -1)
|
||||||
glUniformMatrix4fv(loc, 1, GL_FALSE, &value[0][0]);
|
glUniformMatrix4fv(loc, 1, GL_FALSE, &value[0][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Shader::ReadShaderFile(const std::string& filename)
|
std::string Shader::read_shader_file(const std::string& filename)
|
||||||
{
|
{
|
||||||
std::ifstream file(filename);
|
std::ifstream file(filename);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
error_ = "Failed to open shader file: " + filename + "\n";
|
error_ = "Failed to open shader file: " + filename;
|
||||||
|
Logger::error(sstr("Failed to open shader file: ", filename));
|
||||||
return std::string{0};
|
return std::string{0};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,13 +132,18 @@ std::string Shader::ReadShaderFile(const std::string& filename)
|
|||||||
return buffer.str();
|
return buffer.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Shader::CompileShader(uint32_t type, const std::string& source_path)
|
uint32_t Shader::compile_shader(uint32_t type, const std::string& source_path)
|
||||||
{
|
{
|
||||||
std::string source = ReadShaderFile(source_path);
|
const char* shader_type_name =
|
||||||
//std::cout << "SHADER FILE: " << source << "\n";
|
(type == GL_VERTEX_SHADER) ? "vertex" : "fragment";
|
||||||
|
|
||||||
|
std::string source = read_shader_file(source_path);
|
||||||
if (source.empty())
|
if (source.empty())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
Logger::info(
|
||||||
|
sstr("Compiling ", shader_type_name, " shader: ", source_path));
|
||||||
|
|
||||||
const uint32_t shader = glCreateShader(type);
|
const uint32_t shader = glCreateShader(type);
|
||||||
const char* shader_code = source.c_str();
|
const char* shader_code = source.c_str();
|
||||||
|
|
||||||
@@ -129,9 +157,12 @@ uint32_t Shader::CompileShader(uint32_t type, const std::string& source_path)
|
|||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
glGetShaderInfoLog(shader, sizeof(buffer), nullptr, buffer);
|
glGetShaderInfoLog(shader, sizeof(buffer), nullptr, buffer);
|
||||||
error_ = buffer;
|
error_ = buffer;
|
||||||
|
Logger::error(sstr("Shader compilation failed (",
|
||||||
|
shader_type_name, "): ", buffer));
|
||||||
glDeleteShader(shader);
|
glDeleteShader(shader);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger::info(sstr(shader_type_name, " shader compiled successfully"));
|
||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
|
|||||||
34
src/shader.h
34
src/shader.h
@@ -9,29 +9,35 @@
|
|||||||
|
|
||||||
class Shader {
|
class Shader {
|
||||||
public:
|
public:
|
||||||
Shader(const std::string& vertex_path, const std::string& fragment_path);
|
Shader(const std::string& vertex_path,
|
||||||
|
const std::string& fragment_path);
|
||||||
|
|
||||||
void Use() const;
|
void use() const;
|
||||||
void SetupAttribs() const;
|
void setup_attribs() const;
|
||||||
|
|
||||||
uint32_t getId() const { return program_id_; }
|
[[nodiscard]] uint32_t id() const
|
||||||
const char* getError() const { return error_.c_str(); }
|
{
|
||||||
|
return program_id_;
|
||||||
|
}
|
||||||
|
[[nodiscard]] const char* error() const
|
||||||
|
{
|
||||||
|
return error_.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
int getLocation(const char* key) const;
|
[[nodiscard]] int uniform_location(const char* key) const;
|
||||||
|
|
||||||
static void setInt(int loc, int value);
|
static void set_int(int loc, int value);
|
||||||
static void setFloat(int loc, float value);
|
static void set_float(int loc, float value);
|
||||||
static void setVec3(int loc, const glm::vec3& value);
|
static void set_vec3(int loc, const glm::vec3& value);
|
||||||
static void setVec4(int loc, const glm::vec4& value);
|
static void set_vec4(int loc, const glm::vec4& value);
|
||||||
static void setMat4(int loc, const glm::mat4& value);
|
static void set_mat4(int loc, const glm::mat4& value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t program_id_;
|
uint32_t program_id_;
|
||||||
std::string error_;
|
std::string error_;
|
||||||
|
|
||||||
std::string ReadShaderFile(const std::string& filename);
|
std::string read_shader_file(const std::string& filename);
|
||||||
uint32_t CompileShader(uint32_t type, const std::string& source_path);
|
uint32_t compile_shader(uint32_t type, const std::string& source_path);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // SHADER_H_
|
#endif // SHADER_H_
|
||||||
22
src/state.h
Normal file
22
src/state.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef STATE_H_
|
||||||
|
#define STATE_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include "../lib/glm/glm.hpp"
|
||||||
|
|
||||||
|
class Shader;
|
||||||
|
class Light;
|
||||||
|
|
||||||
|
namespace state {
|
||||||
|
|
||||||
|
inline std::shared_ptr<Shader> default_shader = nullptr;
|
||||||
|
inline glm::mat4 projection_matrix = glm::mat4(1.0f);
|
||||||
|
inline glm::mat4 view_matrix = glm::mat4(1.0f);
|
||||||
|
inline glm::mat4 model_matrix = glm::mat4(1.0f);
|
||||||
|
inline std::vector<std::shared_ptr<Light>> lights;
|
||||||
|
inline glm::vec3 ambient = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
} // namespace state
|
||||||
|
|
||||||
|
#endif // STATE_H_
|
||||||
81
src/texture.cpp
Normal file
81
src/texture.cpp
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#include "texture.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "../lib/glew/GL/glew.h"
|
||||||
|
#include "../lib/glfw/glfw3.h"
|
||||||
|
#include "../lib/stb_image.h"
|
||||||
|
|
||||||
|
#include "logger.h"
|
||||||
|
|
||||||
|
Texture::Texture(uint32_t id, const glm::ivec2& size)
|
||||||
|
: id_(id), size_(size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture::~Texture()
|
||||||
|
{
|
||||||
|
if (id_ != 0) {
|
||||||
|
glDeleteTextures(1, &id_);
|
||||||
|
Logger::info(sstr("Texture ", id_, " destroyed"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Texture> Texture::load(const char* filename)
|
||||||
|
{
|
||||||
|
Logger::info(sstr("Loading texture: ", filename));
|
||||||
|
|
||||||
|
// Load image
|
||||||
|
int width, height, channels;
|
||||||
|
stbi_uc* pixels =
|
||||||
|
stbi_load(filename, &width, &height, &channels, STBI_rgb_alpha);
|
||||||
|
|
||||||
|
if (!pixels) {
|
||||||
|
Logger::error(sstr("Failed to load texture: ", filename, " - ",
|
||||||
|
stbi_failure_reason()));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flip image vertically (OpenGL expects bottom row first)
|
||||||
|
const int row_size = width * 4; // 4 channels (RGBA)
|
||||||
|
auto* row_buffer = new stbi_uc[row_size];
|
||||||
|
for (int y = 0; y < height / 2; ++y) {
|
||||||
|
stbi_uc* row1 = pixels + y * row_size;
|
||||||
|
stbi_uc* row2 = pixels + (height - 1 - y) * row_size;
|
||||||
|
std::copy(row1, row1 + row_size, row_buffer);
|
||||||
|
std::copy(row2, row2 + row_size, row1);
|
||||||
|
std::copy(row_buffer, row_buffer + row_size, row2);
|
||||||
|
}
|
||||||
|
delete[] row_buffer;
|
||||||
|
|
||||||
|
// Generate OpenGL texture
|
||||||
|
GLuint texture_id;
|
||||||
|
glGenTextures(1, &texture_id);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||||
|
|
||||||
|
// Upload texture data
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE, pixels);
|
||||||
|
|
||||||
|
// Set trilinear filtering
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||||
|
GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
// Generate mipmaps
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
// Free image data
|
||||||
|
stbi_image_free(pixels);
|
||||||
|
|
||||||
|
Logger::info(sstr("Texture loaded successfully: ", filename, " (",
|
||||||
|
width, "x", height, ", ", channels, " channels)"));
|
||||||
|
|
||||||
|
return std::shared_ptr<Texture>(
|
||||||
|
new Texture(texture_id, glm::ivec2(width, height)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::bind() const
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_2D, id_);
|
||||||
|
}
|
||||||
35
src/texture.h
Normal file
35
src/texture.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#ifndef TEXTURE_H_
|
||||||
|
#define TEXTURE_H_
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "../lib/glm/glm.hpp"
|
||||||
|
|
||||||
|
class Texture {
|
||||||
|
public:
|
||||||
|
Texture() = delete;
|
||||||
|
~Texture();
|
||||||
|
|
||||||
|
static std::shared_ptr<Texture> load(const char* filename);
|
||||||
|
|
||||||
|
[[nodiscard]] uint32_t id() const
|
||||||
|
{
|
||||||
|
return id_;
|
||||||
|
}
|
||||||
|
[[nodiscard]] const glm::ivec2& size() const
|
||||||
|
{
|
||||||
|
return size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Texture(uint32_t id, const glm::ivec2& size);
|
||||||
|
|
||||||
|
uint32_t id_;
|
||||||
|
glm::ivec2 size_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TEXTURE_H_
|
||||||
@@ -6,6 +6,8 @@
|
|||||||
struct Vertex {
|
struct Vertex {
|
||||||
glm::vec3 position{0.0f, 0.0f, 0.0f};
|
glm::vec3 position{0.0f, 0.0f, 0.0f};
|
||||||
glm::vec3 color{0.0f, 0.0f, 0.0f};
|
glm::vec3 color{0.0f, 0.0f, 0.0f};
|
||||||
|
glm::vec2 tex_coord{0.0f, 0.0f};
|
||||||
|
glm::vec3 normal{0.0f, 0.0f, 0.0f};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VERTEX_H_
|
#endif // VERTEX_H_
|
||||||
94
src/world.cpp
Normal file
94
src/world.cpp
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#include "world.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "camera.h"
|
||||||
|
#include "entity.h"
|
||||||
|
#include "light.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
void World::add_entity(const std::shared_ptr<Entity>& entity)
|
||||||
|
{
|
||||||
|
entities_.push_back(entity);
|
||||||
|
|
||||||
|
// Check if entity is a camera
|
||||||
|
std::shared_ptr<Camera> camera =
|
||||||
|
std::dynamic_pointer_cast<Camera>(entity);
|
||||||
|
if (camera) {
|
||||||
|
cameras_.push_back(camera);
|
||||||
|
Logger::info(sstr("Camera added to world (total cameras: ",
|
||||||
|
cameras_.size(), ")"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if entity is a light
|
||||||
|
std::shared_ptr<Light> light = std::dynamic_pointer_cast<Light>(entity);
|
||||||
|
if (light) {
|
||||||
|
lights_.push_back(light);
|
||||||
|
Logger::info(sstr("Light added to world (total lights: ",
|
||||||
|
lights_.size(), ")"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::info(sstr(
|
||||||
|
"Entity added to world (total entities: ", entities_.size(), ")"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::remove_entity(const std::shared_ptr<Entity>& entity)
|
||||||
|
{
|
||||||
|
// Remove from entities list
|
||||||
|
auto it = std::find(entities_.begin(), entities_.end(), entity);
|
||||||
|
if (it != entities_.end()) {
|
||||||
|
entities_.erase(it);
|
||||||
|
Logger::info("Entity removed from world");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if entity is a camera and remove from cameras list
|
||||||
|
std::shared_ptr<Camera> camera =
|
||||||
|
std::dynamic_pointer_cast<Camera>(entity);
|
||||||
|
if (camera) {
|
||||||
|
auto camIt =
|
||||||
|
std::find(cameras_.begin(), cameras_.end(), camera);
|
||||||
|
if (camIt != cameras_.end()) {
|
||||||
|
cameras_.erase(camIt);
|
||||||
|
Logger::info("Camera removed from world");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if entity is a light and remove from lights list
|
||||||
|
std::shared_ptr<Light> light = std::dynamic_pointer_cast<Light>(entity);
|
||||||
|
if (light) {
|
||||||
|
auto lightIt = std::find(lights_.begin(), lights_.end(), light);
|
||||||
|
if (lightIt != lights_.end()) {
|
||||||
|
lights_.erase(lightIt);
|
||||||
|
Logger::info("Light removed from world");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::update(float delta_time)
|
||||||
|
{
|
||||||
|
for (auto& entity : entities_) {
|
||||||
|
entity->update(delta_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::draw()
|
||||||
|
{
|
||||||
|
// Update state with world lighting information
|
||||||
|
state::ambient = ambient_;
|
||||||
|
state::lights = lights_;
|
||||||
|
|
||||||
|
// Draw for each camera
|
||||||
|
for (auto& camera : cameras_) {
|
||||||
|
// Prepare the camera (sets viewport, projection, view, clears
|
||||||
|
// screen)
|
||||||
|
camera->prepare();
|
||||||
|
|
||||||
|
// Draw all entities
|
||||||
|
for (auto& entity : entities_) {
|
||||||
|
entity->draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
52
src/world.h
Normal file
52
src/world.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#ifndef WORLD_H_
|
||||||
|
#define WORLD_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../lib/glm/glm.hpp"
|
||||||
|
|
||||||
|
class Entity;
|
||||||
|
class Camera;
|
||||||
|
class Light;
|
||||||
|
|
||||||
|
class World {
|
||||||
|
public:
|
||||||
|
World() = default;
|
||||||
|
|
||||||
|
void add_entity(const std::shared_ptr<Entity>& entity);
|
||||||
|
void remove_entity(const std::shared_ptr<Entity>& entity);
|
||||||
|
|
||||||
|
[[nodiscard]] size_t num_entities() const
|
||||||
|
{
|
||||||
|
return entities_.size();
|
||||||
|
}
|
||||||
|
[[nodiscard]] const std::shared_ptr<Entity>& entity(size_t index) const
|
||||||
|
{
|
||||||
|
return entities_[index];
|
||||||
|
}
|
||||||
|
[[nodiscard]] std::shared_ptr<Entity>& entity(size_t index)
|
||||||
|
{
|
||||||
|
return entities_[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const glm::vec3& ambient() const
|
||||||
|
{
|
||||||
|
return ambient_;
|
||||||
|
}
|
||||||
|
void set_ambient(const glm::vec3& ambient)
|
||||||
|
{
|
||||||
|
ambient_ = ambient;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(float delta_time);
|
||||||
|
void draw();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::shared_ptr<Entity>> entities_;
|
||||||
|
std::vector<std::shared_ptr<Camera>> cameras_;
|
||||||
|
std::vector<std::shared_ptr<Light>> lights_;
|
||||||
|
glm::vec3 ambient_{0.0f, 0.0f, 0.0f};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WORLD_H_
|
||||||
@@ -72,20 +72,20 @@
|
|||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup />
|
<PropertyGroup />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<OutDir>$(SolutionDir)Build\$(Platform)\$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)Build\obj\$(Platform)\$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)build\obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<OutDir>$(SolutionDir)Build\$(Platform)\$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)Build\obj\$(Platform)\$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)build\obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<OutDir>$(SolutionDir)Build\$(Platform)\$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)Build\obj\$(Platform)\$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)build\obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<OutDir>$(SolutionDir)Build\$(Platform)\$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)Build\obj\$(Platform)\$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)build\obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@@ -93,12 +93,12 @@
|
|||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>../lib/glew</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>lib/glew</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>GLEW_STATIC;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>GLEW_STATIC;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalLibraryDirectories>../lib/glfw</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>lib/glfw</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>glfw3.win32.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>glfw3.win32.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@@ -108,12 +108,12 @@
|
|||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>../lib/glew</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>lib/glew</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>GLEW_STATIC;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>GLEW_STATIC;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalLibraryDirectories>../lib/glfw</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>lib/glfw</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>glfw3.win64.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>glfw3.win64.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@@ -125,14 +125,14 @@
|
|||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>../lib/glew</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>lib/glew</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>GLEW_STATIC;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>GLEW_STATIC;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalLibraryDirectories>../lib/glfw</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>lib/glfw</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>glfw3.win32.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>glfw3.win32.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@@ -144,35 +144,57 @@
|
|||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>../lib/glew</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>lib/glew</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>GLEW_STATIC;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>GLEW_STATIC;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalLibraryDirectories>../lib/glfw</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>lib/glfw</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>glfw3.win64.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>glfw3.win64.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\lib\glew\GL\glew.h" />
|
<ClInclude Include="lib\glew\GL\glew.h" />
|
||||||
<ClInclude Include="..\lib\glfw\glfw3.h" />
|
<ClInclude Include="lib\glfw\glfw3.h" />
|
||||||
<ClInclude Include="..\lib\glfw\glfw3native.h" />
|
<ClInclude Include="lib\glfw\glfw3native.h" />
|
||||||
<ClInclude Include="..\src\buffer.h" />
|
<ClInclude Include="lib\stb\stb_image.h" />
|
||||||
<ClInclude Include="..\src\shader.h" />
|
<ClInclude Include="src\buffer.h" />
|
||||||
<ClInclude Include="..\src\vertex.h" />
|
<ClInclude Include="src\camera.h" />
|
||||||
|
<ClInclude Include="src\engine.h" />
|
||||||
|
<ClInclude Include="src\entity.h" />
|
||||||
|
<ClInclude Include="src\light.h" />
|
||||||
|
<ClInclude Include="src\logger.h" />
|
||||||
|
<ClInclude Include="src\material.h" />
|
||||||
|
<ClInclude Include="src\mesh.h" />
|
||||||
|
<ClInclude Include="src\model.h" />
|
||||||
|
<ClInclude Include="src\shader.h" />
|
||||||
|
<ClInclude Include="src\state.h" />
|
||||||
|
<ClInclude Include="src\texture.h" />
|
||||||
|
<ClInclude Include="src\vertex.h" />
|
||||||
|
<ClInclude Include="src\world.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\lib\glew\glew.c" />
|
<ClCompile Include="lib\glew\glew.c" />
|
||||||
<ClCompile Include="..\src\buffer.cpp" />
|
<ClCompile Include="src\buffer.cpp" />
|
||||||
<ClCompile Include="..\src\main.cpp" />
|
<ClCompile Include="src\camera.cpp" />
|
||||||
<ClCompile Include="..\src\shader.cpp" />
|
<ClCompile Include="src\engine.cpp" />
|
||||||
<ClCompile Include="..\src\vertex.cpp" />
|
<ClCompile Include="src\entity.cpp" />
|
||||||
|
<ClCompile Include="src\light.cpp" />
|
||||||
|
<ClCompile Include="src\logger.cpp" />
|
||||||
|
<ClCompile Include="src\main.cpp" />
|
||||||
|
<ClCompile Include="src\material.cpp" />
|
||||||
|
<ClCompile Include="src\mesh.cpp" />
|
||||||
|
<ClCompile Include="src\model.cpp" />
|
||||||
|
<ClCompile Include="src\shader.cpp" />
|
||||||
|
<ClCompile Include="src\texture.cpp" />
|
||||||
|
<ClCompile Include="src\vertex.cpp" />
|
||||||
|
<ClCompile Include="src\world.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\data\fragment.glsl" />
|
<None Include="data\shaders\fragment.glsl" />
|
||||||
<None Include="..\data\vertex.glsl" />
|
<None Include="data\shaders\vertex.glsl" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
134
ugine3d.vcxproj.filters
Normal file
134
ugine3d.vcxproj.filters
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="glfw">
|
||||||
|
<UniqueIdentifier>{422e20da-2cf0-4bda-9833-a89b7ab453a1}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="glew">
|
||||||
|
<UniqueIdentifier>{296e1ba9-28bc-4e0b-8d4e-413551edca96}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="stb">
|
||||||
|
<UniqueIdentifier>{e3c5a7f2-1d4b-4a9c-8f2e-9b5c8d7a6e4f}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Shaders">
|
||||||
|
<UniqueIdentifier>{0628083b-a31c-4825-822c-11b6f933e7bd}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="lib\glfw\glfw3.h">
|
||||||
|
<Filter>glfw</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="lib\glfw\glfw3native.h">
|
||||||
|
<Filter>glfw</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="lib\glew\GL\glew.h">
|
||||||
|
<Filter>glew</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="lib\stb\stb_image.h">
|
||||||
|
<Filter>stb</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\vertex.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\shader.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\buffer.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\state.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\mesh.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\entity.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\model.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\camera.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\world.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\engine.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\logger.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\material.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\texture.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="src\main.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="lib\glew\glew.c">
|
||||||
|
<Filter>glew</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\vertex.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\shader.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\buffer.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\mesh.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\entity.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\model.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\camera.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\world.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\engine.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\logger.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\material.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\texture.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="data\shaders\fragment.glsl">
|
||||||
|
<Filter>Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="data\shaders\vertex.glsl">
|
||||||
|
<Filter>Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@@ -1,19 +1,19 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<LocalDebuggerWorkingDirectory>..</LocalDebuggerWorkingDirectory>
|
<LocalDebuggerWorkingDirectory>$(ProjectDir)</LocalDebuggerWorkingDirectory>
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<LocalDebuggerWorkingDirectory>..</LocalDebuggerWorkingDirectory>
|
<LocalDebuggerWorkingDirectory>$(ProjectDir)</LocalDebuggerWorkingDirectory>
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<LocalDebuggerWorkingDirectory>..</LocalDebuggerWorkingDirectory>
|
<LocalDebuggerWorkingDirectory>$(ProjectDir)</LocalDebuggerWorkingDirectory>
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<LocalDebuggerWorkingDirectory>..</LocalDebuggerWorkingDirectory>
|
<LocalDebuggerWorkingDirectory>$(ProjectDir)</LocalDebuggerWorkingDirectory>
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
Reference in New Issue
Block a user