Compare commits
48 Commits
80e5f76ee4
...
shadows_sw
| Author | SHA1 | Date | |
|---|---|---|---|
|
2e6df6c08b
|
|||
| 9e7afb5fb5 | |||
| 34976b8865 | |||
|
3ee778cb92
|
|||
| 64eee9e607 | |||
| adf8c4d7f0 | |||
| 0fab015e25 | |||
| 51562dec9d | |||
| 52e9b19f37 | |||
| 7455a7341c | |||
| 91bc31e7db | |||
| eb5f50fc9d | |||
| 3c9386de63 | |||
| 69caa98d04 | |||
| 12695983d2 | |||
| 36540468dc | |||
| c8dcd5e9c0 | |||
| e3389bcc20 | |||
| 728c4a85ed | |||
| 6ddb3488e5 | |||
| 175cbe7064 | |||
| 50c5e5ae18 | |||
| c3f91d78f0 | |||
| 3cf466e5d3 | |||
| 65dd078f07 | |||
| 3ed7976257 | |||
| 4a1d58ef4c | |||
| 4e62165c80 | |||
|
9cc870c996
|
|||
|
a2695ae481
|
|||
|
2b0a5f82b5
|
|||
| 98ccefd057 | |||
| 71d391c91b | |||
| 4e02e154c6 | |||
| 7c6ca07323 | |||
| 7d30802cbd | |||
| b20068165f | |||
| cb944b62e4 | |||
| 1dfca0aeab | |||
| 953cece292 | |||
|
|
0f993e6c1c | ||
|
|
1afa4ea368 | ||
|
|
6150882794 | ||
| ce3df7d051 | |||
|
|
3b0d1ea0e2 | ||
| c865f9fc94 | |||
| f6f0dd151c | |||
| 52056a44bb |
223
.clang-format
Normal file
223
.clang-format
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignArrayOfStructures: Left
|
||||||
|
AlignConsecutiveAssignments:
|
||||||
|
Enabled: true
|
||||||
|
AcrossEmptyLines: true
|
||||||
|
AcrossComments: true
|
||||||
|
AlignCompound: false
|
||||||
|
PadOperators: true
|
||||||
|
AlignConsecutiveBitFields:
|
||||||
|
Enabled: true
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: true
|
||||||
|
AlignCompound: false
|
||||||
|
PadOperators: true
|
||||||
|
AlignConsecutiveDeclarations:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
PadOperators: false
|
||||||
|
AlignConsecutiveMacros:
|
||||||
|
Enabled: true
|
||||||
|
AcrossEmptyLines: true
|
||||||
|
AcrossComments: true
|
||||||
|
AlignCompound: false
|
||||||
|
PadOperators: true
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
AlignOperands: Align
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllArgumentsOnNextLine: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
AllowShortEnumsOnASingleLine: false
|
||||||
|
AllowShortBlocksOnASingleLine: Empty
|
||||||
|
AllowShortCaseLabelsOnASingleLine: true
|
||||||
|
AllowShortFunctionsOnASingleLine: Inline
|
||||||
|
AllowShortLambdasOnASingleLine: All
|
||||||
|
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
AttributeMacros:
|
||||||
|
- __capability
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: false
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: Never
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: false
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
BeforeLambdaBody: false
|
||||||
|
BeforeWhile: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: false
|
||||||
|
SplitEmptyRecord: false
|
||||||
|
SplitEmptyNamespace: true
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeConceptDeclarations: Always
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
BreakInheritanceList: BeforeComma
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializers: BeforeComma
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ColumnLimit: 140
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
QualifierAlignment: Leave
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DeriveLineEnding: false
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
EmptyLineAfterAccessModifier: Never
|
||||||
|
EmptyLineBeforeAccessModifier: Always
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
PackConstructorInitializers: CurrentLine
|
||||||
|
BasedOnStyle: ''
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
AllowAllConstructorInitializersOnNextLine: true
|
||||||
|
FixNamespaceComments: true
|
||||||
|
ForEachMacros:
|
||||||
|
- foreach
|
||||||
|
- Q_FOREACH
|
||||||
|
- BOOST_FOREACH
|
||||||
|
- piForeach
|
||||||
|
- piForeachC
|
||||||
|
- piForeachR
|
||||||
|
- piForeachRC
|
||||||
|
- piForeachCR
|
||||||
|
IfMacros:
|
||||||
|
- KJ_IF_MAYBE
|
||||||
|
IncludeBlocks: Regroup
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||||
|
Priority: 2
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||||
|
Priority: 3
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 1
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
IncludeIsMainRegex: '(Test)?$'
|
||||||
|
IncludeIsMainSourceRegex: ''
|
||||||
|
IndentAccessModifiers: false
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentCaseBlocks: false
|
||||||
|
IndentGotoLabels: false
|
||||||
|
IndentPPDirectives: AfterHash
|
||||||
|
IndentExternBlock: NoIndent
|
||||||
|
IndentRequiresClause: true
|
||||||
|
IndentWidth: 4
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
InsertBraces: false
|
||||||
|
InsertTrailingCommas: Wrapped
|
||||||
|
JavaScriptQuotes: Leave
|
||||||
|
JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
LambdaBodyIndentation: Signature
|
||||||
|
MacroBlockBegin: "PRIVATE_DEFINITION_START|STATIC_INITIALIZER_BEGIN"
|
||||||
|
MacroBlockEnd: "PRIVATE_DEFINITION_END|STATIC_INITIALIZER_END"
|
||||||
|
MaxEmptyLinesToKeep: 2
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCBinPackProtocolList: Auto
|
||||||
|
ObjCBlockIndentWidth: 2
|
||||||
|
ObjCBreakBeforeNestedBlockParam: true
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 19
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakOpenParenthesis: 0
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyBreakTemplateDeclaration: 10
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
|
PenaltyIndentedWhitespace: 0
|
||||||
|
PointerAlignment: Middle
|
||||||
|
PPIndentWidth: 2
|
||||||
|
ReferenceAlignment: Middle
|
||||||
|
ReflowComments: true
|
||||||
|
RemoveBracesLLVM: false
|
||||||
|
RequiresClausePosition: OwnLine
|
||||||
|
SeparateDefinitionBlocks: Leave
|
||||||
|
ShortNamespaceLines: 1
|
||||||
|
SortIncludes: CaseSensitive
|
||||||
|
SortJavaStaticImport: Before
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterLogicalNot: false
|
||||||
|
SpaceAfterTemplateKeyword: false
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCaseColon: false
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: false
|
||||||
|
SpaceBeforeInheritanceColon: false
|
||||||
|
SpaceBeforeParens: ControlStatementsExceptControlMacros
|
||||||
|
SpaceBeforeParensOptions:
|
||||||
|
AfterControlStatements: true
|
||||||
|
AfterForeachMacros: false
|
||||||
|
AfterFunctionDefinitionName: false
|
||||||
|
AfterFunctionDeclarationName: false
|
||||||
|
AfterIfMacros: false
|
||||||
|
AfterOverloadedOperator: false
|
||||||
|
AfterRequiresInClause: false
|
||||||
|
AfterRequiresInExpression: false
|
||||||
|
BeforeNonEmptyParentheses: false
|
||||||
|
SpaceAroundPointerQualifiers: Both
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: false
|
||||||
|
SpaceInEmptyBlock: false
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
SpacesInAngles: Never
|
||||||
|
SpacesInConditionalStatement: false
|
||||||
|
SpacesInContainerLiterals: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInLineCommentPrefix:
|
||||||
|
Minimum: 1
|
||||||
|
Maximum: -1
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
SpaceBeforeSquareBrackets: false
|
||||||
|
BitFieldColonSpacing: After
|
||||||
|
Standard: c++11
|
||||||
|
StatementAttributeLikeMacros:
|
||||||
|
- Q_EMIT
|
||||||
|
- PIMETA
|
||||||
|
StatementMacros:
|
||||||
|
- Q_UNUSED
|
||||||
|
- QT_REQUIRE_VERSION
|
||||||
|
- PRIVATE_DECLARATION
|
||||||
|
- NO_COPY_CLASS
|
||||||
|
- FOREVER_WAIT
|
||||||
|
- WAIT_FOREVER
|
||||||
|
TabWidth: 4
|
||||||
|
UseCRLF: false
|
||||||
|
UseTab: AlignWithSpaces
|
||||||
|
WhitespaceSensitiveMacros:
|
||||||
|
- STRINGIZE
|
||||||
|
- PP_STRINGIZE
|
||||||
|
- BOOST_PP_STRINGIZE
|
||||||
|
- NS_SWIFT_NAME
|
||||||
|
- CF_SWIFT_NAME
|
||||||
|
...
|
||||||
|
|
||||||
6
.editorconfig
Normal file
6
.editorconfig
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*.{h,c,cpp}]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = tab
|
||||||
|
tab_width = 4
|
||||||
@@ -6,7 +6,11 @@ endif()
|
|||||||
if (POLICY CMP0054)
|
if (POLICY CMP0054)
|
||||||
cmake_policy(SET CMP0054 NEW)
|
cmake_policy(SET CMP0054 NEW)
|
||||||
endif()
|
endif()
|
||||||
project(qglengine)
|
project(QGLEngine)
|
||||||
|
if (NOT DEFINED SHSTKPROJECT)
|
||||||
|
include(SHSTKQtMacros)
|
||||||
|
endif()
|
||||||
|
find_package(PIP REQUIRED)
|
||||||
find_package(QAD REQUIRED)
|
find_package(QAD REQUIRED)
|
||||||
shstk_qt_founded(QtVersions)
|
shstk_qt_founded(QtVersions)
|
||||||
set(_qgl_ok 0)
|
set(_qgl_ok 0)
|
||||||
@@ -19,61 +23,26 @@ endif()
|
|||||||
if (NOT _qgl_ok)
|
if (NOT _qgl_ok)
|
||||||
message(WARNING "Building ${PROJECT_NAME} available only on Qt5/6!")
|
message(WARNING "Building ${PROJECT_NAME} available only on Qt5/6!")
|
||||||
else()
|
else()
|
||||||
qad_find_qt(Core Gui OpenGL OpenGLWidgets Xml)
|
|
||||||
find_package(OpenGL REQUIRED)
|
|
||||||
include(SHSTKQtMacros)
|
include(SHSTKQtMacros)
|
||||||
|
|
||||||
set(qglengine_MAJOR 1)
|
set(QGLEngine_MAJOR 1)
|
||||||
set(qglengine_MINOR 0)
|
set(QGLEngine_MINOR 0)
|
||||||
set(qglengine_REVISION 0)
|
set(QGLEngine_REVISION 0)
|
||||||
set(qglengine_SUFFIX "rc")
|
set(QGLEngine_SUFFIX "rc")
|
||||||
set(qglengine_COMPANY SHS)
|
set(QGLEngine_COMPANY SHS)
|
||||||
set(qglengine_DOMAIN org.SHS)
|
set(QGLEngine_DOMAIN org.SHS)
|
||||||
|
|
||||||
if ("x${CMAKE_MODULE_PATH}" STREQUAL "x")
|
if ("x${CMAKE_MODULE_PATH}" STREQUAL "x")
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
shstk_begin_project(qglengine QGLENGINE)
|
shstk_begin_project(QGLEngine)
|
||||||
|
set(_qglengine_root_build "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
|
|
||||||
qad_sources(SRC)
|
add_subdirectory(src)
|
||||||
qad_sources(FSRC DIR "formats")
|
|
||||||
list(APPEND SRC ${FSRC})
|
|
||||||
qad_sources(FSRC DIR "core")
|
|
||||||
list(APPEND SRC ${FSRC})
|
|
||||||
qad_wrap(${SRC} HDRS out_HDR CPPS out_CPP QMS out_QM)
|
|
||||||
file(GLOB PHS "*_p.h" "formats/*_p.h" "core/*_p.h")
|
|
||||||
list(REMOVE_ITEM out_HDR "${PHS}")
|
|
||||||
import_version(qglengine_core qglengine)
|
|
||||||
set_deploy_property(qglengine_core ${qglengine_LIB_TYPE}
|
|
||||||
LABEL "QGLEngine core library"
|
|
||||||
FULLNAME "${qglengine_DOMAIN}.qglengine_core"
|
|
||||||
COMPANY "${qglengine_COMPANY}"
|
|
||||||
INFO "QGLEngine core library")
|
|
||||||
make_rc(qglengine_core _RC)
|
|
||||||
qad_add_library(qglengine_core ${qglengine_LIB_TYPE} out_CPP ${_RC})
|
|
||||||
qad_generate_export_header(qglengine_core)
|
|
||||||
list(APPEND out_HDR "${CMAKE_CURRENT_BINARY_DIR}/qglengine_core_export.h")
|
|
||||||
list(APPEND out_HDR "${qglengine_VERSION_FILE}")
|
|
||||||
qad_target_include_directories(qglengine_core PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/core")
|
|
||||||
qad_target_link_libraries(qglengine_core QAD::Widgets assimp ${OPENGL_LIBRARIES})
|
|
||||||
message(STATUS "Building QGLEngine version ${qglengine_VERSION} (${qglengine_LIB_TYPE_MSG}) for ${QtVersions}")
|
|
||||||
list(APPEND QT_MULTILIB_LIST qglengine_core)
|
|
||||||
add_subdirectory(widgets)
|
|
||||||
shstk_copy_to_parent()
|
shstk_copy_to_parent()
|
||||||
shstk_qad_install("qglengine" FALSE "qglengine_core" "${out_HDR}" "out_QM")
|
|
||||||
if (NOT DEFINED ANDROID_PLATFORM)
|
|
||||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/plugin")
|
|
||||||
#add_subdirectory(plugin)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
qad_sources(test_SRC DIR "qglview_test")
|
shstk_install(qglengine FALSE "" "${QGLEngine_VERSION_FILE}")
|
||||||
qad_wrap(${test_SRC} CPPS test_CPP)
|
|
||||||
qad_add_executable(qglengine_test test_CPP)
|
|
||||||
qad_target_link_libraries(qglengine_test qglengine_core qglengine_widgets)
|
|
||||||
qad_target_include_directories(qglengine_test PRIVATE ${QAD_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/core" "${CMAKE_CURRENT_SOURCE_DIR}/widgets")
|
|
||||||
|
|
||||||
file(GLOB CMAKES "cmake/*.cmake" "cmake/*.in")
|
file(GLOB CMAKES "cmake/*.cmake" "cmake/*.in")
|
||||||
install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules)
|
install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules)
|
||||||
|
|
||||||
|
|||||||
@@ -11,22 +11,21 @@ These targets include directories and dependencies
|
|||||||
cmake_policy(SET CMP0011 NEW) # don`t affect includer policies
|
cmake_policy(SET CMP0011 NEW) # don`t affect includer policies
|
||||||
cmake_policy(SET CMP0020 NEW) # Automatically link Qt executables to qtmain target on Windows
|
cmake_policy(SET CMP0020 NEW) # Automatically link Qt executables to qtmain target on Windows
|
||||||
|
|
||||||
|
find_package(PIP REQUIRED)
|
||||||
find_package(QAD REQUIRED)
|
find_package(QAD REQUIRED)
|
||||||
include(QtWraps)
|
include(QtWraps)
|
||||||
include(SHSTKMacros)
|
include(SHSTKMacros)
|
||||||
|
|
||||||
shstk_is_parent_exists(hasParent PARENT_DIRECTORY)
|
shstk_is_parent_exists(hasParent PARENT_DIRECTORY)
|
||||||
|
|
||||||
shstk_set_find_dirs(qglengine QGLEngine)
|
shstk_set_find_dirs(QGLEngine)
|
||||||
set(_SEARCH_DIR ${qglengine_LIBDIR})
|
|
||||||
|
|
||||||
if (NOT BUILDING_qglengine)
|
if (NOT BUILDING_QGLEngine)
|
||||||
list(APPEND _SEARCH_DIR $ENV{SMSDK_DIR}/lib)
|
shstk_find_header(QGLEngine "qglengine_version.h" ${QGLEngine_INCDIR})
|
||||||
shstk_find_header(qglengine QGLENGINE "qglengine_version.h" "")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(QGLENGINE_FIND_VERSION VERSION_GREATER QGLENGINE_VERSION)
|
if(QGLEngine_FIND_VERSION VERSION_GREATER QGLEngine_VERSION)
|
||||||
message(FATAL_ERROR "QGLENGINE version ${QGLENGINE_VERSION} is available, but ${QGLENGINE_FIND_VERSION} requested!")
|
message(FATAL_ERROR "QGLEngine version ${QGLEngine_VERSION} is available, but ${QGLEngine_FIND_VERSION} requested!")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(__libs "core;widgets")
|
set(__libs "core;widgets")
|
||||||
@@ -40,15 +39,15 @@ foreach (_l ${__libs})
|
|||||||
set(__libs_${_l} "")
|
set(__libs_${_l} "")
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
set(__deps_core "QAD::Widgets")
|
set(__deps_core "QAD::Widgets;QAD::PIQtUtils")
|
||||||
set(__deps_widgets "QGLEngine::Core")
|
set(__deps_widgets "QGLEngine::Core")
|
||||||
|
|
||||||
#message("find QGLEngine ${BUILDING_qglengine}")
|
#message("find QGLEngine ${BUILDING_QGLEngine}")
|
||||||
|
|
||||||
if (BUILDING_qglengine)
|
if (BUILDING_QGLEngine)
|
||||||
|
|
||||||
if (NOT SET_TARGETS_qglengine)
|
if (NOT SET_TARGETS_QGLEngine)
|
||||||
set(SET_TARGETS_qglengine ON CACHE BOOL "")
|
set(SET_TARGETS_QGLEngine ON CACHE BOOL "")
|
||||||
#message("create aliases")
|
#message("create aliases")
|
||||||
foreach(_l ${__libs})
|
foreach(_l ${__libs})
|
||||||
foreach(_v ${_QT_VERSIONS_})
|
foreach(_v ${_QT_VERSIONS_})
|
||||||
@@ -71,7 +70,7 @@ else()
|
|||||||
foreach(_l ${__libs})
|
foreach(_l ${__libs})
|
||||||
foreach(_v ${_QT_VERSIONS_})
|
foreach(_v ${_QT_VERSIONS_})
|
||||||
set(_m ${__module_${_l}})
|
set(_m ${__module_${_l}})
|
||||||
find_library(QGLENGINE_LIBRARY_${_l}${_v} qglengine_${_l}${_v} HINTS ${_SEARCH_DIR})
|
find_library(QGLENGINE_LIBRARY_${_l}${_v} qglengine_${_l}${_v} HINTS ${QGLEngine_LIBDIR})
|
||||||
#message("found ${_l}${_v} = ${QGLENGINE_LIBRARY_${_l}${_v}} (${qglengine_INCLUDES})")
|
#message("found ${_l}${_v} = ${QGLENGINE_LIBRARY_${_l}${_v}} (${qglengine_INCLUDES})")
|
||||||
if((NOT TARGET QGLEngine::${_m}${_v}) AND QGLENGINE_LIBRARY_${_l}${_v})
|
if((NOT TARGET QGLEngine::${_m}${_v}) AND QGLENGINE_LIBRARY_${_l}${_v})
|
||||||
#message("imported QGLEngine::${_m}${_v} = ${QGLENGINE_LIBRARY_${_l}${_v}}")
|
#message("imported QGLEngine::${_m}${_v} = ${QGLENGINE_LIBRARY_${_l}${_v}}")
|
||||||
@@ -87,7 +86,7 @@ else()
|
|||||||
endforeach()
|
endforeach()
|
||||||
set_target_properties(QGLEngine::${_m}${_v} PROPERTIES
|
set_target_properties(QGLEngine::${_m}${_v} PROPERTIES
|
||||||
IMPORTED_LOCATION "${QGLENGINE_LIBRARY_${_l}${_v}}"
|
IMPORTED_LOCATION "${QGLENGINE_LIBRARY_${_l}${_v}}"
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "${qglengine_INCLUDES}"
|
INTERFACE_INCLUDE_DIRECTORIES "${QGLEngine_INCLUDES}"
|
||||||
INTERFACE_LINK_LIBRARIES "${_deps}")
|
INTERFACE_LINK_LIBRARIES "${_deps}")
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL Buffer
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLBUFFER_H
|
|
||||||
#define GLBUFFER_H
|
|
||||||
|
|
||||||
#include "gltypes.h"
|
|
||||||
|
|
||||||
|
|
||||||
class Buffer
|
|
||||||
{
|
|
||||||
friend class ObjectBase;
|
|
||||||
public:
|
|
||||||
Buffer(GLenum target, GLenum usage = GL_DYNAMIC_DRAW);
|
|
||||||
~Buffer();
|
|
||||||
|
|
||||||
void init (QOpenGLExtraFunctions * f);
|
|
||||||
void destroy (QOpenGLExtraFunctions * f);
|
|
||||||
|
|
||||||
void bind (QOpenGLExtraFunctions * f);
|
|
||||||
void release (QOpenGLExtraFunctions * f);
|
|
||||||
void * map (QOpenGLExtraFunctions * f, GLbitfield mode, int size = -1);
|
|
||||||
void unmap (QOpenGLExtraFunctions * f);
|
|
||||||
|
|
||||||
// returns true if size changed
|
|
||||||
bool resize (QOpenGLExtraFunctions * f, int new_size);
|
|
||||||
void load (QOpenGLExtraFunctions * f, const void * data, int size, int offset = 0);
|
|
||||||
|
|
||||||
GLuint ID() const {return buffer_;}
|
|
||||||
GLenum usage() const {return usage_;}
|
|
||||||
GLenum target() const {return target_;}
|
|
||||||
void setTarget(GLenum t) {target_ = t;}
|
|
||||||
bool isInit() const {return buffer_ != 0;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
GLenum target_, usage_;
|
|
||||||
GLuint buffer_;
|
|
||||||
int prev_size;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // GLBUFFER_H
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL CubeTexture
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLCUBEMAP_H
|
|
||||||
#define GLCUBEMAP_H
|
|
||||||
|
|
||||||
#include "glshaders_types.h"
|
|
||||||
#include "chunkstream.h"
|
|
||||||
|
|
||||||
QVector<QVector3D> loadFileHDR(const QString & path, QSize * size = 0);
|
|
||||||
|
|
||||||
class CubeTexture {
|
|
||||||
public:
|
|
||||||
CubeTexture(QOpenGLExtraFunctions * f_, int _size, const GLenum & _format = GL_RGB16F);
|
|
||||||
bool init();
|
|
||||||
void destroy();
|
|
||||||
void bind(int channel = 0);
|
|
||||||
void release();
|
|
||||||
void resize(int _size) {size = _size; changed_ = true;}
|
|
||||||
void loadHDR(const QVector<QVector3D> & data, QSize sz);
|
|
||||||
void setFileHDR(const QString & path);
|
|
||||||
QString fileHDR() const {return hdr_path;}
|
|
||||||
GLenum format() const {return format_;}
|
|
||||||
void setFormat(GLenum f) {format_ = f; changed_ = true;}
|
|
||||||
GLuint id() const {return id_;}
|
|
||||||
bool isInit() const {return id_ != 0;}
|
|
||||||
void load();
|
|
||||||
private:
|
|
||||||
|
|
||||||
QOpenGLExtraFunctions * f;
|
|
||||||
bool changed_;
|
|
||||||
int size;
|
|
||||||
GLenum format_;
|
|
||||||
GLuint id_;
|
|
||||||
QString hdr_path;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // GLCUBEMAP_H
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL Framebuffer
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLFRAMEBUFFER_H
|
|
||||||
#define GLFRAMEBUFFER_H
|
|
||||||
|
|
||||||
#include "glbuffer.h"
|
|
||||||
|
|
||||||
|
|
||||||
class Framebuffer
|
|
||||||
{
|
|
||||||
friend class FramebufferMipmap;
|
|
||||||
public:
|
|
||||||
Framebuffer(QOpenGLExtraFunctions * f_, int colorAttachments = 1, bool withDepth = true, GLenum colorFormat = GL_RGBA8, GLenum _target = GL_TEXTURE_2D);
|
|
||||||
Framebuffer(QOpenGLExtraFunctions * f_, QVector<GLenum> colors_, bool withDepth = true, GLenum _target = GL_TEXTURE_2D);
|
|
||||||
virtual ~Framebuffer();
|
|
||||||
|
|
||||||
GLuint id() const {return fbo;}
|
|
||||||
GLuint colorTexture(int index = 0) const {return colors[index];}
|
|
||||||
GLuint depthTexture() const {return tex_d;}
|
|
||||||
GLenum target() const {return target_;}
|
|
||||||
bool isInit() const {return fbo != 0;}
|
|
||||||
int width() const {return wid;}
|
|
||||||
int height() const {return hei;}
|
|
||||||
QSize size() const {return QSize(wid, hei);}
|
|
||||||
QRect rect() const {return QRect(0, 0, wid, hei);}
|
|
||||||
QImage grab() const;
|
|
||||||
QVector<float> grabF(int index) const;
|
|
||||||
void queryPoint(int index, QPoint p);
|
|
||||||
void queryPoints(int index, QRect rect, GLenum pixel_format = GL_UNSIGNED_BYTE);
|
|
||||||
void queryImage(int index);
|
|
||||||
uint getPoint() const;
|
|
||||||
QVector<uint> getPointsByte() const;
|
|
||||||
QVector<QVector4D> getPointsFloat() const;
|
|
||||||
QImage getImage() const;
|
|
||||||
int queriedPoints() const {return pbo_queried;}
|
|
||||||
void blit(int index_from, GLuint fb_to, int index_to, QRect from, QRect to, GLbitfield mask = GL_COLOR_BUFFER_BIT, GLenum filter = GL_NEAREST) const;
|
|
||||||
|
|
||||||
void resize(int width, int height, bool force = false);
|
|
||||||
void bind();
|
|
||||||
void release();
|
|
||||||
void setReadBuffer(int index) {glReadBuffer(GL_COLOR_ATTACHMENT0 + index);}
|
|
||||||
void setWriteBuffer(int index);
|
|
||||||
void setWriteBuffers(const int * indeces, int count);
|
|
||||||
void setWriteBuffers(const QVector<int> & indeces) {setWriteBuffers(indeces.constData(), indeces.size());}
|
|
||||||
void setWriteBuffers();
|
|
||||||
void unsetWriteBuffers();
|
|
||||||
void enablePixelBuffer();
|
|
||||||
void setColorTextureFiltering(int index, GLenum filter);
|
|
||||||
|
|
||||||
void copyDepthFrom(GLuint tex) {;}
|
|
||||||
void bindColorTexture(int index, int channel = 0);
|
|
||||||
void bindColorTextures();
|
|
||||||
void bindDepthTexture(int channel);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void deleteGLRenderbuffer(GLuint & drbo);
|
|
||||||
void deleteGLFramebuffer(GLuint & fbo);
|
|
||||||
|
|
||||||
bool is_depth, is_changed;
|
|
||||||
int pbo_queried;
|
|
||||||
QOpenGLExtraFunctions * f;
|
|
||||||
mutable Buffer pbo;
|
|
||||||
QVector<GLuint> colors;
|
|
||||||
QVector<GLenum> color_formats;
|
|
||||||
GLenum target_;
|
|
||||||
GLuint fbo, drbo, tex_d;
|
|
||||||
GLint prev_view[4], wid, hei;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // GLFRAMEBUFFER_H
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL FramebufferMipmap
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <QOpenGLExtraFunctions>
|
|
||||||
#include "glframebuffer_mipmap.h"
|
|
||||||
#include <QTime>
|
|
||||||
|
|
||||||
|
|
||||||
FramebufferMipmap::FramebufferMipmap(const Framebuffer & fb, int index_from_, int levels): src_fb(fb) {
|
|
||||||
index_from = index_from_;
|
|
||||||
for (int i = 0; i < levels; ++i)
|
|
||||||
fbo << new Framebuffer(fb.f, 1, false, fb.color_formats[index_from]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FramebufferMipmap::~FramebufferMipmap() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FramebufferMipmap::resize() {
|
|
||||||
QSize sz = src_fb.size();
|
|
||||||
for (int i = 0; i < fbo.size(); ++i) {
|
|
||||||
sz /= 2;
|
|
||||||
fbo[i]->resize(sz.width(), sz.height());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FramebufferMipmap::create() {
|
|
||||||
if (fbo.isEmpty()) return;
|
|
||||||
src_fb.blit(index_from, fbo[0]->id(), 0, src_fb.rect(), fbo[0]->rect(), GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
|
||||||
for (int i = 0; i < fbo.size() - 1; ++i)
|
|
||||||
fbo[i]->blit(0, fbo[i + 1]->id(), 0, fbo[i]->rect(), fbo[i + 1]->rect(), GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL FramebufferMipmap
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLFRAMEBUFFER_MIPMAP_H
|
|
||||||
#define GLFRAMEBUFFER_MIPMAP_H
|
|
||||||
|
|
||||||
#include "glframebuffer.h"
|
|
||||||
|
|
||||||
|
|
||||||
class FramebufferMipmap
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FramebufferMipmap(const Framebuffer & fb, int index_from_, int levels = 2);
|
|
||||||
virtual ~FramebufferMipmap();
|
|
||||||
|
|
||||||
int levelsCount() const {return fbo.size();}
|
|
||||||
int lastLevel() const {return fbo.size() - 1;}
|
|
||||||
Framebuffer & plane(int level) {return *fbo[level];}
|
|
||||||
Framebuffer & lastPlane() {return *fbo[lastLevel()];}
|
|
||||||
int width (int level) const {return fbo[level]->wid;}
|
|
||||||
int height(int level) const {return fbo[level]->hei;}
|
|
||||||
QSize size(int level) const {return fbo[level]->size();}
|
|
||||||
QRect rect(int level) const {return fbo[level]->rect();}
|
|
||||||
|
|
||||||
void resize();
|
|
||||||
void create();
|
|
||||||
|
|
||||||
private:
|
|
||||||
int index_from;
|
|
||||||
const Framebuffer & src_fb;
|
|
||||||
QVector<Framebuffer*> fbo;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // GLFRAMEBUFFER_MIPMAP_H
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL Material
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "gltypes.h"
|
|
||||||
#include "gltexture_manager.h"
|
|
||||||
#include "qglview.h"
|
|
||||||
|
|
||||||
using namespace QGLEngineShaders;
|
|
||||||
|
|
||||||
|
|
||||||
Map::Map() {
|
|
||||||
bitmap_id = 0;
|
|
||||||
color_amount = 1.f;
|
|
||||||
color_offset = 0.f;
|
|
||||||
bitmap_scale = QPointF(1., 1.);
|
|
||||||
use_bitmap = false;
|
|
||||||
_changed = true;
|
|
||||||
_layer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Map::setBitmapPath(const QString & p) {
|
|
||||||
bitmap_path = p;
|
|
||||||
_changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Map::load(TextureManager * tm) {
|
|
||||||
if (bitmap_id == 0)
|
|
||||||
bitmap_id = tm->loadTexture(bitmap_path, true, _type == mtNormal);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Map::copyToQGLMap(QGLMap & m) const {
|
|
||||||
m.amount = color_amount;
|
|
||||||
m.offset = color_offset;
|
|
||||||
m.scale = QVector2D(bitmap_scale);
|
|
||||||
if (hasBitmap() && use_bitmap) {
|
|
||||||
m.array_index = tarMaps;
|
|
||||||
m.map_index = _layer;
|
|
||||||
} else {
|
|
||||||
m.array_index = tarEmpty;
|
|
||||||
m.map_index = (_type == mtNormal ? emrBlue : emrWhite);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Material::Material(const QString _name) {
|
|
||||||
setTypes();
|
|
||||||
name = _name;
|
|
||||||
color_diffuse = Qt::white;
|
|
||||||
color_emission = Qt::black;
|
|
||||||
glass = false;
|
|
||||||
transparency = reflectivity = 0.f;
|
|
||||||
map_roughness.color_amount = 0.75f;
|
|
||||||
map_metalness.color_amount = 0.25f;
|
|
||||||
iof = 1.f;
|
|
||||||
dispersion = 0.05f;
|
|
||||||
_changed = true;
|
|
||||||
_index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint Material::hash() {
|
|
||||||
return qHash(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Material::hasTransparency() const {
|
|
||||||
return float(color_diffuse.alphaF()) * (1.f - transparency) < 1.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Material::isMapsChanged() const {
|
|
||||||
return map_diffuse ._changed ||
|
|
||||||
map_normal ._changed ||
|
|
||||||
map_metalness._changed ||
|
|
||||||
map_roughness._changed ||
|
|
||||||
map_emission ._changed ||
|
|
||||||
map_relief ._changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Material::isMapChanged(int type) const {
|
|
||||||
switch (type) {
|
|
||||||
case mtDiffuse : return map_diffuse ._changed;
|
|
||||||
case mtNormal : return map_normal ._changed;
|
|
||||||
case mtMetalness: return map_metalness._changed;
|
|
||||||
case mtRoughness: return map_roughness._changed;
|
|
||||||
case mtEmission : return map_emission ._changed;
|
|
||||||
case mtRelief : return map_relief ._changed;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Material::load(TextureManager * tm) {
|
|
||||||
map_diffuse .load(tm);
|
|
||||||
map_normal .load(tm);
|
|
||||||
map_metalness.load(tm);
|
|
||||||
map_roughness.load(tm);
|
|
||||||
map_emission .load(tm);
|
|
||||||
map_relief .load(tm);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Material::setMapsChanged() {
|
|
||||||
map_diffuse ._changed = true;
|
|
||||||
map_normal ._changed = true;
|
|
||||||
map_metalness._changed = true;
|
|
||||||
map_roughness._changed = true;
|
|
||||||
map_emission ._changed = true;
|
|
||||||
map_relief ._changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Material::setTypes() {
|
|
||||||
map_diffuse ._type = mtDiffuse ;
|
|
||||||
map_normal ._type = mtNormal ;
|
|
||||||
map_metalness._type = mtMetalness;
|
|
||||||
map_roughness._type = mtRoughness;
|
|
||||||
map_emission ._type = mtEmission ;
|
|
||||||
map_relief ._type = mtRelief ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Material::detectMaps() {
|
|
||||||
map_diffuse .use_bitmap = !map_diffuse .bitmap_path.isEmpty();
|
|
||||||
map_normal .use_bitmap = !map_normal .bitmap_path.isEmpty();
|
|
||||||
map_metalness.use_bitmap = !map_metalness.bitmap_path.isEmpty();
|
|
||||||
map_roughness.use_bitmap = !map_roughness.bitmap_path.isEmpty();
|
|
||||||
map_emission .use_bitmap = !map_emission .bitmap_path.isEmpty();
|
|
||||||
map_relief .use_bitmap = !map_relief .bitmap_path.isEmpty();
|
|
||||||
}
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL Material
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLMATERIAL_H
|
|
||||||
#define GLMATERIAL_H
|
|
||||||
|
|
||||||
#include "glshaders_types.h"
|
|
||||||
#include "chunkstream.h"
|
|
||||||
|
|
||||||
|
|
||||||
class Map {
|
|
||||||
public:
|
|
||||||
Map();
|
|
||||||
void setBitmapPath(const QString & p);
|
|
||||||
void clearBitmap() {setBitmapPath(QString());}
|
|
||||||
bool hasBitmap() const {return !bitmap_path.isEmpty();}
|
|
||||||
void load(TextureManager * tm);
|
|
||||||
void copyToQGLMap(QGLEngineShaders::QGLMap & m) const;
|
|
||||||
QString bitmap_path;
|
|
||||||
GLuint bitmap_id;
|
|
||||||
QPointF bitmap_offset;
|
|
||||||
QPointF bitmap_scale;
|
|
||||||
float color_amount;
|
|
||||||
float color_offset;
|
|
||||||
bool use_bitmap;
|
|
||||||
|
|
||||||
bool _changed;
|
|
||||||
int _type, _layer;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Material {
|
|
||||||
public:
|
|
||||||
Material(const QString _name = QString());
|
|
||||||
uint hash();
|
|
||||||
bool hasTransparency() const;
|
|
||||||
bool isMapsChanged() const;
|
|
||||||
bool isMapChanged(int type) const;
|
|
||||||
void load(TextureManager * tm);
|
|
||||||
void setMapsChanged();
|
|
||||||
void setTypes();
|
|
||||||
void detectMaps();
|
|
||||||
QString name;
|
|
||||||
QColor color_diffuse;
|
|
||||||
QColor color_emission;
|
|
||||||
bool glass;
|
|
||||||
float transparency;
|
|
||||||
float reflectivity;
|
|
||||||
float iof;
|
|
||||||
float dispersion;
|
|
||||||
Map map_diffuse ;
|
|
||||||
Map map_normal ;
|
|
||||||
Map map_metalness;
|
|
||||||
Map map_roughness;
|
|
||||||
Map map_emission ;
|
|
||||||
Map map_relief ;
|
|
||||||
bool _changed;
|
|
||||||
int _index;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
inline QDataStream & operator <<(QDataStream & s, const Map & m) {
|
|
||||||
ChunkStream cs;
|
|
||||||
cs.add(1, m.bitmap_path).add(2, m.color_amount).add(3, m.color_offset).add(6, m.bitmap_scale)
|
|
||||||
.add(7, m.use_bitmap);
|
|
||||||
s << cs.data(); return s;
|
|
||||||
}
|
|
||||||
inline QDataStream & operator >>(QDataStream & s, Map & m) {
|
|
||||||
ChunkStream cs(s);
|
|
||||||
cs.readAll();
|
|
||||||
cs.get(1, m.bitmap_path).get(2, m.color_amount).get(3, m.color_offset).get(6, m.bitmap_scale)
|
|
||||||
.get(7, m.use_bitmap);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QDataStream & operator <<(QDataStream & s, const Material * m) {
|
|
||||||
ChunkStream cs;
|
|
||||||
cs.add(1, m->name).add(2, m->color_diffuse).add(4, m->color_emission)
|
|
||||||
.add(5, m->transparency).add(6, m->reflectivity).add(7, m->glass).add(8, m->map_diffuse).add(9, m->map_normal)
|
|
||||||
.add(10, m->map_relief).add(11, m->map_metalness).add(12, m->map_roughness).add(13, m->map_emission);
|
|
||||||
s << (cs.data()); return s;
|
|
||||||
}
|
|
||||||
inline QDataStream & operator >>(QDataStream & s, Material *& m) {
|
|
||||||
m = new Material();
|
|
||||||
ChunkStream cs(s);
|
|
||||||
while (!cs.atEnd()) {
|
|
||||||
switch (cs.read()) {
|
|
||||||
case 1: cs.get(m->name); break;
|
|
||||||
case 2: cs.get(m->color_diffuse); break;
|
|
||||||
case 4: cs.get(m->color_emission); break;
|
|
||||||
case 5: cs.get(m->transparency); break;
|
|
||||||
case 6: cs.get(m->reflectivity); break;
|
|
||||||
case 7: cs.get(m->glass); break;
|
|
||||||
case 8: cs.get(m->map_diffuse); break;
|
|
||||||
case 9: cs.get(m->map_normal); break;
|
|
||||||
case 10: cs.get(m->map_relief); break;
|
|
||||||
case 11: cs.get(m->map_metalness); break;
|
|
||||||
case 12: cs.get(m->map_roughness); break;
|
|
||||||
case 13: cs.get(m->map_emission); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m->setTypes();
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // GLMATERIAL_H
|
|
||||||
104
core/glmesh.h
104
core/glmesh.h
@@ -1,104 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL Mesh
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLMESH_H
|
|
||||||
#define GLMESH_H
|
|
||||||
|
|
||||||
#include <chunkstream.h>
|
|
||||||
#include "glvertexobject.h"
|
|
||||||
|
|
||||||
|
|
||||||
class Mesh
|
|
||||||
{
|
|
||||||
friend QDataStream & operator <<(QDataStream & s, const Mesh * m);
|
|
||||||
friend QDataStream & operator >>(QDataStream & s, Mesh *& m);
|
|
||||||
public:
|
|
||||||
Mesh(GLenum geom_type_ = GL_TRIANGLES);
|
|
||||||
~Mesh();
|
|
||||||
|
|
||||||
Mesh * clone();
|
|
||||||
|
|
||||||
void init (QOpenGLExtraFunctions * f);
|
|
||||||
void destroy (QOpenGLExtraFunctions * f);
|
|
||||||
bool rebuffer(QOpenGLExtraFunctions * f);
|
|
||||||
void draw (QOpenGLExtraFunctions * f, int count, int type = 0);
|
|
||||||
void clear();
|
|
||||||
void loadObject (QOpenGLExtraFunctions * f, const QGLEngineShaders::Object & object, int type = 0);
|
|
||||||
void loadObjects (QOpenGLExtraFunctions * f, const QVector<QGLEngineShaders::Object> & objects, int type = 0);
|
|
||||||
void loadSelections(QOpenGLExtraFunctions * f, const QVector<uchar> & sels, int type = 0);
|
|
||||||
|
|
||||||
int verticesCount() const {return vertices_.size();}
|
|
||||||
int trianglesCount() const {return triangles_.size();}
|
|
||||||
int linesCount() const {return lines_.size();}
|
|
||||||
bool isInit() const {return buffer_geom.isInit();}
|
|
||||||
bool isEmpty() const {return vertices_.isEmpty();}
|
|
||||||
uint hash() const;
|
|
||||||
|
|
||||||
bool isObjectsChanged (int type = 0) const;
|
|
||||||
bool isSelectionChanged (int type = 0) const;
|
|
||||||
void setObjectsChanged (int type = 0, bool yes = true);
|
|
||||||
void setSelectionChanged(int type = 0, bool yes = true);
|
|
||||||
void setAllObjectsChanged (bool yes = true);
|
|
||||||
void setAllSelectionChanged(bool yes = true);
|
|
||||||
|
|
||||||
QVector<QVector3D> & vertices () {changed = hash_changed = true; return vertices_;}
|
|
||||||
QVector<QVector3D> & normals () {changed = hash_changed = true; return normals_;}
|
|
||||||
QVector<QVector2D> & texcoords() {changed = hash_changed = true; return texcoords_;}
|
|
||||||
QVector< Vector3i> & indicesTriangles() {changed = hash_changed = true; return triangles_;}
|
|
||||||
QVector< Vector2i> & indicesLines () {changed = hash_changed = true; return lines_;}
|
|
||||||
|
|
||||||
void translatePoints(const QVector3D & dp);
|
|
||||||
void translatePoints(const double & x, const double & y, const double & z) {translatePoints(QVector3D(x, y, z));}
|
|
||||||
void scalePoints (const QVector3D & dp);
|
|
||||||
void scalePoints (const double & s) {scalePoints(QVector3D(s, s, s));}
|
|
||||||
void rotatePoints (const double & angle, const QVector3D & a);
|
|
||||||
void rotatePoints (const double & angle, const double & x, const double & y, const double & z) {rotatePoints(angle, QVector3D(x, y, z));}
|
|
||||||
void transformPoints(const QMatrix4x4 & mat);
|
|
||||||
void flipNormals();
|
|
||||||
void append(const Mesh * m);
|
|
||||||
|
|
||||||
bool saveToFile(const QString & filename);
|
|
||||||
bool loadFromFile(const QString & filename);
|
|
||||||
|
|
||||||
Box3D boundingBox() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void calculateNormals();
|
|
||||||
void calculateTangents();
|
|
||||||
VertexObject * vaoByType(int type);
|
|
||||||
|
|
||||||
QVector<QVector3D> vertices_, normals_, tangents_, bitangents_;
|
|
||||||
QVector<QVector2D> texcoords_;
|
|
||||||
QVector< Vector3i> triangles_;
|
|
||||||
QVector< Vector2i> lines_;
|
|
||||||
|
|
||||||
QVector<QGLEngineShaders::Vertex> data_;
|
|
||||||
GLenum geom_type;
|
|
||||||
Buffer buffer_geom, buffer_ind;
|
|
||||||
QMap<int, VertexObject * > vao_map;
|
|
||||||
mutable uint hash_;
|
|
||||||
mutable bool hash_changed;
|
|
||||||
int vert_count;
|
|
||||||
bool changed;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
QDataStream & operator <<(QDataStream & s, const Mesh * m);
|
|
||||||
QDataStream & operator >>(QDataStream & s, Mesh *& m);
|
|
||||||
|
|
||||||
#endif // GLMESH_H
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL Primitives
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLPRIMITIVE_CUBE_H
|
|
||||||
#define GLPRIMITIVE_CUBE_H
|
|
||||||
|
|
||||||
#include "gltypes.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Primitive {
|
|
||||||
|
|
||||||
|
|
||||||
Mesh * plane(float width = 1., float length = 1.);
|
|
||||||
|
|
||||||
Mesh * cube(float width = 1., float length = 1., float height = 1.);
|
|
||||||
|
|
||||||
Mesh * ellipsoid(int segments_wl, int segments_h, float radius = 1., float end_angle = 360.);
|
|
||||||
|
|
||||||
Mesh * disc(int segments, float radius = 1., float end_angle = 360.);
|
|
||||||
|
|
||||||
Mesh * cone(int segments, float radius = 1., float height = 1.);
|
|
||||||
|
|
||||||
Mesh * cylinder(int segments, float radius = 1., float height = 1., float end_angle = 360.);
|
|
||||||
|
|
||||||
Mesh * arrow(int segments = 16, float thick = 0.04, float angle = 30.); // length = 1
|
|
||||||
|
|
||||||
Mesh * torus(int segments_main = 30, int segments_second = 16, float radius_main = 2.5, float radius_second = 0.5, float end_angle = 360.);
|
|
||||||
|
|
||||||
|
|
||||||
Mesh * lineFrame(QVector3D p0, QVector3D p1);
|
|
||||||
|
|
||||||
Mesh * cubeFrame(float width = 1., float length = 1., float height = 1.);
|
|
||||||
|
|
||||||
Mesh * ellipsoidFrame(int segments_wl, int segments_h, float radius = 1.);
|
|
||||||
|
|
||||||
Mesh * coneFrame(int segments, float radius = 1., float height = 1.);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // GLPRIMITIVE_CUBE_H
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
QGLEngineShaders
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLSHADERS_H
|
|
||||||
#define GLSHADERS_H
|
|
||||||
|
|
||||||
#include "gltypes.h"
|
|
||||||
|
|
||||||
namespace QGLEngineShaders {
|
|
||||||
|
|
||||||
bool loadShadersMulti(QOpenGLShaderProgram *& prog, const QString & file, bool add_qgl = true, const QStringList & defines = QStringList());
|
|
||||||
bool loadShaders(QOpenGLShaderProgram *& prog, const QStringList & files, bool add_qgl = true, const QStringList & defines = QStringList());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // GLSHADERS_H
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
/*
|
|
||||||
QGLEngineShaders
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLSHADERS_HEADERS_H
|
|
||||||
#define GLSHADERS_HEADERS_H
|
|
||||||
|
|
||||||
namespace QGLEngineShaders {
|
|
||||||
|
|
||||||
const int max_materials = 128;
|
|
||||||
const int max_lights = 256 ;
|
|
||||||
|
|
||||||
const char qgl_common_head[] =
|
|
||||||
"#version 400 core\n"
|
|
||||||
"";
|
|
||||||
|
|
||||||
const char qgl_vertex_head[] =
|
|
||||||
"layout(location = 1 ) in vec3 qgl_Vertex ;\n"
|
|
||||||
"layout(location = 2 ) in vec3 qgl_Normal ;\n"
|
|
||||||
"layout(location = 3 ) in vec3 qgl_Tangent ;\n"
|
|
||||||
"layout(location = 4 ) in vec3 qgl_Bitangent ;\n"
|
|
||||||
"layout(location = 5 ) in vec2 qgl_Texture ;\n"
|
|
||||||
"layout(location = 6 ) in uint qgl_Material ;\n"
|
|
||||||
"layout(location = 7 ) in uint qgl_ObjectSelected;\n"
|
|
||||||
"layout(location = 8 ) in uint qgl_ObjectID ;\n"
|
|
||||||
"layout(location = 9 ) in vec4 qgl_ObjectColor ;\n"
|
|
||||||
"layout(location = 10) in mat4 qgl_ModelMatrix ;\n"
|
|
||||||
"out vec2 qgl_FragTexture;\n"
|
|
||||||
"flat out uint qgl_MaterialIndex;\n"
|
|
||||||
"uniform mat4 qgl_ViewMatrix;\n"
|
|
||||||
"uniform mat4 qgl_ViewProjMatrix;\n"
|
|
||||||
"mat3 qgl_getNormalMatrix() {return inverse(mat3(qgl_ViewMatrix * qgl_ModelMatrix));}\n"
|
|
||||||
"mat3 qgl_getTangentMatrix() {return mat3(qgl_ViewMatrix * qgl_ModelMatrix);}\n"
|
|
||||||
"vec4 qgl_ftransform() {return qgl_ViewProjMatrix * (qgl_ModelMatrix * vec4(qgl_Vertex, 1));}\n"
|
|
||||||
"";
|
|
||||||
|
|
||||||
const char qgl_fragment_head[] =
|
|
||||||
"in vec2 qgl_FragTexture;\n"
|
|
||||||
"flat in uint qgl_MaterialIndex;\n"
|
|
||||||
"out vec4 qgl_FragData[gl_MaxDrawBuffers];\n"
|
|
||||||
"vec4 qgl_materialTexture(uint type, vec2 coord, vec4 tex_shift) {\n"
|
|
||||||
" coord *= qgl_material[qgl_MaterialIndex].map[type].scale;\n"
|
|
||||||
" vec4 t = texture(qgl_texture_array[qgl_material[qgl_MaterialIndex].map[type].array_index],\n"
|
|
||||||
" vec3(coord, qgl_material[qgl_MaterialIndex].map[type].map_index));\n"
|
|
||||||
" t += tex_shift;\n"
|
|
||||||
" t.rgb = t.rgb * qgl_material[qgl_MaterialIndex].map[type].amount + qgl_material[qgl_MaterialIndex].map[type].offset;\n"
|
|
||||||
" return t;\n"
|
|
||||||
"}\n"
|
|
||||||
"#define qgl_FragColor qgl_FragData[0]\n"
|
|
||||||
"";
|
|
||||||
|
|
||||||
const char qgl_geometry_head[] =
|
|
||||||
"";
|
|
||||||
|
|
||||||
const char qgl_structs[] =
|
|
||||||
"#define QGL_MAPS_COUNT 6\n"
|
|
||||||
"#define QGL_MAP_DIFFUSE 0\n"
|
|
||||||
"#define QGL_MAP_NORMAL 1\n"
|
|
||||||
"#define QGL_MAP_METALNESS 2\n"
|
|
||||||
"#define QGL_MAP_ROUGHNESS 3\n"
|
|
||||||
"#define QGL_MAP_EMISSION 4\n"
|
|
||||||
"#define QGL_MAP_RELIEF 5\n"
|
|
||||||
"#define QGL_TEXTURE_ARRAY_EMPTY 0\n"
|
|
||||||
"#define QGL_TEXTURE_ARRAY_MAPS 1\n"
|
|
||||||
"struct QGLMap {\n"
|
|
||||||
" float offset;\n"
|
|
||||||
" float amount;\n"
|
|
||||||
" vec2 scale;\n"
|
|
||||||
" uint array_index;\n"
|
|
||||||
" uint map_index;\n"
|
|
||||||
"};\n"
|
|
||||||
"struct QGLMaterial {\n"
|
|
||||||
" vec4 color_diffuse;\n"
|
|
||||||
" vec4 color_emission;\n"
|
|
||||||
" float transparency;\n"
|
|
||||||
" float reflectivity;\n"
|
|
||||||
" float iof;\n"
|
|
||||||
" float dispersion;\n"
|
|
||||||
" QGLMap map[QGL_MAPS_COUNT];\n"
|
|
||||||
"};\n"
|
|
||||||
"struct QGLLightParameter {\n"
|
|
||||||
" vec4 color;\n"
|
|
||||||
" vec4 decay_intensity;\n"
|
|
||||||
" vec4 angles;\n"
|
|
||||||
"};\n"
|
|
||||||
"struct QGLLightPosition {\n"
|
|
||||||
" vec4 position;\n"
|
|
||||||
" vec4 direction;\n"
|
|
||||||
"};\n"
|
|
||||||
"";
|
|
||||||
|
|
||||||
const char qgl_uniform[] =
|
|
||||||
"layout (std140) uniform QGLMaterialData {\n"
|
|
||||||
" QGLMaterial qgl_material[128];\n"
|
|
||||||
"};\n"
|
|
||||||
"layout (std140) uniform QGLLightParameterData {\n"
|
|
||||||
" QGLLightParameter qgl_light_parameter[256];\n"
|
|
||||||
"};\n"
|
|
||||||
"layout (std140) uniform QGLLightPositionData {\n"
|
|
||||||
" QGLLightPosition qgl_light_position[256];\n"
|
|
||||||
"};\n"
|
|
||||||
"uniform sampler2DArray qgl_texture_array[2];\n"
|
|
||||||
"";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // GLSHADERS_HEADERS_H
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
/*
|
|
||||||
QGLEngineShaders
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "glshaders_types.h"
|
|
||||||
|
|
||||||
|
|
||||||
QGLEngineShaders::QGLMap::QGLMap() {
|
|
||||||
offset = 0.;
|
|
||||||
amount = 1.;
|
|
||||||
scale = QVector2D(1., 1.);
|
|
||||||
array_index = map_index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QGLEngineShaders::QGLMaterial::QGLMaterial() {
|
|
||||||
color_diffuse = QVector4D(1., 1., 1., 0.);
|
|
||||||
color_emission = QVector4D(0., 0., 0., 0.);
|
|
||||||
transparency = 0.;
|
|
||||||
reflectivity = 0.;
|
|
||||||
iof = 0.;
|
|
||||||
dispersion = 0.;
|
|
||||||
map[mtNormal].map_index = emrBlue;
|
|
||||||
map[mtRoughness].amount = 0.75;
|
|
||||||
map[mtMetalness].amount = 0.25;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLEngineShaders::prepareDrawGeom(QOpenGLExtraFunctions * f) {
|
|
||||||
//qDebug() << "prepareDrawGeom";
|
|
||||||
|
|
||||||
f->glEnableVertexAttribArray(pos_loc );
|
|
||||||
f->glEnableVertexAttribArray(normal_loc );
|
|
||||||
f->glEnableVertexAttribArray(tangent_loc );
|
|
||||||
f->glEnableVertexAttribArray(bitangent_loc);
|
|
||||||
f->glEnableVertexAttribArray(tex_loc );
|
|
||||||
|
|
||||||
int size = sizeof(Vertex);
|
|
||||||
f->glVertexAttribPointer(pos_loc , 3, GL_FLOAT, GL_FALSE, size, (const void *)pos_offset );
|
|
||||||
f->glVertexAttribPointer(normal_loc , 3, GL_FLOAT, GL_FALSE, size, (const void *)normal_offset );
|
|
||||||
f->glVertexAttribPointer(tangent_loc , 3, GL_FLOAT, GL_FALSE, size, (const void *)tangent_offset );
|
|
||||||
f->glVertexAttribPointer(bitangent_loc, 3, GL_FLOAT, GL_FALSE, size, (const void *)bitangent_offset);
|
|
||||||
f->glVertexAttribPointer(tex_loc , 2, GL_FLOAT, GL_FALSE, size, (const void *)tex_offset );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLEngineShaders::prepareDrawObj(QOpenGLExtraFunctions * f) {
|
|
||||||
//qDebug() << "prepareDrawObj";
|
|
||||||
|
|
||||||
f->glEnableVertexAttribArray(material_loc );
|
|
||||||
f->glEnableVertexAttribArray(object_id_loc);
|
|
||||||
f->glEnableVertexAttribArray(color_loc );
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
|
||||||
f->glEnableVertexAttribArray(modelmatrix_loc + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLsizei size = sizeof(Object);
|
|
||||||
f->glVertexAttribIPointer(material_loc , 1, GL_UNSIGNED_INT , size, (const void *)material_offset );
|
|
||||||
f->glVertexAttribIPointer(object_id_loc, 1, GL_UNSIGNED_INT , size, (const void *)object_id_offset);
|
|
||||||
f->glVertexAttribPointer (color_loc , 4, GL_FLOAT, GL_FALSE, size, (const void *)color_offset );
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
|
||||||
f->glVertexAttribPointer(modelmatrix_loc + i, 4, GL_FLOAT, GL_FALSE, size, (const void *)(modelmatrix_offset + sizeof(QVector4D)*i));
|
|
||||||
}
|
|
||||||
|
|
||||||
f->glVertexAttribDivisor(material_loc , 1);
|
|
||||||
f->glVertexAttribDivisor(object_id_loc, 1);
|
|
||||||
f->glVertexAttribDivisor(color_loc , 1);
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
|
||||||
f->glVertexAttribDivisor(modelmatrix_loc + i, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLEngineShaders::prepareDrawSel(QOpenGLExtraFunctions * f) {
|
|
||||||
//qDebug() << "prepareDrawObj";
|
|
||||||
|
|
||||||
f->glEnableVertexAttribArray(is_selected_loc);
|
|
||||||
GLsizei size = 1;
|
|
||||||
f->glVertexAttribIPointer(is_selected_loc, 1, GL_UNSIGNED_BYTE, size, (const void *)is_selected_offset);
|
|
||||||
f->glVertexAttribDivisor(is_selected_loc, 1);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
/*
|
|
||||||
QGLEngineShaders
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLSHADERS_TYPES_H
|
|
||||||
#define GLSHADERS_TYPES_H
|
|
||||||
|
|
||||||
#include "gltypes.h"
|
|
||||||
|
|
||||||
namespace QGLEngineShaders {
|
|
||||||
|
|
||||||
|
|
||||||
/// VBO
|
|
||||||
|
|
||||||
// geometry
|
|
||||||
const GLsizei pos_offset = 0;
|
|
||||||
const GLsizei normal_offset = sizeof(QVector3D) + pos_offset ;
|
|
||||||
const GLsizei tangent_offset = sizeof(QVector3D) + normal_offset ;
|
|
||||||
const GLsizei bitangent_offset = sizeof(QVector3D) + tangent_offset ;
|
|
||||||
const GLsizei tex_offset = sizeof(QVector3D) + bitangent_offset;
|
|
||||||
|
|
||||||
// object
|
|
||||||
const GLsizei material_offset = 0;
|
|
||||||
const GLsizei object_id_offset = sizeof(GLuint ) + material_offset ;
|
|
||||||
const GLsizei color_offset = sizeof(GLuint ) + object_id_offset ;
|
|
||||||
const GLsizei modelmatrix_offset = sizeof(QVector4D) + color_offset;
|
|
||||||
|
|
||||||
const GLsizei is_selected_offset = 0;
|
|
||||||
|
|
||||||
const GLuint pos_loc = 1 ; // qgl_Vertex
|
|
||||||
const GLuint normal_loc = 2 ; // qgl_Normal
|
|
||||||
const GLuint tangent_loc = 3 ; // qgl_Tangent
|
|
||||||
const GLuint bitangent_loc = 4 ; // qgl_Bitangent
|
|
||||||
const GLuint tex_loc = 5 ; // qgl_Texture
|
|
||||||
|
|
||||||
const GLuint material_loc = 6 ; // qgl_Material
|
|
||||||
const GLuint object_id_loc = 8 ; // qgl_ObjectID
|
|
||||||
const GLuint color_loc = 9 ; // qgl_ObjectColor
|
|
||||||
const GLuint modelmatrix_loc = 10; // qgl_ModelViewProjectionMatrix
|
|
||||||
|
|
||||||
const GLuint is_selected_loc = 7 ; // qgl_ObjectSelected
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
struct Vertex {
|
|
||||||
QVector3D pos;
|
|
||||||
QVector3D normal;
|
|
||||||
QVector3D tangent;
|
|
||||||
QVector3D bitangent;
|
|
||||||
QVector2D tex;
|
|
||||||
};
|
|
||||||
struct Object {
|
|
||||||
Object() {
|
|
||||||
material = object_id = 0;
|
|
||||||
color = QVector4D(1,1,1,1);
|
|
||||||
QMatrix4x4().copyDataTo(modelmatrix);
|
|
||||||
}
|
|
||||||
GLuint material;
|
|
||||||
GLuint object_id;
|
|
||||||
QVector4D color;
|
|
||||||
GLfloat modelmatrix[16];
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
|
|
||||||
/// UBO
|
|
||||||
|
|
||||||
enum BindingPoints {
|
|
||||||
bpMaterials,
|
|
||||||
bpLightParameters,
|
|
||||||
bpLightPositions,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum MapType {
|
|
||||||
mtDiffuse = 0,
|
|
||||||
mtNormal = 1,
|
|
||||||
mtMetalness = 2,
|
|
||||||
mtRoughness = 3,
|
|
||||||
mtEmission = 4,
|
|
||||||
mtRelief = 5,
|
|
||||||
};
|
|
||||||
enum TextureArrayRole {
|
|
||||||
tarEmpty = 0,
|
|
||||||
tarMaps = 1,
|
|
||||||
};
|
|
||||||
enum EmptyMapRole {
|
|
||||||
emrWhite = 0,
|
|
||||||
emrBlue = 1,
|
|
||||||
};
|
|
||||||
#define QGL_MAPS_COUNT 6
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
struct QGLMap {
|
|
||||||
QGLMap();
|
|
||||||
GLfloat offset;
|
|
||||||
GLfloat amount;
|
|
||||||
QVector2D scale;
|
|
||||||
GLuint array_index;
|
|
||||||
GLuint map_index;
|
|
||||||
GLfloat __res_2[2];
|
|
||||||
};
|
|
||||||
struct QGLMaterial {
|
|
||||||
QGLMaterial();
|
|
||||||
QVector4D color_diffuse;
|
|
||||||
QVector4D color_emission;
|
|
||||||
GLfloat transparency;
|
|
||||||
GLfloat reflectivity;
|
|
||||||
GLfloat iof;
|
|
||||||
GLfloat dispersion;
|
|
||||||
QGLMap map[QGL_MAPS_COUNT];
|
|
||||||
};
|
|
||||||
struct QGLLightParameter {
|
|
||||||
QVector4D color;
|
|
||||||
QVector4D decay_intensity; // [^0, ^1, ^2, intensity]
|
|
||||||
QVector4D angles; // [start, cos(start), end, cos(end)]
|
|
||||||
};
|
|
||||||
struct QGLLightPosition {
|
|
||||||
QVector4D position;
|
|
||||||
QVector4D direction;
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
void prepareDrawGeom(QOpenGLExtraFunctions * f);
|
|
||||||
void prepareDrawObj (QOpenGLExtraFunctions * f);
|
|
||||||
void prepareDrawSel (QOpenGLExtraFunctions * f);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // GLSHADERS_TYPES_H
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL Texture2DArray
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLTEXTUREARRAY_H
|
|
||||||
#define GLTEXTUREARRAY_H
|
|
||||||
|
|
||||||
#include "gltypes.h"
|
|
||||||
|
|
||||||
|
|
||||||
class Texture2DArray
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Texture2DArray(bool filter);
|
|
||||||
~Texture2DArray();
|
|
||||||
|
|
||||||
void init (QOpenGLExtraFunctions * f);
|
|
||||||
void destroy (QOpenGLExtraFunctions * f);
|
|
||||||
|
|
||||||
void bind (QOpenGLExtraFunctions * f, int channel = 0);
|
|
||||||
void release (QOpenGLExtraFunctions * f);
|
|
||||||
|
|
||||||
// returns true if size changed
|
|
||||||
bool resize (QOpenGLExtraFunctions * f, QSize new_size, int layers_count);
|
|
||||||
void load (QOpenGLExtraFunctions * f, const QImage & image, int layer);
|
|
||||||
void mipmaps (QOpenGLExtraFunctions * f);
|
|
||||||
|
|
||||||
GLuint ID() const {return texture_;}
|
|
||||||
bool isInit() const {return texture_ != 0;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
GLenum target_;
|
|
||||||
GLuint texture_;
|
|
||||||
QSize size_;
|
|
||||||
int layers_;
|
|
||||||
bool filtering_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // GLTEXTUREARRAY_H
|
|
||||||
304
core/gltypes.h
304
core/gltypes.h
@@ -1,304 +0,0 @@
|
|||||||
/*
|
|
||||||
QGLView Types
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLTYPES_H
|
|
||||||
#define GLTYPES_H
|
|
||||||
|
|
||||||
#if WIN32 || WIN64 || _WIN32 || _WIN64 || __WIN32__ || __WIN64__
|
|
||||||
# define WINDOWS
|
|
||||||
#endif
|
|
||||||
#if __QNX__ || __QNXNTO__
|
|
||||||
# define QNX
|
|
||||||
#endif
|
|
||||||
#ifdef __APPLE__
|
|
||||||
# define MAC
|
|
||||||
#endif
|
|
||||||
#ifndef WINDOWS
|
|
||||||
# ifndef QNX
|
|
||||||
# ifndef MAC
|
|
||||||
# define LINUX
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
#if __GNUC__
|
|
||||||
# define CC_GCC
|
|
||||||
#elif _MSC_VER
|
|
||||||
# define CC_VC
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
//#ifndef WINDOWS
|
|
||||||
//# ifdef MAC
|
|
||||||
//# include <OpenGL/gl.h>
|
|
||||||
//# include <OpenGL/glu.h>
|
|
||||||
//# include <GLUT/glut.h>
|
|
||||||
//# else
|
|
||||||
//# include <GL/gl.h>
|
|
||||||
//# include <GL/glext.h>
|
|
||||||
//# include <GL/glu.h>
|
|
||||||
//# endif
|
|
||||||
//#endif
|
|
||||||
#include <QOpenGLExtraFunctions>
|
|
||||||
#include <QOpenGLShader>
|
|
||||||
#include <QOpenGLShaderProgram>
|
|
||||||
#include <qopenglext.h>
|
|
||||||
#include <cmath>
|
|
||||||
#include <float.h>
|
|
||||||
#include <QMatrix4x4>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QDataStream>
|
|
||||||
#include <QColor>
|
|
||||||
#include <QVector2D>
|
|
||||||
#include <QVector3D>
|
|
||||||
#include <QImage>
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QDir>
|
|
||||||
#ifndef QNX
|
|
||||||
# include <cmath>
|
|
||||||
# include <complex>
|
|
||||||
#else
|
|
||||||
# include <math.h>
|
|
||||||
# include <complex.h>
|
|
||||||
#endif
|
|
||||||
#include <iostream>
|
|
||||||
#include "qglengine_version.h"
|
|
||||||
#include "qglengine_core_export.h"
|
|
||||||
|
|
||||||
|
|
||||||
//#ifdef WINDOWS
|
|
||||||
//# define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
|
|
||||||
//# define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
#ifndef M_PI
|
|
||||||
# define M_PI 3.14159265358979323846
|
|
||||||
#endif
|
|
||||||
#ifndef M_2PI
|
|
||||||
# define M_2PI 6.28318530717958647692
|
|
||||||
#endif
|
|
||||||
#ifndef M_PI_3
|
|
||||||
# define M_PI_3 1.04719755119659774615
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef GL_RGBA16F
|
|
||||||
# define GL_RGBA16F GL_RGBA16F_ARB
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using std::complex;
|
|
||||||
|
|
||||||
#ifndef PIP_VERSION
|
|
||||||
typedef long long llong;
|
|
||||||
typedef unsigned char uchar;
|
|
||||||
typedef unsigned short int ushort;
|
|
||||||
typedef unsigned int uint;
|
|
||||||
typedef unsigned long ulong;
|
|
||||||
typedef unsigned long long ullong;
|
|
||||||
typedef long double ldouble;
|
|
||||||
|
|
||||||
const float deg2rad = atanf(1.f) / 45.f;
|
|
||||||
const float rad2deg = 45.f / atanf(1.f);
|
|
||||||
|
|
||||||
# ifdef WINDOWS
|
|
||||||
inline int random() {return rand();}
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
#define random randomi
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CC_VC
|
|
||||||
inline float round(const float & v) {return floor(v + 0.5);}
|
|
||||||
#endif
|
|
||||||
inline float randomu() {return float(random()) / RAND_MAX;}
|
|
||||||
|
|
||||||
inline const QSizeF operator *(const QSizeF & f, const QSizeF & s) {return QSizeF(f.width() * s.width(), f.height() * s.height());}
|
|
||||||
#ifndef PIP_VERSION
|
|
||||||
template<typename T> inline void piSwap(T & f, T & s) {T t(f); f = s; s = t;}
|
|
||||||
template<typename Type> inline Type piMin(const Type & f, const Type & s) {return (f > s) ? s : f;}
|
|
||||||
template<typename Type> inline Type piMin(const Type & f, const Type & s, const Type & t) {return (f < s && f < t) ? f : ((s < t) ? s : t);}
|
|
||||||
template<typename Type> inline Type piMax(const Type & f, const Type & s) {return (f < s) ? s : f;}
|
|
||||||
template<typename Type> inline Type piMax(const Type & f, const Type & s, const Type & t) {return (f > s && f > t) ? f : ((s > t) ? s : t);}
|
|
||||||
template<typename Type> inline Type piClamp(const Type & v, const Type & min, const Type & max) {return (v > max ? max : (v < min ? min : v));}
|
|
||||||
inline ushort letobe_s(ushort v) {return (v << 8) | (v >> 8);}
|
|
||||||
inline uint letobe_i(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
|
|
||||||
#endif
|
|
||||||
// return [-1, 1]
|
|
||||||
inline float urand(const float & scale = 1.) {return ((float)rand() / RAND_MAX - .5f) * (scale + scale);}
|
|
||||||
// return [0, 1]
|
|
||||||
inline float uprand(const float & scale = 1.) {return ((float)rand() / RAND_MAX) * scale;}
|
|
||||||
QString readCharsUntilNull(QDataStream & s);
|
|
||||||
QString findFile(const QString & file, const QStringList & pathes);
|
|
||||||
inline QColor operator *(const QColor & c, float v) {return QColor(piClamp<int>(c.red() * v, 0, 255), piClamp<int>(c.green() * v, 0, 255), piClamp<int>(c.blue() * v, 0, 255), piClamp<int>(c.alpha() * v, 0, 255));}
|
|
||||||
inline QColor operator /(const QColor & c, float v) {return QColor(piClamp<int>(c.red() / v, 0, 255), piClamp<int>(c.green() / v, 0, 255), piClamp<int>(c.blue() / v, 0, 255), piClamp<int>(c.alpha() / v, 0, 255));}
|
|
||||||
|
|
||||||
|
|
||||||
inline void qglColor(const QColor & c) {glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());}
|
|
||||||
inline void glClearError() {int c = 100; while (glGetError() != GL_NO_ERROR && --c > 0) glGetError();}
|
|
||||||
inline void glSetCapEnabled(GLenum cap, bool on = true) {if (on) glEnable(cap); else glDisable(cap);}
|
|
||||||
inline void glSetPolygonMode(GLenum mode) {glPolygonMode(GL_FRONT_AND_BACK, mode);}
|
|
||||||
inline void deleteGLTexture(QOpenGLExtraFunctions * f, GLuint & tex) {if (tex != 0) f->glDeleteTextures(1, &tex); tex = 0;}
|
|
||||||
void glEnableDepth();
|
|
||||||
void glDisableDepth();
|
|
||||||
void glClearFramebuffer(const QColor & color = Qt::black, bool depth = true);
|
|
||||||
void glDrawQuad(QOpenGLShaderProgram * prog = nullptr, QVector4D * corner_dirs = nullptr, GLfloat x = -1.f, GLfloat y = -1.f, GLfloat w = 2.f, GLfloat h = 2.f);
|
|
||||||
void createGLTexture(QOpenGLExtraFunctions * f, GLuint & tex, int width, int height, const GLenum & format = GL_RGBA, const GLenum & target = GL_TEXTURE_2D);
|
|
||||||
void createGLTexture(QOpenGLExtraFunctions * f, GLuint & tex, const QImage & image, const GLenum & format = GL_RGBA, const GLenum & target = GL_TEXTURE_2D);
|
|
||||||
QMatrix4x4 glMatrixPerspective(float angle, float aspect, float near_);
|
|
||||||
QImage rotateQImageLeft(const QImage & im);
|
|
||||||
QImage rotateQImageRight(const QImage & im);
|
|
||||||
inline QImage rotateQImage180(const QImage & im) {return im.mirrored(true, true);}
|
|
||||||
|
|
||||||
class QGLView;
|
|
||||||
class MouseController;
|
|
||||||
class ObjectBase;
|
|
||||||
class AimedObject;
|
|
||||||
class Light;
|
|
||||||
class Camera;
|
|
||||||
class Texture;
|
|
||||||
class CubeTexture;
|
|
||||||
class Map;
|
|
||||||
class Material;
|
|
||||||
class TextureManager;
|
|
||||||
class Texture2DArray;
|
|
||||||
class Framebuffer;
|
|
||||||
class FramebufferMipmap;
|
|
||||||
class VertexObject;
|
|
||||||
class Mesh;
|
|
||||||
class Scene;
|
|
||||||
class RendererBase;
|
|
||||||
class Renderer;
|
|
||||||
class RendererMaterial;
|
|
||||||
class RendererService;
|
|
||||||
class RendererSelection;
|
|
||||||
|
|
||||||
enum RenderPass {
|
|
||||||
rpSolid,
|
|
||||||
rpTransparent,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef QList<ObjectBase*> ObjectBaseList;
|
|
||||||
|
|
||||||
struct Box3D {
|
|
||||||
GLfloat x;
|
|
||||||
GLfloat y;
|
|
||||||
GLfloat z;
|
|
||||||
GLfloat width;
|
|
||||||
GLfloat length;
|
|
||||||
GLfloat height;
|
|
||||||
GLfloat angle_z;
|
|
||||||
GLfloat angle_xy;
|
|
||||||
GLfloat angle_roll;
|
|
||||||
Box3D() {x = y = z = width = length = height = angle_z = angle_xy = angle_roll = 0.f;}
|
|
||||||
Box3D(const QVector3D & center, GLfloat hwid, GLfloat hlen, GLfloat hhei) {x = center.x() - hwid; y = center.y() - hlen; z = center.z() - hhei; width = 2 * hwid; length = 2 * hlen; height = 2 * hhei; angle_z = angle_xy = angle_roll = 0.f;}
|
|
||||||
Box3D(const QVector<QVector3D> & points);
|
|
||||||
bool isEmpty() const {return (qAbs(width) < 1E-6f) && (qAbs(length) < 1E-6f) && (qAbs(height) < 1E-6f);}
|
|
||||||
QVector3D randomPoint() const {return QVector3D(uprand(length) + x, uprand(width) + y, uprand(height) + z);}
|
|
||||||
QVector3D pos() const {return QVector3D(x, y, z);}
|
|
||||||
QVector3D size() const {return QVector3D(length, width, height);}
|
|
||||||
QVector3D center() const {return QVector3D(length / 2.f + x, width / 2.f + y, height / 2.f + z);}
|
|
||||||
QVector3D angles() const {return QVector3D(angle_xy, angle_roll, angle_z);}
|
|
||||||
QVector<QVector3D> corners() const;
|
|
||||||
void setPos(const QVector3D & p) {x = p.x(); y = p.y(); z = p.z();}
|
|
||||||
void setAngles(const QVector3D & a) {angle_xy = a.x(); angle_roll = a.y(); angle_z = a.z();}
|
|
||||||
void setSize(const QVector3D & s) {length = s.x(); width = s.y(); height = s.z();}
|
|
||||||
Box3D & moveTo(const QVector3D & v) {x = v.x(); y = v.y(); z = v.z(); return *this;}
|
|
||||||
Box3D & move(const QVector3D & v) {x += v.x(); y += v.y(); z += v.z(); return *this;}
|
|
||||||
Box3D movedTo(const QVector3D & v) const {Box3D t(*this); t.x = v.x(); t.y = v.y(); t.z = v.z(); return t;}
|
|
||||||
Box3D moved(const QVector3D & v) const {Box3D t(*this); t.x += v.x(); t.y += v.y(); t.z += v.z(); return t;}
|
|
||||||
Box3D & operator |=(const Box3D & o);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline QDebug operator <<(QDebug d, const Box3D & v) {d << "Box3D {start (" << v.x << "," << v.y << "," << v.z << "), size (" << v.length << "," << v.width << "," << v.height << ")}"; return d;}
|
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
struct Vector2i {
|
|
||||||
Vector2i(int p0_ = 0, int p1_ = 0) {p0 = p0_; p1 = p1_;}
|
|
||||||
Vector2i(const QString & str);
|
|
||||||
Vector2i movedX(const int & o) {return Vector2i(p0 + o, p1);}
|
|
||||||
Vector2i movedY(const int & o) {return Vector2i(p0, p1 + o);}
|
|
||||||
Vector2i moved(const int & x, const int & y) {return Vector2i(p0 + x, p1 + y);}
|
|
||||||
GLint p0;
|
|
||||||
GLint p1;
|
|
||||||
bool operator ==(const Vector2i & o) const {return p0 == o.p0 && p1 == o.p1;}
|
|
||||||
bool operator !=(const Vector2i & o) const {return p0 != o.p0 || p1 != o.p1;}
|
|
||||||
void operator +=(int v) {p0 += v; p1 += v;}
|
|
||||||
QVector2D toQVector2D() const {return QVector2D(p0, p1);}
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
inline Vector2i operator +(const Vector2i & f, const Vector2i & s) {return Vector2i(f.p0 + s.p0, f.p1 + s.p1);}
|
|
||||||
inline Vector2i operator -(const Vector2i & f, const Vector2i & s) {return Vector2i(f.p0 - s.p0, f.p1 - s.p1);}
|
|
||||||
inline Vector2i operator /(const Vector2i & f, const int & s) {return Vector2i(f.p0 / s, f.p1 / s);}
|
|
||||||
inline uint qHash(const Vector2i & v) {return v.p0 ^ ((v.p1 << 8) | (v.p1 >> 24));}
|
|
||||||
inline QDebug operator <<(QDebug d, const Vector2i & v) {d.nospace() << "{" << v.p0 << ", " << v.p1 << "}"; return d.space();}
|
|
||||||
|
|
||||||
inline QDataStream & operator <<(QDataStream & s, const Vector2i & v) {s << v.p0 << v.p1; return s;}
|
|
||||||
inline QDataStream & operator >>(QDataStream & s, Vector2i & v) {s >> v.p0 >> v.p1; return s;}
|
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
struct Vector3i {
|
|
||||||
Vector3i(int p0_ = 0, int p1_ = 0, int p2_ = 0) {p0 = p0_; p1 = p1_; p2 = p2_;}
|
|
||||||
Vector3i(const QString & str);
|
|
||||||
Vector3i movedX(const int & o) {return Vector3i(p0 + o, p1, p2);}
|
|
||||||
Vector3i movedY(const int & o) {return Vector3i(p0, p1 + o, p2);}
|
|
||||||
Vector3i movedZ(const int & o) {return Vector3i(p0, p1, p2 + o);}
|
|
||||||
Vector3i moved(const int & x, const int & y, const int & z) {return Vector3i(p0 + x, p1 + y, p2 + z);}
|
|
||||||
GLint p0;
|
|
||||||
GLint p1;
|
|
||||||
GLint p2;
|
|
||||||
bool operator ==(const Vector3i & o) const {return p0 == o.p0 && p1 == o.p1 && p2 == o.p2;}
|
|
||||||
bool operator !=(const Vector3i & o) const {return p0 != o.p0 || p1 != o.p1 || p2 != o.p2;}
|
|
||||||
void operator +=(int v) {p0 += v; p1 += v; p2 += v;}
|
|
||||||
QVector3D toQVector3D() const {return QVector3D(p0, p1, p2);}
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
inline Vector3i operator +(const Vector3i & f, const Vector3i & s) {return Vector3i(f.p0 + s.p0, f.p1 + s.p1, f.p2 + s.p2);}
|
|
||||||
inline Vector3i operator -(const Vector3i & f, const Vector3i & s) {return Vector3i(f.p0 - s.p0, f.p1 - s.p1, f.p2 - s.p2);}
|
|
||||||
inline Vector3i operator /(const Vector3i & f, const int & s) {return Vector3i(f.p0 / s, f.p1 / s, f.p2 / s);}
|
|
||||||
inline uint qHash(const Vector3i & v) {return v.p0 ^ ((v.p1 << 8) | (v.p1 >> 24)) ^ ((v.p2 << 16) | (v.p2 >> 16));}
|
|
||||||
inline QDebug operator <<(QDebug d, const Vector3i & v) {d.nospace() << "{" << v.p0 << ", " << v.p1 << ", " << v.p2 << "}"; return d.space();}
|
|
||||||
|
|
||||||
inline QDataStream & operator <<(QDataStream & s, const Vector3i & v) {s << v.p0 << v.p1 << v.p2; return s;}
|
|
||||||
inline QDataStream & operator >>(QDataStream & s, Vector3i & v) {s >> v.p0 >> v.p1 >> v.p2; return s;}
|
|
||||||
|
|
||||||
|
|
||||||
QVector3D vectorFromString(const QString & str);
|
|
||||||
QColor colorFromString(const QString & str);
|
|
||||||
inline QVector4D QColor2QVector(const QColor & c) {return QVector4D(c.redF(), c.greenF(), c.blueF(), c.alphaF());}
|
|
||||||
inline float cosABV(const QVector3D & v0, const QVector3D & v1) {
|
|
||||||
float l = v0.length() * v1.length();
|
|
||||||
if (l == 0.f) return 0.;
|
|
||||||
return (QVector3D::dotProduct(v0, v1)) / l;
|
|
||||||
}
|
|
||||||
inline void normalizeAngleRad(float & a) {while (a < 0.) a += M_2PI; while (a >= M_2PI) a -= M_2PI;}
|
|
||||||
inline void normalizeAngleDeg360(float & a) {while (a < 0.) a += 360. ; while (a >= 360. ) a -= 360. ;}
|
|
||||||
inline QVector3D projection(const QVector3D & v, const QVector3D & to) {return to.normalized() * v.length() * cosABV(v, to);}
|
|
||||||
QVector3D orthToVector(const QVector3D & v, const float & scale = 1.);
|
|
||||||
QVector3D rotateVector(const QVector3D & v, const QVector3D & a);
|
|
||||||
void setVectorLength(QVector3D & v, const float & l);
|
|
||||||
void lengthenVector(QVector3D & v, const float & l);
|
|
||||||
inline float squareLength(const QVector3D & from, const QVector3D & to) {return (to.x() - from.x())*(to.x() - from.x()) + (to.y() - from.y())*(to.y() - from.y()) + (to.z() - from.z())*(to.z() - from.z());}
|
|
||||||
inline QVector3D directionFromAngles(const QVector3D & a) {return rotateVector(QVector3D(1., 0., 0.), a);}
|
|
||||||
inline float frac(const float & x, const float & b) {return x - int(x / b) * b;}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // GLTYPES_H
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL VertexObject
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLVERTEXOBJECT_H
|
|
||||||
#define GLVERTEXOBJECT_H
|
|
||||||
|
|
||||||
#include "glbuffer.h"
|
|
||||||
#include "glshaders_types.h"
|
|
||||||
|
|
||||||
|
|
||||||
class VertexObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
VertexObject();
|
|
||||||
~VertexObject();
|
|
||||||
|
|
||||||
void init (QOpenGLExtraFunctions * f);
|
|
||||||
void destroy (QOpenGLExtraFunctions * f);
|
|
||||||
|
|
||||||
void bind (QOpenGLExtraFunctions * f);
|
|
||||||
void release (QOpenGLExtraFunctions * f);
|
|
||||||
|
|
||||||
void bindBuffers (QOpenGLExtraFunctions * f, Buffer & geom, Buffer & elem, bool force = false);
|
|
||||||
void loadObject (QOpenGLExtraFunctions * f, const QGLEngineShaders::Object & object);
|
|
||||||
void loadObjects (QOpenGLExtraFunctions * f, const QVector<QGLEngineShaders::Object> & objects);
|
|
||||||
void loadSelections(QOpenGLExtraFunctions * f, const QVector<uchar> & sels);
|
|
||||||
|
|
||||||
void draw(QOpenGLExtraFunctions * f, GLenum geom_type, int vert_cout, int obj_count);
|
|
||||||
|
|
||||||
GLuint ID() const {return vao_;}
|
|
||||||
bool isInit() const {return vao_ != 0;}
|
|
||||||
|
|
||||||
bool isObjectsChanged() const {return objects_changed;}
|
|
||||||
bool isSelectionChanged() const {return selected_changed;}
|
|
||||||
void setObjectsChanged(bool yes = true) {objects_changed = yes;}
|
|
||||||
void setSelectionChanged(bool yes = true) {selected_changed = yes;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void loadBuffer(QOpenGLExtraFunctions * f, Buffer & buf, const void * data, int size);
|
|
||||||
|
|
||||||
GLuint vao_;
|
|
||||||
Buffer buffer_obj, buffer_sel;
|
|
||||||
bool buffers_binded, objects_changed, selected_changed;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // GLVERTEXOBJECT_H
|
|
||||||
126
core/hdr.cpp
126
core/hdr.cpp
@@ -1,126 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL HDR
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "hdr_p.h"
|
|
||||||
#include <qmath.h>
|
|
||||||
#include <QByteArray>
|
|
||||||
|
|
||||||
#define RGBE_DATA_RED 2
|
|
||||||
#define RGBE_DATA_GREEN 1
|
|
||||||
#define RGBE_DATA_BLUE 0
|
|
||||||
/* number of floats per pixel */
|
|
||||||
#define RGBE_DATA_SIZE 3
|
|
||||||
|
|
||||||
|
|
||||||
void rgbe2float(float *red, float *green, float *blue, uchar rgbe[4]) {
|
|
||||||
float f;
|
|
||||||
if (rgbe[3]) {
|
|
||||||
f = static_cast<float>(ldexp(1.0,rgbe[3]-(int)(128+8)));
|
|
||||||
*red = rgbe[0] * f;
|
|
||||||
*green = rgbe[1] * f;
|
|
||||||
*blue = rgbe[2] * f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*red = *green = *blue = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* simple read routine. will not correctly handle run length encoding */
|
|
||||||
bool RGBE_ReadPixels(QDataStream * fp, float * data, int numpixels) {
|
|
||||||
uchar rgbe[4];
|
|
||||||
while(numpixels-- > 0) {
|
|
||||||
if (fp->readRawData((char*)rgbe, sizeof(rgbe)) < 1)
|
|
||||||
return false;
|
|
||||||
rgbe2float(&data[RGBE_DATA_RED], &data[RGBE_DATA_GREEN], &data[RGBE_DATA_BLUE],rgbe);
|
|
||||||
data += RGBE_DATA_SIZE;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool RGBE_ReadPixels_RLE(QDataStream * fp, float * data, int scanline_width, int num_scanlines) {
|
|
||||||
uchar rgbe[4], *ptr, *ptr_end;
|
|
||||||
int i, count;
|
|
||||||
uchar buf[2];
|
|
||||||
QByteArray scanline_buffer;
|
|
||||||
|
|
||||||
if ((scanline_width < 8)||(scanline_width > 0x7fff))
|
|
||||||
/* run length encoding is not allowed so read flat*/
|
|
||||||
return RGBE_ReadPixels(fp,data,scanline_width*num_scanlines);
|
|
||||||
scanline_buffer.resize(4*scanline_width);
|
|
||||||
/* read in each successive scanline */
|
|
||||||
while(num_scanlines > 0) {
|
|
||||||
if (fp->readRawData((char*)rgbe,sizeof(rgbe)) < 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ((rgbe[0] != 2)||(rgbe[1] != 2)||(rgbe[2] & 0x80)) {
|
|
||||||
/* this file is not run length encoded */
|
|
||||||
rgbe2float(&data[RGBE_DATA_RED],&data[RGBE_DATA_GREEN],&data[RGBE_DATA_BLUE],rgbe);
|
|
||||||
data += RGBE_DATA_SIZE;
|
|
||||||
return RGBE_ReadPixels(fp,data,scanline_width*num_scanlines-1);
|
|
||||||
}
|
|
||||||
if ((((int)rgbe[2])<<8 | rgbe[3]) != scanline_width) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ptr = (uchar*)scanline_buffer.data();
|
|
||||||
/* read each of the four channels for the scanline into the buffer */
|
|
||||||
for(i=0;i<4;i++) {
|
|
||||||
ptr_end = (uchar*)scanline_buffer.data() + ((i+1)*scanline_width);
|
|
||||||
while(ptr < ptr_end) {
|
|
||||||
if (fp->readRawData((char*)buf,sizeof(buf[0])*2) < 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (buf[0] > 128) {
|
|
||||||
/* a run of the same value */
|
|
||||||
count = buf[0]-128;
|
|
||||||
if ((count == 0)||(count > ptr_end - ptr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
while(count-- > 0)
|
|
||||||
*ptr++ = buf[1];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* a non-run */
|
|
||||||
count = buf[0];
|
|
||||||
if ((count == 0)||(count > ptr_end - ptr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*ptr++ = buf[1];
|
|
||||||
if (--count > 0) {
|
|
||||||
if (fp->readRawData((char*)ptr,sizeof(*ptr)*count) < 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ptr += count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* now convert data from buffer into floats */
|
|
||||||
for(i=0;i<scanline_width;i++) {
|
|
||||||
rgbe[0] = scanline_buffer[i];
|
|
||||||
rgbe[1] = scanline_buffer[i+scanline_width];
|
|
||||||
rgbe[2] = scanline_buffer[i+2*scanline_width];
|
|
||||||
rgbe[3] = scanline_buffer[i+3*scanline_width];
|
|
||||||
rgbe2float(&data[RGBE_DATA_RED],&data[RGBE_DATA_GREEN],
|
|
||||||
&data[RGBE_DATA_BLUE],rgbe);
|
|
||||||
data += RGBE_DATA_SIZE;
|
|
||||||
}
|
|
||||||
num_scanlines--;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
26
core/hdr_p.h
26
core/hdr_p.h
@@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL HDR
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HDR_P_H
|
|
||||||
#define HDR_P_H
|
|
||||||
|
|
||||||
#include <QDataStream>
|
|
||||||
|
|
||||||
bool RGBE_ReadPixels_RLE(QDataStream * fp, float * data, int scanline_width, int num_scanlines);
|
|
||||||
|
|
||||||
#endif // HDR_P_H
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL Loader Assimp
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LOADER_ASSIMP_H
|
|
||||||
#define LOADER_ASSIMP_H
|
|
||||||
|
|
||||||
#include "gltypes.h"
|
|
||||||
|
|
||||||
Scene * loadScene(const QString & filepath);
|
|
||||||
QStringList supportedFormats();
|
|
||||||
|
|
||||||
#endif // LOADER_ASSIMP_H
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL Loader QGL
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LOADER_QGL_H
|
|
||||||
#define LOADER_QGL_H
|
|
||||||
|
|
||||||
#include "gltypes.h"
|
|
||||||
#include <QFileInfo>
|
|
||||||
|
|
||||||
Scene * loadFromQGLFile(const QString & filepath);
|
|
||||||
bool saveToQGLFile(const QString & filepath, const Scene * scene);
|
|
||||||
|
|
||||||
#endif // LOADER_QGL_H
|
|
||||||
91
glcamera.cpp
91
glcamera.cpp
@@ -1,91 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL Camera
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "gltypes.h"
|
|
||||||
#include "qglview.h"
|
|
||||||
|
|
||||||
|
|
||||||
Camera::Camera() {
|
|
||||||
type_ = glCamera;
|
|
||||||
fov_ = 60.;
|
|
||||||
roll_ = 0.;
|
|
||||||
depth_start = 0.1f;
|
|
||||||
mirror_x = mirror_y = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QMatrix4x4 Camera::offsetMatrix() const {
|
|
||||||
QMatrix4x4 ret;
|
|
||||||
ret.translate(parent_ ? -offset_ : -aim());
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Camera::assign(const Camera & c) {
|
|
||||||
trans = c.trans;
|
|
||||||
aim_dist = c.aim_dist;
|
|
||||||
fov_ = c.fov_;
|
|
||||||
mirror_x = c.mirror_x;
|
|
||||||
mirror_y = c.mirror_y;
|
|
||||||
depth_start = c.depth_start;
|
|
||||||
buildTransform();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ObjectBase * Camera::clone(bool withChildren) {
|
|
||||||
Camera * o = new Camera(*this);
|
|
||||||
o->is_init = false;
|
|
||||||
o->name_ = name_;
|
|
||||||
o->scene_ = nullptr;
|
|
||||||
o->children_.clear();
|
|
||||||
if (withChildren) {
|
|
||||||
for (int i = 0; i < children_.size(); ++i)
|
|
||||||
o->addChild(children_[i]->clone(withChildren));
|
|
||||||
}
|
|
||||||
o->trans = trans;
|
|
||||||
o->aim_dist = aim_dist;
|
|
||||||
o->fov_ = fov_;
|
|
||||||
o->roll_ = roll_;
|
|
||||||
o->mirror_x = mirror_x;
|
|
||||||
o->mirror_y = mirror_y;
|
|
||||||
o->depth_start = depth_start;
|
|
||||||
o->meta = meta;
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QMatrix4x4 Camera::viewMatrix() const {
|
|
||||||
QMatrix4x4 ret;
|
|
||||||
//qDebug() << pos() << aim();
|
|
||||||
ret.translate(0., 0., -distance());
|
|
||||||
ret.rotate(-roll_, 0., 0., 1.);
|
|
||||||
ret *= trans.matrixRotateScale().inverted();
|
|
||||||
if (parent_) {
|
|
||||||
QMatrix4x4 pmat = parent_->worldTransform();
|
|
||||||
offset_ = pmat.column(3).toVector3D();
|
|
||||||
pmat(0, 3) = pmat(1, 3) = pmat(2, 3) = 0.;
|
|
||||||
pmat.translate(aim());
|
|
||||||
ret *= pmat.inverted();
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QMatrix4x4 Camera::projectionMatrix(double aspect) const {
|
|
||||||
return glMatrixPerspective(fov_, aspect, depth_start);
|
|
||||||
}
|
|
||||||
65
glcamera.h
65
glcamera.h
@@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL Camera
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLCAMERA_H
|
|
||||||
#define GLCAMERA_H
|
|
||||||
|
|
||||||
#include "globject.h"
|
|
||||||
|
|
||||||
|
|
||||||
class Camera: public AimedObject
|
|
||||||
{
|
|
||||||
friend QDataStream & operator <<(QDataStream & s, const ObjectBase * p);
|
|
||||||
friend QDataStream & operator >>(QDataStream & s, ObjectBase *& p);
|
|
||||||
public:
|
|
||||||
Camera();
|
|
||||||
|
|
||||||
void setFOV(const float & f) {fov_ = f;}
|
|
||||||
void setAngles(const QVector3D & a) {setRotation(a);}
|
|
||||||
void setAngleZ(const float & a) {setRotationZ(a);}
|
|
||||||
void setAngleXY(const float & a) {setRotationX(a);}
|
|
||||||
void setAngleRoll(const float & a) {roll_ = a;}
|
|
||||||
void setDepthStart(const float & d) {depth_start = d;}
|
|
||||||
void setMirrorX(bool yes) {mirror_x = yes;}
|
|
||||||
void setMirrorY(bool yes) {mirror_y = yes;}
|
|
||||||
|
|
||||||
float FOV() const {return fov_;}
|
|
||||||
float angleZ() const {return rotationZ();}
|
|
||||||
float angleXY() const {return rotationX();}
|
|
||||||
float angleRoll() const {return roll_;}
|
|
||||||
float depthStart() const {return depth_start;}
|
|
||||||
bool isMirrorX() const {return mirror_x;}
|
|
||||||
bool isMirrorY() const {return mirror_y;}
|
|
||||||
void assign(const Camera & c);
|
|
||||||
|
|
||||||
virtual ObjectBase * clone(bool withChildren = true);
|
|
||||||
QMatrix4x4 viewMatrix() const;
|
|
||||||
QMatrix4x4 projectionMatrix(double aspect) const;
|
|
||||||
QMatrix4x4 offsetMatrix() const;
|
|
||||||
|
|
||||||
QMatrix4x4 fullViewMatrix() const {return viewMatrix() * offsetMatrix();}
|
|
||||||
|
|
||||||
private:
|
|
||||||
mutable QVector3D offset_;
|
|
||||||
GLfloat fov_, roll_;
|
|
||||||
GLfloat depth_start;
|
|
||||||
bool mirror_x;
|
|
||||||
bool mirror_y;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // GLCAMERA_H
|
|
||||||
717
globject.cpp
717
globject.cpp
@@ -1,717 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL ObjectBase & Light
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "globject.h"
|
|
||||||
#include "glcamera.h"
|
|
||||||
#include "glscene.h"
|
|
||||||
#include "glmesh.h"
|
|
||||||
#include <chunkstream.h>
|
|
||||||
//static int _count = 0;
|
|
||||||
|
|
||||||
ObjectBase::ObjectBase(Mesh * geom, Material * mat) {
|
|
||||||
type_ = glMesh;
|
|
||||||
render_mode = View;
|
|
||||||
prev_pass = rpSolid;
|
|
||||||
parent_ = nullptr;
|
|
||||||
color_ = Qt::white;
|
|
||||||
is_root = is_init = selected_ = false;
|
|
||||||
visible_ = accept_fog = accept_light = cast_shadow = rec_shadow = select_ = true;
|
|
||||||
line_width = -1.;
|
|
||||||
id_ = 0;
|
|
||||||
blend_src = GL_SRC_ALPHA;
|
|
||||||
blend_dest = GL_ONE_MINUS_SRC_ALPHA;
|
|
||||||
type_ = glMesh;
|
|
||||||
raw_matrix = selected_aim = false;
|
|
||||||
mat_.setToIdentity();
|
|
||||||
scene_ = nullptr;
|
|
||||||
mesh_ = geom;
|
|
||||||
material_ = mat;
|
|
||||||
//qDebug() << "ObjectBase, now" << ++_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ObjectBase::~ObjectBase() {
|
|
||||||
//qDebug() << "~ObjectBase, now" << --_count;
|
|
||||||
if (parent_) parent_->children_.removeAll(this);
|
|
||||||
if (scene_) {
|
|
||||||
scene_->__objectDeleted(this);
|
|
||||||
scene_->setTreeChanged();
|
|
||||||
scene_->setTreeStructChanged();
|
|
||||||
}
|
|
||||||
foreach (ObjectBase * c, children_) {
|
|
||||||
c->parent_ = nullptr;
|
|
||||||
delete c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ObjectBase * ObjectBase::clone(bool withChildren) {
|
|
||||||
ObjectBase * o = new ObjectBase();
|
|
||||||
o->prev_pass = prev_pass;
|
|
||||||
o->is_init = false;
|
|
||||||
o->accept_light = accept_light;
|
|
||||||
o->accept_fog = accept_fog;
|
|
||||||
o->visible_ = visible_;
|
|
||||||
o->color_ = color_;
|
|
||||||
o->type_ = type_;
|
|
||||||
o->raw_matrix = raw_matrix;
|
|
||||||
o->mat_ = mat_;
|
|
||||||
o->trans = trans;
|
|
||||||
o->itransform_ = itransform_;
|
|
||||||
o->bound = bound;
|
|
||||||
o->name_ = name_;// + "_copy";
|
|
||||||
o->blend_src = blend_src;
|
|
||||||
o->blend_dest = blend_dest;
|
|
||||||
o->pos_h = pos_h;
|
|
||||||
o->material_ = material_;
|
|
||||||
o->mesh_ = mesh_;
|
|
||||||
o->meta = meta;
|
|
||||||
o->scene_ = nullptr;
|
|
||||||
if (withChildren) {
|
|
||||||
for (int i = 0; i < children_.size(); ++i)
|
|
||||||
o->addChild(children_[i]->clone(withChildren));
|
|
||||||
}
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::destroy() {
|
|
||||||
if (mesh_) delete mesh_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::init() {
|
|
||||||
calculateBoundingBox();
|
|
||||||
//material_.reflection.create();
|
|
||||||
//qDebug() << "init" << vbo.buffer_;
|
|
||||||
is_init = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RenderPass ObjectBase::pass() const {
|
|
||||||
RenderPass ret = rpSolid;
|
|
||||||
if (material_)
|
|
||||||
if (material_->hasTransparency())
|
|
||||||
ret = rpTransparent;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::setScene(Scene * v) {
|
|
||||||
scene_ = v;
|
|
||||||
foreach (ObjectBase * c, children_)
|
|
||||||
c->setScene(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::addChild(ObjectBase * o) {
|
|
||||||
if (o == this) return;
|
|
||||||
if (o->parent_)
|
|
||||||
o->parent_->children_.removeAll(o);
|
|
||||||
children_ << o;
|
|
||||||
o->parent_ = this;
|
|
||||||
o->setScene(scene_);
|
|
||||||
o->buildTransform();
|
|
||||||
/*if (scene_) {
|
|
||||||
ObjectBaseList cl = o->children(true);
|
|
||||||
cl << o;
|
|
||||||
//foreach (ObjectBase * i, cl) {
|
|
||||||
// emit view_->objectAdded(i);
|
|
||||||
//}
|
|
||||||
}*/
|
|
||||||
setSceneTreeChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::removeChild(ObjectBase * o) {
|
|
||||||
if (o == this) return;
|
|
||||||
children_.removeAll(o);
|
|
||||||
o->parent_ = nullptr;
|
|
||||||
o->buildTransform();
|
|
||||||
setSceneTreeChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::removeChild(int index) {
|
|
||||||
children_[index]->parent_ = nullptr;
|
|
||||||
children_[index]->buildTransform();
|
|
||||||
children_.removeAt(index);
|
|
||||||
setSceneTreeChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::clearChildren(bool deleteAll) {
|
|
||||||
foreach (ObjectBase * i, children_) {
|
|
||||||
i->scene_ = nullptr;
|
|
||||||
i->parent_ = nullptr;
|
|
||||||
i->clearChildren(deleteAll);
|
|
||||||
if (deleteAll) {
|
|
||||||
delete i;
|
|
||||||
} else {
|
|
||||||
i->buildTransform();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
children_.clear();
|
|
||||||
setSceneTreeChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ObjectBase * ObjectBase::child(int index) {
|
|
||||||
if (index < 0 || index >= children_.size()) return nullptr;
|
|
||||||
return children_[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ObjectBase * ObjectBase::child(const QString & name) {
|
|
||||||
foreach (ObjectBase * i, children_)
|
|
||||||
if (i->name_ == name) return i;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const ObjectBase * ObjectBase::child(int index) const {
|
|
||||||
if (index < 0 || index >= children_.size()) return nullptr;
|
|
||||||
return children_[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const ObjectBase * ObjectBase::child(const QString & name) const {
|
|
||||||
foreach (ObjectBase * i, children_)
|
|
||||||
if (i->name_ == name) return i;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ObjectBaseList ObjectBase::children(bool all_) {
|
|
||||||
if (!all_) return children_;
|
|
||||||
ObjectBaseList cl;
|
|
||||||
addChildren(cl, this);
|
|
||||||
return cl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ObjectBase::isVisible(bool check_parents) const {
|
|
||||||
if (!check_parents) return visible_;
|
|
||||||
if (!visible_) return false;
|
|
||||||
ObjectBase * p = parent_;
|
|
||||||
while (p) {
|
|
||||||
if (!p->visible_) return false;
|
|
||||||
p = p->parent_;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::setVisible(bool v) {
|
|
||||||
visible_ = v;
|
|
||||||
setSceneTreeChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::rotateZ(GLfloat a) {
|
|
||||||
raw_matrix = false;
|
|
||||||
trans.setRotationZ(trans.rotationZ() + a);
|
|
||||||
//angles_.setZ(angles_.z() + a);
|
|
||||||
//while (angles_.z() < -360.f) angles_.setZ(angles_.z() + 360.f);
|
|
||||||
//while (angles_.z() > 360.f) angles_.setZ(angles_.z() - 360.f);
|
|
||||||
buildTransform();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::setRotationZ(GLfloat a) {
|
|
||||||
raw_matrix = false;
|
|
||||||
trans.setRotationZ(a);
|
|
||||||
//angles_.setZ(a);
|
|
||||||
//while (angles_.z() < -360.f) angles_.setZ(angles_.z() + 360.f);
|
|
||||||
//while (angles_.z() > 360.f) angles_.setZ(angles_.z() - 360.f);
|
|
||||||
buildTransform();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::setTransform(const Transform & t) {
|
|
||||||
trans = t;
|
|
||||||
buildTransform();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::addChildren(ObjectBaseList & list, ObjectBase * where) {
|
|
||||||
foreach (ObjectBase * i, where->children_) {
|
|
||||||
list << i;
|
|
||||||
addChildren(list, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::calculateBoundingBox() {
|
|
||||||
bound = Box3D();
|
|
||||||
if (mesh_) {
|
|
||||||
bound = mesh_->boundingBox();
|
|
||||||
QVector<QVector3D> c = bound.corners(), tc;
|
|
||||||
foreach (QVector3D p, c)
|
|
||||||
tc << (itransform_ * QVector4D(p, 1)).toVector3D();
|
|
||||||
bound = Box3D(tc);
|
|
||||||
}
|
|
||||||
foreach (ObjectBase * i, children_) {
|
|
||||||
i->calculateBoundingBox();
|
|
||||||
bound |= i->boundingBox();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::updateTransform() {
|
|
||||||
buildTransform(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::setProperty(const QString & pn, const QVariant & v) {
|
|
||||||
meta[pn] = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QVariant ObjectBase::property(const QString & pn, bool * exists) const {
|
|
||||||
if (exists) *exists = meta.contains(pn);
|
|
||||||
return meta.value(pn);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ObjectBase::hasProperty(const QString & pn) const {
|
|
||||||
return meta.contains(pn);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::removeProperty(const QString & pn) {
|
|
||||||
meta.remove(pn);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::setMatrix(const QMatrix4x4 & t) {
|
|
||||||
//raw_matrix = true;
|
|
||||||
//mat_ = t;
|
|
||||||
//pos_ = mat_.column(3).toVector3D();
|
|
||||||
//mat_.setColumn(3, QVector4D(0., 0., 0., 1.));
|
|
||||||
raw_matrix = false;
|
|
||||||
trans.setMatrix(t);
|
|
||||||
buildTransform();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QMatrix4x4 ObjectBase::matrix() const {
|
|
||||||
return trans.matrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QVector3D ObjectBase::inParentSpace(const QVector3D & v) const {
|
|
||||||
if (!parent_) return v;
|
|
||||||
return (parent_->matrix() * QVector4D(v, 1)).toVector3D();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::transferTransformToChildren(bool only_scale) {
|
|
||||||
QMatrix4x4 m = trans.matrix();
|
|
||||||
if (only_scale) m = trans.matrixScale();
|
|
||||||
foreach (ObjectBase * i, children_)
|
|
||||||
i->trans.setMatrix(m * i->trans.matrix());
|
|
||||||
if (only_scale) resetScale();
|
|
||||||
else setMatrix(QMatrix4x4());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::cleanTree() {
|
|
||||||
for (int i = 0; i < children_.size(); ++i) {
|
|
||||||
ObjectBase * o = children_[i];
|
|
||||||
if (!o->hasChildren() && !o->mesh() && (o->type() == glMesh)) {
|
|
||||||
delete o;
|
|
||||||
--i;
|
|
||||||
}
|
|
||||||
o->cleanTree();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ObjectBase::isSelected(bool check_parents) const {
|
|
||||||
if (!check_parents) return selected_;
|
|
||||||
if (selected_) return true;
|
|
||||||
ObjectBase * p = parent_;
|
|
||||||
while (p) {
|
|
||||||
if (p->selected_) return true;
|
|
||||||
p = p->parent_;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::setSelected(bool yes) {
|
|
||||||
//qDebug() << "select" << name() << view_;
|
|
||||||
if (select_)
|
|
||||||
selected_ = yes;
|
|
||||||
if (!selected_)
|
|
||||||
selected_aim = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ObjectBase * ObjectBase::selectedParent() const {
|
|
||||||
ObjectBase * p = parent_;
|
|
||||||
while (p) {
|
|
||||||
if (p->selected_) return p;
|
|
||||||
p = p->parent_;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::setMaterial(Material * m, bool with_children) {
|
|
||||||
material_ = m;
|
|
||||||
if (with_children)
|
|
||||||
foreach (ObjectBase * i, children_) i->setMaterial(m, true);
|
|
||||||
setObjectsChanged();
|
|
||||||
if (scene_) scene_->mat_changed = scene_->tree_changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::setColor(QColor c, bool with_children) {
|
|
||||||
color_ = c;
|
|
||||||
if (with_children)
|
|
||||||
foreach (ObjectBase * i, children_) i->setColor(c, true);
|
|
||||||
setObjectsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::setMesh(Mesh * v) {
|
|
||||||
if (scene_)
|
|
||||||
v = scene_->attachMesh(v);
|
|
||||||
mesh_ = v;
|
|
||||||
setSceneTreeChanged();
|
|
||||||
setObjectsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::buildTransform(bool force) {
|
|
||||||
if (force) trans.setDirty();
|
|
||||||
itransform_.setToIdentity();
|
|
||||||
ObjectBase * p = parent_;
|
|
||||||
if (p)
|
|
||||||
itransform_ = p->itransform_;
|
|
||||||
//if (raw_matrix) {
|
|
||||||
// itransform_.translate(pos_);
|
|
||||||
// itransform_ *= mat_;
|
|
||||||
// //qDebug() << "raw_matrix" << itransform_;
|
|
||||||
//} else
|
|
||||||
localTransform(itransform_);
|
|
||||||
//qDebug() << name_ << itransform_;
|
|
||||||
foreach (ObjectBase * i, children_)
|
|
||||||
i->buildTransform(force);
|
|
||||||
setObjectsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::initInternal() {
|
|
||||||
init();
|
|
||||||
foreach (ObjectBase * i, children_) i->initInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::localTransform(QMatrix4x4 & m) {
|
|
||||||
m *= trans.matrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::setSceneTreeChanged() {
|
|
||||||
if (scene_) {
|
|
||||||
scene_->setTreeChanged();
|
|
||||||
scene_->setTreeStructChanged();
|
|
||||||
}
|
|
||||||
setObjectsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectBase::setObjectsChanged() {
|
|
||||||
int p = pass();
|
|
||||||
if (mesh_) {
|
|
||||||
mesh_->setObjectsChanged (p, true);
|
|
||||||
mesh_->setSelectionChanged(p, true);
|
|
||||||
if (prev_pass != p) {
|
|
||||||
mesh_->setObjectsChanged (prev_pass, true);
|
|
||||||
mesh_->setSelectionChanged(prev_pass, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prev_pass = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QMatrix4x4 ObjectBase::worldMatrix(QMatrix4x4 parent) const {
|
|
||||||
QMatrix4x4 mat;
|
|
||||||
//mat.translate(pos_);
|
|
||||||
//if (raw_matrix) {
|
|
||||||
// mat *= mat_;
|
|
||||||
//} else {
|
|
||||||
// if (angles_.z() != 0.f) mat.rotate(angles_.z(), 0., 0., 1.);
|
|
||||||
// if (angles_.y() != 0.f) mat.rotate(angles_.y(), 0., 1., 0.);
|
|
||||||
// if (angles_.x() != 0.f) mat.rotate(angles_.x(), 1., 0., 0.);
|
|
||||||
// mat.scale(scale_);
|
|
||||||
//}
|
|
||||||
mat = trans.matrix();
|
|
||||||
return parent * mat;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AimedObject::AimedObject() {
|
|
||||||
aim_dist = 1.;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QVector3D AimedObject::worldAim() const {
|
|
||||||
QVector3D ret = worldPos() + worldDirection() * aim_dist;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void AimedObject::setAim(const QVector3D & p) {
|
|
||||||
QVector3D dir = p - pos();
|
|
||||||
trans.setRotation(Transform::fromDirection(dir, trans.rotationY()));
|
|
||||||
aim_dist = dir.length();
|
|
||||||
buildTransform();
|
|
||||||
//if (!p.isNull())
|
|
||||||
//qDebug() << "setAim" << p << aim() << worldAim();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QVector3D AimedObject::direction() const {
|
|
||||||
return trans.direction();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void AimedObject::setDirection(const QVector3D & d) {
|
|
||||||
//double len = qMax(aim_.length(), 0.001f);
|
|
||||||
//aim_ = d.normalized() * len;
|
|
||||||
buildTransform();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void AimedObject::flyCloser(double s) {
|
|
||||||
double tl = 1. / (1. + s);
|
|
||||||
move(direction() * aim_dist * (1. - tl));
|
|
||||||
aim_dist *= tl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void AimedObject::flyFarer(double s) {
|
|
||||||
double tl = 1. * (1. + s);
|
|
||||||
move(direction() * aim_dist * (1. - tl));
|
|
||||||
aim_dist *= tl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void AimedObject::flyToDistance(double d) {
|
|
||||||
move(direction() * (aim_dist - d));
|
|
||||||
aim_dist = d;
|
|
||||||
//qDebug() << d << (aim() - pos()).length() << aim();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void AimedObject::moveForward(const float & x, bool withZ) {
|
|
||||||
QVector3D dv = itransform_.mapVector(QVector3D(0, 0, -x));
|
|
||||||
if (!withZ) dv[2] = 0.;
|
|
||||||
move(dv);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void AimedObject::moveLeft(const float & x, bool withZ) {
|
|
||||||
QVector3D dv = itransform_.mapVector(QVector3D(-x, 0, 0));
|
|
||||||
if (!withZ) dv[2] = 0.;
|
|
||||||
move(dv);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void AimedObject::moveUp(const float & x, bool onlyZ) {
|
|
||||||
QVector3D dv = itransform_.mapVector(QVector3D(0, x, 0));
|
|
||||||
if (onlyZ) dv[0] = dv[1] = 0.;
|
|
||||||
move(dv);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void AimedObject::orbitZ(const float & a) {
|
|
||||||
QVector3D pa = aim();
|
|
||||||
rotateZ(-a);
|
|
||||||
move(pa - aim());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void AimedObject::orbitXY(const float & a) {
|
|
||||||
QVector3D pa = aim();
|
|
||||||
rotateX(-a);
|
|
||||||
move(pa - aim());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void AimedObject::transformChanged() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Light::Light(): AimedObject(), shadow_map(0, true, GL_R16F) {
|
|
||||||
type_ = glLight;
|
|
||||||
light_type = Omni;
|
|
||||||
intensity = 1.;
|
|
||||||
angle_start = angle_end = 180.;
|
|
||||||
decay_linear = decay_quadratic = decay_start = 0.;
|
|
||||||
decay_const = decay_end = 1.;
|
|
||||||
setDirection(0, 0, -1.);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Light::Light(const QVector3D & p, const QColor & c, float i): AimedObject(), shadow_map(0, true, GL_R16F) {
|
|
||||||
type_ = glLight;
|
|
||||||
light_type = Omni;
|
|
||||||
intensity = i;
|
|
||||||
color_ = c;
|
|
||||||
angle_start = angle_end = 180.;
|
|
||||||
decay_linear = decay_quadratic = decay_start = 0.;
|
|
||||||
decay_const = decay_end = 1.;
|
|
||||||
setPos(p);
|
|
||||||
setDirection(0, 0, -1.);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ObjectBase * Light::clone(bool withChildren) {
|
|
||||||
Light * o = new Light(*this);
|
|
||||||
//GLObjectBase::clone(withChildren);
|
|
||||||
o->is_init = false;
|
|
||||||
o->name_ = name_;// + "_copy";
|
|
||||||
o->scene_ = nullptr;
|
|
||||||
o->children_.clear();
|
|
||||||
if (withChildren) {
|
|
||||||
for (int i = 0; i < children_.size(); ++i)
|
|
||||||
o->addChild(children_[i]->clone(withChildren));
|
|
||||||
}
|
|
||||||
o->color_ = color_;
|
|
||||||
o->light_type = light_type;
|
|
||||||
o->trans = trans;
|
|
||||||
o->aim_dist = aim_dist;
|
|
||||||
o->angle_start = angle_start;
|
|
||||||
o->angle_end = angle_end;
|
|
||||||
o->intensity = intensity;
|
|
||||||
o->decay_const = decay_const;
|
|
||||||
o->decay_linear = decay_linear;
|
|
||||||
o->decay_quadratic = decay_quadratic;
|
|
||||||
o->meta = meta;
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Light::apply() {
|
|
||||||
if (scene_) scene_->setLightsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QDataStream & operator <<(QDataStream & s, const ObjectBase * p) {
|
|
||||||
ChunkStream cs;
|
|
||||||
//qDebug() << "place" << p->name() << "...";
|
|
||||||
cs.add(1, int(p->type_)).add(2, p->accept_light).add(3, p->accept_fog).add(4, p->visible_)
|
|
||||||
.add(5, p->cast_shadow).add(6, p->rec_shadow).add(7, p->raw_matrix).add(8, p->line_width)
|
|
||||||
.add(9, int(p->render_mode)).add(14, p->mat_).add(16, p->children_.size())
|
|
||||||
.add(17, p->name_).add(18, p->meta).add(19, p->color_).add(20, p->trans);
|
|
||||||
//qDebug() << "place self done";
|
|
||||||
if (p->type_ == ObjectBase::glLight) {
|
|
||||||
//qDebug() << "place light ...";
|
|
||||||
const Light * l = (const Light*)p;
|
|
||||||
cs.add(101, l->angle_start).add(102, l->angle_end).add(103, l->intensity)
|
|
||||||
.add(104, l->decay_const).add(105, l->decay_linear).add(106, l->decay_quadratic)
|
|
||||||
.add(107, l->decay_start).add(108, l->decay_end).add(109, int(l->light_type))
|
|
||||||
.add(111, l->distance());
|
|
||||||
}
|
|
||||||
if (p->type_ == ObjectBase::glCamera) {
|
|
||||||
//qDebug() << "place camera ...";
|
|
||||||
const Camera * c = (const Camera*)p;
|
|
||||||
cs.add(200, c->aim()).add(201, c->fov_).add(202, c->depth_start)
|
|
||||||
.add(206, c->mirror_x).add(207, c->mirror_y).add(208, c->distance())
|
|
||||||
.add(209, c->roll_);
|
|
||||||
}
|
|
||||||
//qDebug() << "place" << p->name() << cs.data().size() << s.device()->size();
|
|
||||||
s << cs.data();
|
|
||||||
foreach (const ObjectBase * c, p->children_)
|
|
||||||
s << c;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
QDataStream & operator >>(QDataStream & s, ObjectBase *& p) {
|
|
||||||
ChunkStream cs(s);
|
|
||||||
p = nullptr;
|
|
||||||
int ccnt = 0;
|
|
||||||
Light * l = nullptr;
|
|
||||||
Camera * c = nullptr;
|
|
||||||
//qDebug() << "read obj ...";
|
|
||||||
while (!cs.atEnd()) {
|
|
||||||
switch (cs.read()) {
|
|
||||||
case 1: {
|
|
||||||
ObjectBase::Type type = (ObjectBase::Type)cs.getData<int>();
|
|
||||||
switch (type) {
|
|
||||||
case ObjectBase::glMesh: p = new ObjectBase(); break;
|
|
||||||
case ObjectBase::glLight: p = new Light(); l = (Light*)p; break;
|
|
||||||
case ObjectBase::glCamera: p = new Camera(); c = (Camera*)p; break;
|
|
||||||
default : break;
|
|
||||||
}
|
|
||||||
if (p) p->type_ = type;
|
|
||||||
} break;
|
|
||||||
case 2: if (p) p->accept_light = cs.getData<bool>(); break;
|
|
||||||
case 3: if (p) p->accept_fog = cs.getData<bool>(); break;
|
|
||||||
case 4: if (p) p->visible_ = cs.getData<bool>(); break;
|
|
||||||
case 5: if (p) p->cast_shadow = cs.getData<bool>(); break;
|
|
||||||
case 6: if (p) p->rec_shadow = cs.getData<bool>(); break;
|
|
||||||
case 7: if (p) p->raw_matrix = cs.getData<bool>(); break;
|
|
||||||
case 8: if (p) p->line_width = cs.getData<float>(); break;
|
|
||||||
case 9: if (p) p->render_mode = (ObjectBase::RenderMode)cs.getData<int>(); break;
|
|
||||||
case 14: if (p) p->mat_ = cs.getData<QMatrix4x4>(); break;
|
|
||||||
case 16: if (p) ccnt = cs.getData<int>(); break;
|
|
||||||
case 17: if (p) p->name_ = cs.getData<QString>(); break;
|
|
||||||
case 18: if (p) p->meta = cs.getData<QVariantMap>(); break;
|
|
||||||
case 19: if (p) p->color_ = cs.getData<QColor>(); break;
|
|
||||||
case 20: if (p) p->trans = cs.getData<Transform>(); break;
|
|
||||||
case 100: if (l) l->setAim(cs.getData<QVector3D>()); break;
|
|
||||||
case 101: if (l) l->angle_start = cs.getData<GLfloat>(); break;
|
|
||||||
case 102: if (l) l->angle_end = cs.getData<GLfloat>(); break;
|
|
||||||
case 103: if (l) l->intensity = cs.getData<GLfloat>(); break;
|
|
||||||
case 104: if (l) l->decay_const = cs.getData<GLfloat>(); break;
|
|
||||||
case 105: if (l) l->decay_linear = cs.getData<GLfloat>(); break;
|
|
||||||
case 106: if (l) l->decay_quadratic = cs.getData<GLfloat>(); break;
|
|
||||||
case 107: if (l) l->decay_start = cs.getData<GLfloat>(); break;
|
|
||||||
case 108: if (l) l->decay_end = cs.getData<GLfloat>(); break;
|
|
||||||
case 109: if (l) l->light_type = (Light::Type)cs.getData<int>(); break;
|
|
||||||
case 111: if (l) l->setDistance(cs.getData<double>()); break;
|
|
||||||
case 200: if (c) c->setAim(cs.getData<QVector3D>()); break;
|
|
||||||
case 201: if (c) c->setFOV(cs.getData<GLfloat>()); break;
|
|
||||||
case 202: if (c) c->setDepthStart(cs.getData<GLfloat>()); break;
|
|
||||||
case 206: if (c) c->mirror_x = cs.getData<bool>(); break;
|
|
||||||
case 207: if (c) c->mirror_y = cs.getData<bool>(); break;
|
|
||||||
case 208: if (c) c->setDistance(cs.getData<double>()); break;
|
|
||||||
case 209: if (c) c->roll_ = cs.getData<GLfloat>(); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//qDebug() << p->name() << ccnt;
|
|
||||||
for (int i = 0; i < ccnt; ++i) {
|
|
||||||
ObjectBase * c = nullptr;
|
|
||||||
s >> c;
|
|
||||||
if (!c) continue;
|
|
||||||
c->parent_ = p;
|
|
||||||
p->children_ << c;
|
|
||||||
}
|
|
||||||
p->buildTransform();
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
303
globject.h
303
globject.h
@@ -1,303 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL ObjectBase & Light
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLOBJECT_H
|
|
||||||
#define GLOBJECT_H
|
|
||||||
|
|
||||||
#include "glframebuffer.h"
|
|
||||||
#include "glmaterial.h"
|
|
||||||
#include "gltypes.h"
|
|
||||||
#include "gltransform.h"
|
|
||||||
|
|
||||||
|
|
||||||
class ObjectBase
|
|
||||||
{
|
|
||||||
friend class Scene;
|
|
||||||
friend class RendererSelection;
|
|
||||||
friend QDataStream & operator <<(QDataStream & s, const ObjectBase * p);
|
|
||||||
friend QDataStream & operator >>(QDataStream & s, ObjectBase *& p);
|
|
||||||
friend QDataStream & operator >>(QDataStream & s, Scene *& p);
|
|
||||||
public:
|
|
||||||
enum Type {glMesh, glLight, glCamera, glParticlesSystem};
|
|
||||||
enum RenderMode {View = 0, Point = GL_POINT, Line = GL_LINE, Fill = GL_FILL};
|
|
||||||
|
|
||||||
explicit ObjectBase(Mesh * geom = 0, Material * mat = 0);
|
|
||||||
virtual ~ObjectBase();
|
|
||||||
|
|
||||||
virtual ObjectBase * clone(bool withChildren = true);
|
|
||||||
void destroy();
|
|
||||||
|
|
||||||
QString name() const {return name_;}
|
|
||||||
void setName(const QString & name) {name_ = name;}
|
|
||||||
virtual void init();
|
|
||||||
virtual void update() {}
|
|
||||||
bool isInit() const {return is_init;}
|
|
||||||
Type type() const {return type_;}
|
|
||||||
RenderPass pass() const;
|
|
||||||
uint id() const {return id_;}
|
|
||||||
|
|
||||||
RenderMode renderMode() const {return render_mode;}
|
|
||||||
void setRenderMode(RenderMode mode) {render_mode = mode;}
|
|
||||||
|
|
||||||
float lineWidth() const {return line_width;}
|
|
||||||
void setLineWidth(const float & width) {line_width = width;}
|
|
||||||
|
|
||||||
ObjectBase * parent() {return parent_;}
|
|
||||||
void setParent(ObjectBase * o) {parent_ = o;}
|
|
||||||
bool hasParent() const {return parent_ != nullptr;}
|
|
||||||
bool hasChildren() const {return !children_.isEmpty();}
|
|
||||||
void setScene(Scene * v);
|
|
||||||
|
|
||||||
void addChild(ObjectBase * o);
|
|
||||||
void removeChild(ObjectBase * o);
|
|
||||||
void removeChild(int index);
|
|
||||||
void clearChildren(bool deleteAll = false);
|
|
||||||
int childCount() const {return children_.size();}
|
|
||||||
ObjectBase * child(int index);
|
|
||||||
ObjectBase * child(const QString & name);
|
|
||||||
const ObjectBase * child(int index) const;
|
|
||||||
const ObjectBase * child(const QString & name) const;
|
|
||||||
ObjectBaseList children(bool all_ = false);
|
|
||||||
|
|
||||||
bool isVisible(bool check_parents = false) const;
|
|
||||||
bool isHidden(bool check_parents = false) const {return !isVisible(check_parents);}
|
|
||||||
void setVisible(bool v);
|
|
||||||
void setHidden(bool v) {setVisible(!v);}
|
|
||||||
void show() {setVisible(true);}
|
|
||||||
void hide() {setVisible(false);}
|
|
||||||
|
|
||||||
bool isReceiveShadows() const {return rec_shadow;}
|
|
||||||
bool isCastShadows() const {return cast_shadow;}
|
|
||||||
void setReceiveShadows(bool on) {rec_shadow = on;}
|
|
||||||
void setCastShadows(bool on) {cast_shadow = on;}
|
|
||||||
|
|
||||||
void move(const QVector3D & dv) {trans.setTranslation(pos() + dv); buildTransform();}
|
|
||||||
void moveTo(const QVector3D & dv) {trans.setTranslation(dv); buildTransform();}
|
|
||||||
void move(GLfloat dx, GLfloat dy, GLfloat dz = 0.) {move(QVector3D(dx, dy, dz)); buildTransform();}
|
|
||||||
void moveTo(GLfloat dx, GLfloat dy, GLfloat dz = 0.) {moveTo(QVector3D(dx, dy, dz)); buildTransform();}
|
|
||||||
void moveX(GLfloat o) {trans.setTranslationX(posX() + o); buildTransform();}
|
|
||||||
void moveY(GLfloat o) {trans.setTranslationY(posY() + o); buildTransform();}
|
|
||||||
void moveZ(GLfloat o) {trans.setTranslationZ(posZ() + o); buildTransform();}
|
|
||||||
void setPosX(GLfloat o) {trans.setTranslationX(o); buildTransform();}
|
|
||||||
void setPosY(GLfloat o) {trans.setTranslationY(o); buildTransform();}
|
|
||||||
void setPosZ(GLfloat o) {trans.setTranslationZ(o); buildTransform();}
|
|
||||||
void setPos(GLfloat x, GLfloat y, GLfloat z) {trans.setTranslation(QVector3D(x, y, z)); buildTransform();}
|
|
||||||
void setPos(const QVector3D & p) {trans.setTranslation(p); buildTransform();}
|
|
||||||
void resetPos() {trans.setTranslation(QVector3D()); buildTransform();}
|
|
||||||
|
|
||||||
QVector3D pos() const {return trans.translation();}
|
|
||||||
float posX() const {return trans.translation().x();}
|
|
||||||
float posY() const {return trans.translation().y();}
|
|
||||||
float posZ() const {return trans.translation().z();}
|
|
||||||
QVector3D worldPos() const {return (itransform_ * QVector4D(0, 0, 0, 1.)).toVector3D();}
|
|
||||||
QMatrix4x4 worldTransform() const {return itransform_;}
|
|
||||||
|
|
||||||
QVector3D rotation() const {return trans.rotation();}
|
|
||||||
float rotationX() const {return rotation().x();}
|
|
||||||
float rotationY() const {return rotation().y();}
|
|
||||||
float rotationZ() const {return rotation().z();}
|
|
||||||
void rotateX(GLfloat a) {raw_matrix = false; trans.setRotationX(trans.rotationX() + a); buildTransform();}
|
|
||||||
void rotateY(GLfloat a) {raw_matrix = false; trans.setRotationY(trans.rotationY() + a); buildTransform();}
|
|
||||||
void rotateZ(GLfloat a);
|
|
||||||
void setRotationX(GLfloat a) {raw_matrix = false; trans.setRotationX(a); buildTransform();}
|
|
||||||
void setRotationY(GLfloat a) {raw_matrix = false; trans.setRotationY(a); buildTransform();}
|
|
||||||
void setRotationZ(GLfloat a);
|
|
||||||
void setRotation(const QVector3D & a) {raw_matrix = false; trans.setRotation(a); buildTransform();}
|
|
||||||
void resetRotation() {raw_matrix = false; trans.setRotation(QVector3D()); buildTransform();}
|
|
||||||
|
|
||||||
QVector3D scale() {return trans.scale3D();}
|
|
||||||
float scaleX() {return trans.scale3D().x();}
|
|
||||||
float scaleY() {return trans.scale3D().y();}
|
|
||||||
float scaleZ() {return trans.scale3D().z();}
|
|
||||||
void scale(const QVector3D & sv) {raw_matrix = false; trans.setScale(trans.scale3D() * sv); buildTransform();}
|
|
||||||
void scale(GLfloat sx, GLfloat sy, GLfloat sz) {raw_matrix = false; scale(QVector3D(sx, sy, sz)); buildTransform();}
|
|
||||||
void scale(GLfloat sx, GLfloat sy) {raw_matrix = false; scale(QVector3D(sx, sy, sy)); buildTransform();}
|
|
||||||
void scale(GLfloat sx) {raw_matrix = false; scale(QVector3D(sx, sx, sx)); buildTransform();}
|
|
||||||
void scaleX(GLfloat a) {raw_matrix = false; trans.setScaleX(trans.scale3D().x() + a); buildTransform();}
|
|
||||||
void scaleY(GLfloat a) {raw_matrix = false; trans.setScaleY(trans.scale3D().y() + a); buildTransform();}
|
|
||||||
void scaleZ(GLfloat a) {raw_matrix = false; trans.setScaleZ(trans.scale3D().z() + a); buildTransform();}
|
|
||||||
void setScale(const QVector3D & a) {raw_matrix = false; trans.setScale(a); buildTransform();}
|
|
||||||
void setScale(GLfloat a) {raw_matrix = false; trans.setScale(a); buildTransform();}
|
|
||||||
void setScaleX(GLfloat a) {raw_matrix = false; trans.setScaleX(a); buildTransform();}
|
|
||||||
void setScaleY(GLfloat a) {raw_matrix = false; trans.setScaleY(a); buildTransform();}
|
|
||||||
void setScaleZ(GLfloat a) {raw_matrix = false; trans.setScaleZ(a); buildTransform();}
|
|
||||||
void resetScale() {raw_matrix = false; trans.setScale(1.f); buildTransform();}
|
|
||||||
|
|
||||||
Transform transform() {return trans;}
|
|
||||||
void setTransform(const Transform & t);
|
|
||||||
void setMatrix(const QMatrix4x4 & t);
|
|
||||||
QMatrix4x4 matrix() const;
|
|
||||||
bool isRawMatrix() {return raw_matrix;}
|
|
||||||
QVector3D inParentSpace(const QVector3D & v) const;
|
|
||||||
void transferTransformToChildren(bool only_scale = false);
|
|
||||||
void cleanTree();
|
|
||||||
|
|
||||||
bool isAcceptLight() const {return accept_light;}
|
|
||||||
void setAcceptLight(bool yes) {accept_light = yes;}
|
|
||||||
|
|
||||||
bool isAcceptFog() const {return accept_fog;}
|
|
||||||
void setAcceptFog(bool yes) {accept_fog = yes;}
|
|
||||||
|
|
||||||
bool isSelected(bool check_parents = false) const;
|
|
||||||
void setSelected(bool yes);
|
|
||||||
void select() {setSelected(true);}
|
|
||||||
void deselect() {setSelected(false);}
|
|
||||||
ObjectBase * selectedParent() const;
|
|
||||||
void setAimSelected(bool yes) {selected_aim = yes;}
|
|
||||||
bool isAimSelected() const {return selected_aim;}
|
|
||||||
|
|
||||||
bool isSelectable() const {return select_;}
|
|
||||||
void setSelectable(bool yes) {select_ = yes;}
|
|
||||||
|
|
||||||
GLenum srcAlpha() const {return blend_src;}
|
|
||||||
GLenum destAlpha() const {return blend_dest;}
|
|
||||||
void setSrcAlpha(GLenum mode) {blend_src = mode;}
|
|
||||||
void setDestAlpha(GLenum mode) {blend_dest = mode;}
|
|
||||||
|
|
||||||
void setMaterial(Material * m, bool with_children = false);
|
|
||||||
Material * material() {return material_;}
|
|
||||||
|
|
||||||
void setColor(QColor c, bool with_children = false);
|
|
||||||
QColor color() {return color_;}
|
|
||||||
|
|
||||||
const Box3D & boundingBox() const {return bound;}
|
|
||||||
void setMesh(Mesh * v);
|
|
||||||
Mesh * mesh() {return mesh_;}
|
|
||||||
|
|
||||||
void calculateBoundingBox();
|
|
||||||
void updateTransform();
|
|
||||||
|
|
||||||
void setProperty(const QString & pn, const QVariant & v);
|
|
||||||
QVariant property(const QString & pn, bool * exists = 0) const;
|
|
||||||
bool hasProperty(const QString & pn) const;
|
|
||||||
void removeProperty(const QString & pn);
|
|
||||||
|
|
||||||
QVector3D pos_h;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void transformChanged() {}
|
|
||||||
void addChildren(ObjectBaseList & list, ObjectBase * where);
|
|
||||||
void buildTransform(bool force = false);
|
|
||||||
void initInternal();
|
|
||||||
void setSceneTreeChanged();
|
|
||||||
void setObjectsChanged();
|
|
||||||
void localTransform(QMatrix4x4 & m);
|
|
||||||
QMatrix4x4 worldMatrix(QMatrix4x4 parent) const;
|
|
||||||
|
|
||||||
int prev_pass; // Pass
|
|
||||||
bool is_init, accept_light, accept_fog, visible_, cast_shadow, rec_shadow, select_, selected_, raw_matrix;
|
|
||||||
bool is_root, selected_aim;
|
|
||||||
float line_width;
|
|
||||||
QColor color_;
|
|
||||||
uint id_;
|
|
||||||
Type type_;
|
|
||||||
RenderMode render_mode;
|
|
||||||
Box3D bound;
|
|
||||||
Transform trans;
|
|
||||||
ObjectBaseList children_;
|
|
||||||
QMatrix4x4 itransform_, mat_;
|
|
||||||
QString name_;
|
|
||||||
GLenum blend_src, blend_dest;
|
|
||||||
ObjectBase * parent_;
|
|
||||||
Scene * scene_;
|
|
||||||
Material * material_;
|
|
||||||
Mesh * mesh_;
|
|
||||||
QVariantMap meta;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bool operator <(const ObjectBase & f, const ObjectBase & s) {return f.pos_h.z() < s.pos_h.z();}
|
|
||||||
|
|
||||||
|
|
||||||
class AimedObject: public ObjectBase {
|
|
||||||
friend class QGLView;
|
|
||||||
friend class GLRendererBase;
|
|
||||||
friend class Light;
|
|
||||||
friend class Camera;
|
|
||||||
public:
|
|
||||||
AimedObject();
|
|
||||||
~AimedObject() {}
|
|
||||||
QVector3D aim() const {return pos() + (direction() * aim_dist);}
|
|
||||||
QVector3D worldAim() const;
|
|
||||||
void setAim(const QVector3D & p);
|
|
||||||
QVector3D direction() const;
|
|
||||||
QVector3D worldDirection() const {return (itransform_ * QVector4D(QVector3D(0,0,-1), 0.)).toVector3D().normalized();}
|
|
||||||
void setDirection(const QVector3D & d);
|
|
||||||
void setDirection(double x, double y, double z) {setDirection(QVector3D(x, y, z));}
|
|
||||||
|
|
||||||
double distance() const {return aim_dist;}
|
|
||||||
void setDistance(double d) {aim_dist = d;}
|
|
||||||
void flyCloser(double s);
|
|
||||||
void flyFarer(double s);
|
|
||||||
void flyToDistance(double d);
|
|
||||||
|
|
||||||
void moveForward(const float & x, bool withZ = true);
|
|
||||||
void moveBackward(const float & x, bool withZ = true) {moveForward(-x, withZ);}
|
|
||||||
void moveLeft(const float & x, bool withZ = true);
|
|
||||||
void moveRight(const float & x, bool withZ = true) {moveLeft(-x, withZ);}
|
|
||||||
void moveUp(const float & x, bool onlyZ = false);
|
|
||||||
void moveDown(const float & x, bool onlyZ = false) {moveUp(-x, onlyZ);}
|
|
||||||
|
|
||||||
void rotateRoll(const float & a) {rotateY(a);}
|
|
||||||
void orbitZ(const float & a);
|
|
||||||
void orbitXY(const float & a);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void transformChanged() override;
|
|
||||||
double aim_dist;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Light: public AimedObject {
|
|
||||||
friend class QGLView;
|
|
||||||
friend class RendererBase;
|
|
||||||
public:
|
|
||||||
enum Type {Omni, Cone, Directional};
|
|
||||||
|
|
||||||
Light();
|
|
||||||
Light(const QVector3D & p, const QColor & c = Qt::white, float i = 1.);
|
|
||||||
virtual ObjectBase * clone(bool withChildren = true);
|
|
||||||
virtual void init() {shadow_map.resize(512, 512); is_init = true;}
|
|
||||||
void apply();
|
|
||||||
|
|
||||||
float angle_start;
|
|
||||||
float angle_end;
|
|
||||||
float intensity;
|
|
||||||
float decay_const;
|
|
||||||
float decay_linear;
|
|
||||||
float decay_quadratic;
|
|
||||||
float decay_start;
|
|
||||||
float decay_end;
|
|
||||||
Type light_type;
|
|
||||||
Framebuffer shadow_map;
|
|
||||||
QMatrix4x4 shadow_matrix;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline T globject_cast(ObjectBase * object) {return reinterpret_cast<T>(object);}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline T globject_cast(const ObjectBase * object) {return reinterpret_cast<T>(object);}
|
|
||||||
|
|
||||||
|
|
||||||
QDataStream & operator <<(QDataStream & s, const ObjectBase * p);
|
|
||||||
QDataStream & operator >>(QDataStream & s, ObjectBase *& p);
|
|
||||||
|
|
||||||
inline ObjectBaseList lights2objectList(const QList<Light*> & v) {ObjectBaseList ret; foreach (Light*i, v) ret << (ObjectBase*)i; return ret;}
|
|
||||||
inline ObjectBaseList cameras2objectList(const QList<Camera*> & v) {ObjectBaseList ret; foreach (Camera*i, v) ret << (ObjectBase*)i; return ret;}
|
|
||||||
|
|
||||||
#endif // GLOBJECT_H
|
|
||||||
@@ -1,201 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL TextureManager
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "gltexture_manager.h"
|
|
||||||
#include "gltypes.h"
|
|
||||||
|
|
||||||
QStringList TextureManager::search_pathes(".");
|
|
||||||
|
|
||||||
|
|
||||||
QVector3D colorVector(QRgb c) {
|
|
||||||
return QVector3D(((uchar*)(&c))[0] / 255.f, ((uchar*)(&c))[1] / 255.f, ((uchar*)(&c))[2] / 255.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QString TextureManager::findFile(const QString & path) {
|
|
||||||
return ::findFile(path, search_pathes);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GLuint TextureManager::loadTexture(const QString & path, bool ownership, bool bump) {
|
|
||||||
QString p = findFile(path);
|
|
||||||
if (p.isEmpty()) return 0;
|
|
||||||
int tid = textureID(p, bump);
|
|
||||||
if (tid > 0) {
|
|
||||||
//qDebug() << "[TextureManager] Found" << path << "as" << tid;
|
|
||||||
return tid;
|
|
||||||
}
|
|
||||||
QImage image(p);
|
|
||||||
if (bump) convertToNormal(image);
|
|
||||||
//qDebug() << p << image.width() << image.height() << image.format() << bump;
|
|
||||||
GLuint tid_ = tid;
|
|
||||||
createGLTexture(f, tid_, image);
|
|
||||||
tid = tid_;
|
|
||||||
if (tid == 0) {
|
|
||||||
qDebug() << "[TextureManager] Can`t load" << p;
|
|
||||||
return tid;
|
|
||||||
}
|
|
||||||
qDebug() << "[TextureManager] Loaded" << p << "as" << tid;
|
|
||||||
if (ownership) {
|
|
||||||
tex_ids[bump ? 1 : 0].insert(p, tid);
|
|
||||||
tex_im [bump ? 1 : 0].insert(p, image);
|
|
||||||
}
|
|
||||||
return tid;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GLuint TextureManager::loadTexture(const QImage & im, bool ownership, bool bump) {
|
|
||||||
if (im.isNull()) return 0;
|
|
||||||
QImage image(im);
|
|
||||||
if (bump) convertToNormal(image);
|
|
||||||
GLuint tid = 0;
|
|
||||||
createGLTexture(f, tid, im);
|
|
||||||
if (tid == 0) {
|
|
||||||
qDebug() << "[TextureManager] Can`t load image";
|
|
||||||
return tid;
|
|
||||||
}
|
|
||||||
//qDebug() << "[TextureManager] Loaded image as" << tid;
|
|
||||||
return tid;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QImage TextureManager::loadTextureImage(const QString & path, bool bump) {
|
|
||||||
QString p = findFile(path);
|
|
||||||
if (p.isEmpty()) return QImage();
|
|
||||||
QImage ret = tex_im[bump ? 1 : 0].value(p);
|
|
||||||
if (!ret.isNull()) return ret;
|
|
||||||
ret = QImage(p);
|
|
||||||
if (bump) convertToNormal(ret);
|
|
||||||
tex_im[bump ? 1 : 0].insert(p, ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TextureManager::reloadTexture(GLuint tid, const QString & path) {
|
|
||||||
QString p = findFile(path);
|
|
||||||
if (p.isEmpty() || (tid == 0)) return;
|
|
||||||
QImage image(p);
|
|
||||||
createGLTexture(f, tid, image);
|
|
||||||
if (tid == 0) {
|
|
||||||
qDebug() << "[TextureManager] Can`t load" << p;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
qDebug() << "[TextureManager] Reloaded" << p << "as" << tid;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TextureManager::reloadTexture(GLuint tid, const QImage & im) {
|
|
||||||
if (im.isNull() || (tid == 0)) return;
|
|
||||||
QImage image(im);
|
|
||||||
createGLTexture(f, tid, image);
|
|
||||||
qDebug() << "[TextureManager] Reloaded" << tid;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TextureManager::convertToNormal(QImage & im) {
|
|
||||||
if (im.isNull()) return;
|
|
||||||
QImage sim = im.convertToFormat(QImage::Format_ARGB32);
|
|
||||||
float sum[3] = {0., 0., 0.};
|
|
||||||
llong a = 0;
|
|
||||||
const uchar * sd = sim.constBits();
|
|
||||||
for (int i = 0; i < sim.height(); i++) {
|
|
||||||
for (int j = 0; j < sim.width(); j++) {
|
|
||||||
sum[2] += sd[a] / 255.f - 0.5f; ++a;
|
|
||||||
sum[1] += sd[a] / 255.f - 0.5f; ++a;
|
|
||||||
sum[0] += sd[a] / 255.f - 0.5f; ++a;
|
|
||||||
++a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
float wh = sim.width() * sim.height();
|
|
||||||
sum[0] /= wh;
|
|
||||||
sum[1] /= wh;
|
|
||||||
sum[2] /= wh;
|
|
||||||
//qDebug() << sum[0] << sum[1] << sum[2];
|
|
||||||
if ((qAbs(sum[0]) <= 0.05f) && (qAbs(sum[1]) <= 0.05f) && (sum[2] >= 0.25f)) /// already normal
|
|
||||||
return;
|
|
||||||
//qDebug() << "convert to normal";
|
|
||||||
QImage dim = QImage(sim.width(), sim.height(), QImage::Format_ARGB32);
|
|
||||||
int tx, ty, w = sim.width(), h = sim.height();
|
|
||||||
a = 0;
|
|
||||||
uchar * dd = dim.bits();
|
|
||||||
for (int i = 0; i < sim.height(); i++) {
|
|
||||||
for (int j = 0; j < sim.width(); j++) {
|
|
||||||
tx = j - 1;
|
|
||||||
tx = tx < 0 ? w + tx : tx % w;
|
|
||||||
ty = i - 1;
|
|
||||||
ty = ty < 0 ? h + ty : ty % h;
|
|
||||||
QVector3D p[3], res;
|
|
||||||
p[0] = colorVector(sim.pixel(j, i));
|
|
||||||
p[1] = colorVector(sim.pixel(j, ty));
|
|
||||||
p[2] = colorVector(sim.pixel(tx, i));
|
|
||||||
res.setY(piClamp(0.5f + (p[0].length() - p[1].length()) / 2.f, 0.f, 1.f));
|
|
||||||
res.setX(piClamp(0.5f - (p[0].length() - p[2].length()) / 2.f, 0.f, 1.f));
|
|
||||||
tx = (j + 1) % w;
|
|
||||||
ty = (i + 1) % h;
|
|
||||||
p[1] = colorVector(sim.pixel(j, ty));
|
|
||||||
p[2] = colorVector(sim.pixel(tx, i));
|
|
||||||
res.setY(piClamp(0.5f + (p[0].length() - p[1].length()) / 2.f, 0.f, 1.f));
|
|
||||||
res.setX(piClamp(0.5f - (p[0].length() - p[2].length()) / 2.f, 0.f, 1.f));
|
|
||||||
res.setZ(1.f);
|
|
||||||
dd[a] = res.z() * 255; ++a;
|
|
||||||
dd[a] = res.y() * 255; ++a;
|
|
||||||
dd[a] = res.x() * 255; ++a;
|
|
||||||
dd[a] = 255; ++a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
im = dim;
|
|
||||||
//im.save("_normal.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool TextureManager::loadTextures() {
|
|
||||||
QFileInfoList fil;
|
|
||||||
foreach (const QString & i, tex_pathes)
|
|
||||||
loadTexture(i, true);
|
|
||||||
tex_pathes.clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TextureManager::deleteTextures() {
|
|
||||||
for (int i = 0; i < 2; ++i) {
|
|
||||||
QList<GLuint> texs = tex_ids[i].values();
|
|
||||||
qDebug() << "[TextureManager] Delete" << texs.size() << "textures";
|
|
||||||
if (!texs.isEmpty()) f->glDeleteTextures(texs.size(), &texs[0]);
|
|
||||||
tex_ids[i].clear();
|
|
||||||
tex_im [i].clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TextureManager::deleteTexture(const QString & name) {
|
|
||||||
for (int i = 0; i < 2; ++i) {
|
|
||||||
if (tex_ids[i].contains(name)) {
|
|
||||||
GLuint id = tex_ids[i][name];
|
|
||||||
f->glDeleteTextures(1, &id);
|
|
||||||
tex_ids[i].remove(name);
|
|
||||||
tex_im [i].remove(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TextureManager::clearImageCache() {
|
|
||||||
tex_im[0].clear();
|
|
||||||
tex_im[1].clear();
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL TextureManager
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLTEXTUREMANAGER_H
|
|
||||||
#define GLTEXTUREMANAGER_H
|
|
||||||
|
|
||||||
#include <QOpenGLExtraFunctions>
|
|
||||||
#include <QDir>
|
|
||||||
#include <QMap>
|
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QImage>
|
|
||||||
|
|
||||||
|
|
||||||
class TextureManager {
|
|
||||||
public:
|
|
||||||
TextureManager(QOpenGLExtraFunctions * f_): f(f_) {}
|
|
||||||
virtual ~TextureManager() {}
|
|
||||||
|
|
||||||
static void addSearchPath(const QString & path) {if (!search_pathes.contains(path)) search_pathes << path;}
|
|
||||||
static void clearSearchPathes() {search_pathes.clear();}
|
|
||||||
static QStringList searchPathes() {return search_pathes;}
|
|
||||||
static QString findFile(const QString & path);
|
|
||||||
GLuint loadTexture(const QString & path, bool ownership = true, bool bump = false);
|
|
||||||
GLuint loadTexture(const QImage & image, bool ownership = true, bool bump = false);
|
|
||||||
QImage loadTextureImage(const QString & path, bool bump = false);
|
|
||||||
void reloadTexture(GLuint tid, const QString & path);
|
|
||||||
void reloadTexture(GLuint tid, const QImage & image);
|
|
||||||
int textureID (const QString & path, bool bump = false) {return tex_ids[bump ? 1 : 0][path];}
|
|
||||||
QImage textureImage(const QString & path, bool bump = false) {return tex_im [bump ? 1 : 0][path];}
|
|
||||||
void addTexture(const QString & path) {tex_pathes << path;}
|
|
||||||
bool loadTextures();
|
|
||||||
void deleteTextures();
|
|
||||||
void deleteTexture(const QString & name);
|
|
||||||
void clearImageCache();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static void convertToNormal(QImage & im);
|
|
||||||
|
|
||||||
static QStringList search_pathes;
|
|
||||||
|
|
||||||
QMap<QString, GLuint> tex_ids[2];
|
|
||||||
QMap<QString, QImage> tex_im [2];
|
|
||||||
QStringList tex_pathes;
|
|
||||||
QOpenGLExtraFunctions * f;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // GLTEXTUREMANAGER_H
|
|
||||||
102
glwidget.h
102
glwidget.h
@@ -1,102 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL GLWidget
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLWIDGET_H
|
|
||||||
#define GLWIDGET_H
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
|
|
||||||
class QGLView;
|
|
||||||
class ObjectBase;
|
|
||||||
class Scene;
|
|
||||||
|
|
||||||
class GLWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor)
|
|
||||||
Q_PROPERTY (qreal lineWidth READ lineWidth WRITE setLineWidth)
|
|
||||||
Q_PROPERTY (qreal FOV READ FOV WRITE setFOV)
|
|
||||||
Q_PROPERTY (qreal depthStart READ depthStart WRITE setDepthStart)
|
|
||||||
Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor)
|
|
||||||
Q_PROPERTY (bool grabMouse READ isGrabMouseEnabled WRITE setGrabMouseEnabled)
|
|
||||||
Q_PROPERTY (bool mouseRotate READ isMouseRotateEnabled WRITE setMouseRotateEnabled)
|
|
||||||
Q_PROPERTY (bool mouseSelection READ isMouseSelectionEnabled WRITE setMouseSelectionEnabled)
|
|
||||||
Q_PROPERTY (bool cameraOrbit READ isCameraOrbit WRITE setCameraOrbit)
|
|
||||||
Q_PROPERTY (bool hoverHalo READ isHoverHaloEnabled WRITE setHoverHaloEnabled)
|
|
||||||
Q_PROPERTY (QColor hoverHaloColor READ hoverHaloColor WRITE setHoverHaloColor)
|
|
||||||
Q_PROPERTY (qreal hoverHaloFillAlpha READ hoverHaloFillAlpha WRITE setHoverHaloFillAlpha)
|
|
||||||
Q_PROPERTY (bool selectionHalo READ isSelectionHaloEnabled WRITE setSelectionHaloEnabled)
|
|
||||||
Q_PROPERTY (QColor selectionHaloColor READ selectionHaloColor WRITE setSelectionHaloColor)
|
|
||||||
Q_PROPERTY (qreal selectionHaloFillAlpha READ selectionHaloFillAlpha WRITE setSelectionHaloFillAlpha)
|
|
||||||
public:
|
|
||||||
explicit GLWidget(QWidget *parent = nullptr);
|
|
||||||
QGLView * view() {return view_;}
|
|
||||||
|
|
||||||
QColor backColor() const;
|
|
||||||
qreal lineWidth() const;
|
|
||||||
qreal FOV() const;
|
|
||||||
qreal depthStart() const;
|
|
||||||
QColor ambientColor() const;
|
|
||||||
bool isLightEnabled() const;
|
|
||||||
bool isGrabMouseEnabled() const;
|
|
||||||
bool isMouseRotateEnabled() const;
|
|
||||||
bool isMouseSelectionEnabled() const;
|
|
||||||
bool isCameraOrbit() const;
|
|
||||||
bool isHoverHaloEnabled() const;
|
|
||||||
QColor hoverHaloColor() const;
|
|
||||||
qreal hoverHaloFillAlpha() const;
|
|
||||||
bool isSelectionHaloEnabled() const;
|
|
||||||
QColor selectionHaloColor() const;
|
|
||||||
qreal selectionHaloFillAlpha() const;
|
|
||||||
Scene * scene();
|
|
||||||
|
|
||||||
void addObject(ObjectBase * o);
|
|
||||||
QByteArray saveCamera();
|
|
||||||
void restoreCamera(const QByteArray & ba);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void stop();
|
|
||||||
void start(float freq = 60.0);
|
|
||||||
void setBackColor(const QColor & c);
|
|
||||||
void setLineWidth(const qreal & arg);
|
|
||||||
void setFOV(const qreal & arg);
|
|
||||||
void setDepthStart(const qreal & arg);
|
|
||||||
void setAmbientColor(const QColor & arg);
|
|
||||||
void setLightEnabled(const bool & arg);
|
|
||||||
void setGrabMouseEnabled(const bool & arg);
|
|
||||||
void setMouseRotateEnabled(const bool & arg);
|
|
||||||
void setMouseSelectionEnabled(const bool & arg);
|
|
||||||
void setCameraOrbit(const bool & arg);
|
|
||||||
void setHoverHaloEnabled(const bool & arg);
|
|
||||||
void setHoverHaloColor(const QColor & arg);
|
|
||||||
void setHoverHaloFillAlpha(const qreal & arg);
|
|
||||||
void setSelectionHaloEnabled(const bool & arg);
|
|
||||||
void setSelectionHaloColor(const QColor & arg);
|
|
||||||
void setSelectionHaloFillAlpha(const qreal & arg);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void viewDoubleClicked();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QWidget * container;
|
|
||||||
QGLView * view_;
|
|
||||||
QLayout * lay;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // GLWIDGET_H
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL MouseController
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MOUSE_CONTROLLER_H
|
|
||||||
#define MOUSE_CONTROLLER_H
|
|
||||||
|
|
||||||
#include "glprimitives.h"
|
|
||||||
#include "glcamera.h"
|
|
||||||
#include "renderer_service.h"
|
|
||||||
#include <QMouseEvent>
|
|
||||||
#include <QTime>
|
|
||||||
|
|
||||||
|
|
||||||
class MouseController: public QObject
|
|
||||||
{
|
|
||||||
friend class QGLView;
|
|
||||||
friend class RendererSelection;
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
MouseController(QGLView * view_);
|
|
||||||
virtual ~MouseController();
|
|
||||||
|
|
||||||
bool isGrabMouseEnabled() const {return grabMouse_;}
|
|
||||||
bool isMouseRotateEnabled() const {return mouseRotate_;}
|
|
||||||
bool isMouseSelectionEnabled() const {return mouseSelect_;}
|
|
||||||
bool isCameraOrbit() const {return cameraOrbit_;}
|
|
||||||
|
|
||||||
Qt::MouseButton selectionButton() const {return sel_button;}
|
|
||||||
Qt::KeyboardModifier selectionModifier() const {return sel_mod;}
|
|
||||||
|
|
||||||
void setSelectionButton(Qt::MouseButton v) {sel_button = v;}
|
|
||||||
void setSelectionModifier(Qt::KeyboardModifier v) {sel_mod = v;}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void resize();
|
|
||||||
void mousePressEvent(QMouseEvent * e);
|
|
||||||
void mouseMoveEvent(QMouseEvent * e);
|
|
||||||
void mouseReleaseEvent(QMouseEvent * e);
|
|
||||||
void wheelEvent(QWheelEvent * e);
|
|
||||||
void leaveEvent(QEvent * );
|
|
||||||
void mouseDoubleClickEvent(QMouseEvent * e);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QGLView * view;
|
|
||||||
QPoint lastPos, downPos;
|
|
||||||
QSet<int> keys_;
|
|
||||||
QVector<ObjectBase * > hov_objects, hov_aims;
|
|
||||||
Qt::MouseButton sel_button;
|
|
||||||
Qt::KeyboardModifier sel_mod;
|
|
||||||
RendererService::HandleAction cur_action;
|
|
||||||
QFlags<RendererService::HandleMesh> cur_handle;
|
|
||||||
float app_scale;
|
|
||||||
bool grabMouse_, mouse_first, mouseRotate_, mouseSelect_, customMouseMove_, canSelect_;
|
|
||||||
bool cameraOrbit_, selecting_, mouse_sec;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void setGrabMouseEnabled(const bool & arg) {grabMouse_ = arg; mouse_first = true;}
|
|
||||||
void setMouseRotateEnabled(const bool & arg) {mouseRotate_ = arg;}
|
|
||||||
void setMouseSelectionEnabled(const bool & arg) {mouseSelect_ = arg;}
|
|
||||||
void setCustomMouseMove(const bool & arg) {customMouseMove_ = arg;}
|
|
||||||
void setCameraOrbit(const bool & arg) {cameraOrbit_ = arg;}
|
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // QGLVIEW_H
|
|
||||||
112
openglwindow.cpp
112
openglwindow.cpp
@@ -1,112 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL OpenGLWindow
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "openglwindow.h"
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QOpenGLContext>
|
|
||||||
#include <QOpenGLPaintDevice>
|
|
||||||
#include <QPainter>
|
|
||||||
|
|
||||||
|
|
||||||
OpenGLWindow::OpenGLWindow(QWindow *parent)
|
|
||||||
: QWindow(parent)
|
|
||||||
, m_context(nullptr)
|
|
||||||
, m_device(nullptr)
|
|
||||||
{
|
|
||||||
setFlags(flags() | Qt::FramelessWindowHint);
|
|
||||||
setSurfaceType(QWindow::OpenGLSurface);
|
|
||||||
QSurfaceFormat format = QSurfaceFormat::defaultFormat();
|
|
||||||
// qDebug() << format;
|
|
||||||
#ifdef QT_OPENGL_ES_2
|
|
||||||
format.setRenderableType(QSurfaceFormat::OpenGLES);
|
|
||||||
#else
|
|
||||||
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
|
|
||||||
format.setVersion(4, 0);
|
|
||||||
format.setProfile(QSurfaceFormat::CoreProfile);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
format.setDepthBufferSize(24);
|
|
||||||
format.setSamples(8);
|
|
||||||
setFormat(format);
|
|
||||||
QSurfaceFormat::setDefaultFormat(format);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
OpenGLWindow::~OpenGLWindow() {
|
|
||||||
delete m_device;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OpenGLWindow::render(QPainter *painter) {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OpenGLWindow::initialize() {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OpenGLWindow::render() {
|
|
||||||
// if (!m_device) m_device = new QOpenGLPaintDevice;
|
|
||||||
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
|
||||||
// m_device->setSize(size() * devicePixelRatio());
|
|
||||||
// m_device->setDevicePixelRatio(devicePixelRatio());
|
|
||||||
// QPainter painter(m_device);
|
|
||||||
// render(&painter);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OpenGLWindow::renderLater() {
|
|
||||||
requestUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool OpenGLWindow::event(QEvent *event) {
|
|
||||||
switch (event->type()) {
|
|
||||||
case QEvent::UpdateRequest:
|
|
||||||
renderNow();
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return QWindow::event(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OpenGLWindow::exposeEvent(QExposeEvent *event) {
|
|
||||||
if (isExposed()) renderNow();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OpenGLWindow::renderNow() {
|
|
||||||
if (!isExposed())
|
|
||||||
return;
|
|
||||||
bool needsInitialize = false;
|
|
||||||
if (!m_context) {
|
|
||||||
m_context = new QOpenGLContext(this);
|
|
||||||
m_context->setFormat(requestedFormat());
|
|
||||||
m_context->create();
|
|
||||||
needsInitialize = true;
|
|
||||||
}
|
|
||||||
m_context->makeCurrent(this);
|
|
||||||
if (needsInitialize) {
|
|
||||||
initializeOpenGLFunctions();
|
|
||||||
initialize();
|
|
||||||
}
|
|
||||||
render();
|
|
||||||
m_context->swapBuffers(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL OpenGLWindow
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <QWindow>
|
|
||||||
#include <QOpenGLExtraFunctions>
|
|
||||||
|
|
||||||
class QPainter;
|
|
||||||
class QOpenGLContext;
|
|
||||||
class QOpenGLPaintDevice;
|
|
||||||
|
|
||||||
|
|
||||||
class OpenGLWindow: public QWindow, public QOpenGLExtraFunctions
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit OpenGLWindow(QWindow *parent = nullptr);
|
|
||||||
~OpenGLWindow();
|
|
||||||
|
|
||||||
virtual void render(QPainter *painter);
|
|
||||||
virtual void render();
|
|
||||||
virtual void initialize();
|
|
||||||
QOpenGLContext * context() {return m_context;}
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void renderLater();
|
|
||||||
void renderNow();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool event(QEvent *event) override;
|
|
||||||
void exposeEvent(QExposeEvent *event) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QOpenGLContext *m_context;
|
|
||||||
QOpenGLPaintDevice *m_device;
|
|
||||||
};
|
|
||||||
|
|
||||||
288
qglview.cpp
288
qglview.cpp
@@ -1,288 +0,0 @@
|
|||||||
/*
|
|
||||||
QGLView
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "qglview.h"
|
|
||||||
#include "glmesh.h"
|
|
||||||
#include "gltexture_manager.h"
|
|
||||||
#include <chunkstream.h>
|
|
||||||
#include <qad_types.h>
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QOpenGLTexture>
|
|
||||||
#include <QKeyEvent>
|
|
||||||
|
|
||||||
using namespace QGLEngineShaders;
|
|
||||||
|
|
||||||
|
|
||||||
QGLView::QGLView(): OpenGLWindow(), renderer_(this), mouse(this) {
|
|
||||||
setIcon(QIcon(":/icons/qglview.png"));
|
|
||||||
deleting_ = false;
|
|
||||||
timer = 0;
|
|
||||||
need_init_ = is_first_draw = true;
|
|
||||||
backColor_ = Qt::darkGray;
|
|
||||||
hoverHaloColor_ = QColor(195, 140, 255);
|
|
||||||
selectionHaloColor_ = QColor(175, 255, 140);
|
|
||||||
ambientColor_ = QColor(10, 10, 10);
|
|
||||||
lineWidth_ = 1.;
|
|
||||||
max_anisotropic = 1;
|
|
||||||
max_texture_chanels = 8;
|
|
||||||
lightEnabled_ = true;
|
|
||||||
shaders_supported = false;
|
|
||||||
fps_cnt = 0;
|
|
||||||
fps_tm = fps_ = 0.;
|
|
||||||
fogColor_ = Qt::darkGray;
|
|
||||||
fogDensity_ = 0.;
|
|
||||||
fogDecay_ = 10.;
|
|
||||||
hoverHaloFill_ = selectionHaloFill_ = 0.15f;
|
|
||||||
//lmode = Simple;
|
|
||||||
setFeature(qglFXAA, false);
|
|
||||||
setFeature(qglAnisotropicLevel, 8);
|
|
||||||
setFeature(qglEyeAccomodationEnabled, false);
|
|
||||||
setFeature(qglEyeAccomodationTime, 16.);
|
|
||||||
setFeature(qglEyeAccomodationMaxSpeed, 0.2);
|
|
||||||
setFeature(qglBloomEnabled, false);
|
|
||||||
setFeature(qglBloomThreshold, 0.9);
|
|
||||||
setFeature(qglBloomFactor, 1.);
|
|
||||||
setFeature(qglBloomRadius, 8);
|
|
||||||
setFeature(qglMotionBlurEnabled, false);
|
|
||||||
setFeature(qglMotionBlurFactor, 1.);
|
|
||||||
setFeature(qglMotionBlurSteps, 8);
|
|
||||||
setFeature(qglShadowsEnabled, false);
|
|
||||||
setFeature(qglShadowsMapSize, 512);
|
|
||||||
setFeature(qglShadowsSoftEnabled, true);
|
|
||||||
setFeature(qglReflectionsEnabled, false);
|
|
||||||
setFeature(qglReflectionsBlur, true);
|
|
||||||
setFeature(qglSSAOEnabled, false);
|
|
||||||
setFeature(qglSSAORadius, 5);
|
|
||||||
setFeature(qglDepthOfFieldEnabled, false);
|
|
||||||
setFeature(qglDepthOfFieldAutoFocusEnabled, true);
|
|
||||||
setFeature(qglDepthOfFieldAutoFocusSpeed, 0.1);
|
|
||||||
setFeature(qglDepthOfFieldFocus, 1.);
|
|
||||||
setFeature(qglDepthOfFieldDiaphragm, 8.);
|
|
||||||
hoverHalo_ = selectionHalo_ = true;
|
|
||||||
fogEnabled_ = is_init = shaders_bind = changed_ = false;
|
|
||||||
rmode = ObjectBase::Fill;
|
|
||||||
scene_ = new Scene();
|
|
||||||
connect(scene_, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged()));
|
|
||||||
connect(scene_, SIGNAL(__destroyed()), this, SLOT(__destroyed()));
|
|
||||||
connect(scene_, SIGNAL(__objectDeleted(ObjectBase*)), this, SLOT(__objectDeleted(ObjectBase*)));
|
|
||||||
default_camera = new Camera();
|
|
||||||
default_camera->setPos(QVector3D(2, 2, 2));
|
|
||||||
default_camera->setAim(QVector3D());
|
|
||||||
camera_ = default_camera;
|
|
||||||
// qDebug() << camera_->aim();
|
|
||||||
default_camera->setName("Camera");
|
|
||||||
emit cameraPosChanged(default_camera->pos());
|
|
||||||
ktm_.restart();
|
|
||||||
|
|
||||||
Mesh * m = Primitive::cube(10, 10, 10);
|
|
||||||
m->flipNormals();
|
|
||||||
ObjectBase * o = new ObjectBase(m);
|
|
||||||
o->setColor(Qt::cyan);
|
|
||||||
scene()->addObject(o);
|
|
||||||
delete m;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QGLView::~QGLView() {
|
|
||||||
deleting_ = true;
|
|
||||||
stop();
|
|
||||||
scene_->clear();
|
|
||||||
delete scene_;
|
|
||||||
delete default_camera;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLView::stop() {
|
|
||||||
if (timer) killTimer(timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLView::start(float freq) {
|
|
||||||
timer = startTimer(freq <= 0.f ? 0 : int(1000.f / freq));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QList<Light * > QGLView::selectedLights() const {
|
|
||||||
QList<Light * > ret;
|
|
||||||
ObjectBaseList sol = scene_->selectedObjects();
|
|
||||||
foreach (ObjectBase * o, sol)
|
|
||||||
if (o->type() == ObjectBase::glLight)
|
|
||||||
ret << (Light*)o;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QList<Camera * > QGLView::selectedCameras() const {
|
|
||||||
QList<Camera * > ret;
|
|
||||||
ObjectBaseList sol = scene_->selectedObjects();
|
|
||||||
foreach (ObjectBase * o, sol)
|
|
||||||
if (o->type() == ObjectBase::glCamera)
|
|
||||||
ret << (Camera*)o;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void QGLView::resizeEvent(QResizeEvent * e) {
|
|
||||||
renderLater();
|
|
||||||
mouse.resize();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLView::timerEvent(QTimerEvent *) {
|
|
||||||
renderNow();
|
|
||||||
Qt::KeyboardModifiers km = QApplication::keyboardModifiers();
|
|
||||||
foreach (int i, keys_)
|
|
||||||
emit keyEvent((Qt::Key)i, km);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLView::render() {
|
|
||||||
resizeGL(width(), height());
|
|
||||||
emit glBeginPaint();
|
|
||||||
renderer_.mouse_pos = mapFromGlobal(QCursor::pos());
|
|
||||||
renderer_.renderScene();
|
|
||||||
emit glEndPaint();
|
|
||||||
fps_tm += time.elapsed();
|
|
||||||
time.restart();
|
|
||||||
fps_cnt++;
|
|
||||||
if (fps_tm < 1000.) return;
|
|
||||||
fps_ = fps_cnt / fps_tm * 1000.;
|
|
||||||
fps_tm = 0.;
|
|
||||||
fps_cnt = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLView::initialize() {
|
|
||||||
checkCaps();
|
|
||||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
||||||
glDisable(GL_MULTISAMPLE);
|
|
||||||
glDisable(GL_BLEND);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
glEnable(GL_TEXTURE_CUBE_MAP);
|
|
||||||
glEnable(GL_TEXTURE_MAX_ANISOTROPY_EXT);
|
|
||||||
glEnable(GL_CULL_FACE);
|
|
||||||
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
|
||||||
glCullFace(GL_BACK);
|
|
||||||
renderer_.reloadShaders();
|
|
||||||
renderer_.init(width(), height());
|
|
||||||
is_init = true;
|
|
||||||
need_init_ = false;
|
|
||||||
emit glInitializeDone();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLView::checkCaps() {
|
|
||||||
glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropic);
|
|
||||||
shaders_supported = QOpenGLShaderProgram::hasOpenGLShaderPrograms();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLView::__destroyed() {
|
|
||||||
renderer_.rend_mat.mat_thumbnails.clear();
|
|
||||||
mouse.hov_objects.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLView::__objectDeleted(ObjectBase * o) {
|
|
||||||
if (o == camera_)
|
|
||||||
setDefaultCamera();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLView::resizeGL(int width, int height) {
|
|
||||||
if (!is_init) return;
|
|
||||||
if (width <= 0 || height <= 0) return;
|
|
||||||
if (prev_size == QSize(width, height)) return;
|
|
||||||
prev_size = QSize(width, height);
|
|
||||||
aspect = float(width) / float(height);
|
|
||||||
renderer_.resize(width, height);
|
|
||||||
//qDebug() << "resize" << width << height;
|
|
||||||
iaspect = (aspect == 0.f) ? 0. : 1 / aspect;
|
|
||||||
glViewport(0, 0, width, height);
|
|
||||||
emit glResize(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLView::keyPressEvent(QKeyEvent * e) {
|
|
||||||
emit glKeyPressEvent(e);
|
|
||||||
if (e->key() > 0) keys_.insert(e->key());
|
|
||||||
if (e->key() == Qt::Key_F11) {
|
|
||||||
emit doubleClick();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLView::keyReleaseEvent(QKeyEvent * e) {
|
|
||||||
emit glKeyReleaseEvent(e);
|
|
||||||
keys_.remove(e->key());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLView::focusOutEvent(QFocusEvent *) {
|
|
||||||
keys_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLView::focusOn(const Box3D & bb) {
|
|
||||||
if (bb.isEmpty() || !camera()) return;
|
|
||||||
double size = qMax(qMax(bb.width, bb.length), bb.height);
|
|
||||||
camera()->setAim(bb.center());
|
|
||||||
camera()->flyToDistance(size * 1.25);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QByteArray QGLView::saveCamera() {
|
|
||||||
ChunkStream cs;
|
|
||||||
const Camera * c = camera();
|
|
||||||
cs.add(1, c->pos()).add(2, c->aim()).add(3, c->rotation()).add(4, c->FOV());
|
|
||||||
return cs.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLView::restoreCamera(const QByteArray & ba) {
|
|
||||||
if (ba.isEmpty()) return;
|
|
||||||
Camera * c = camera();
|
|
||||||
QVector3D pos(c->pos()), aim(c->aim()), ang(c->rotation());
|
|
||||||
float fov(c->FOV());
|
|
||||||
ChunkStream cs(ba);
|
|
||||||
cs.readAll();
|
|
||||||
cs.get(1, pos).get(2, aim).get(3, ang).get(4, fov);
|
|
||||||
camera()->setPos(pos);
|
|
||||||
camera()->setAim(aim);
|
|
||||||
camera()->setAngles(ang);
|
|
||||||
camera()->setFOV(fov);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QByteArray QGLView::saveFeatures() {
|
|
||||||
QByteArray ba;
|
|
||||||
QDataStream ds(&ba, QIODevice::WriteOnly);
|
|
||||||
ds << features_;
|
|
||||||
return ba;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLView::restoreFeatures(const QByteArray & ba) {
|
|
||||||
QHash<int, QVariant> f;
|
|
||||||
QDataStream ds(ba);
|
|
||||||
ds >> f;
|
|
||||||
features_ = f;
|
|
||||||
}
|
|
||||||
281
qglview.h
281
qglview.h
@@ -1,281 +0,0 @@
|
|||||||
/*
|
|
||||||
QGLView
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef QGLVIEW_H
|
|
||||||
#define QGLVIEW_H
|
|
||||||
|
|
||||||
#include "openglwindow.h"
|
|
||||||
#include "glframebuffer.h"
|
|
||||||
#include "glprimitives.h"
|
|
||||||
#include "glcamera.h"
|
|
||||||
#include "glscene.h"
|
|
||||||
#include "renderer.h"
|
|
||||||
#include "mouse_controller.h"
|
|
||||||
#include <QElapsedTimer>
|
|
||||||
#include <QMenu>
|
|
||||||
|
|
||||||
|
|
||||||
class QGLView: public OpenGLWindow
|
|
||||||
{
|
|
||||||
friend class RendererSelection;
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor)
|
|
||||||
Q_PROPERTY (float lineWidth READ lineWidth WRITE setLineWidth)
|
|
||||||
Q_PROPERTY (float FOV READ FOV WRITE setFOV)
|
|
||||||
Q_PROPERTY (float depthStart READ depthStart WRITE setDepthStart)
|
|
||||||
Q_PROPERTY (float gamma READ gamma WRITE setGamma)
|
|
||||||
Q_PROPERTY (bool autoExposure READ autoExposure WRITE setAutoExposure)
|
|
||||||
Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor)
|
|
||||||
Q_PROPERTY (QColor fogColor READ fogColor WRITE setFogColor)
|
|
||||||
Q_PROPERTY (bool fogEnabled READ isFogEnabled WRITE setFogEnabled)
|
|
||||||
Q_PROPERTY (float fogDensity READ fogDensity WRITE setFogDensity)
|
|
||||||
Q_PROPERTY (float fogDecay READ fogDecay WRITE setFogDecay)
|
|
||||||
Q_PROPERTY (int renderMode READ renderMode WRITE setRenderMode)
|
|
||||||
Q_PROPERTY (bool grabMouse READ isGrabMouseEnabled WRITE setGrabMouseEnabled)
|
|
||||||
Q_PROPERTY (bool mouseRotate READ isMouseRotateEnabled WRITE setMouseRotateEnabled)
|
|
||||||
Q_PROPERTY (bool mouseSelection READ isMouseSelectionEnabled WRITE setMouseSelectionEnabled)
|
|
||||||
Q_PROPERTY (bool cameraOrbit READ isCameraOrbit WRITE setCameraOrbit)
|
|
||||||
Q_PROPERTY (bool hoverHalo READ isHoverHaloEnabled WRITE setHoverHaloEnabled)
|
|
||||||
Q_PROPERTY (QColor hoverHaloColor READ hoverHaloColor WRITE setHoverHaloColor)
|
|
||||||
Q_PROPERTY (float hoverHaloFillAlpha READ hoverHaloFillAlpha WRITE setHoverHaloFillAlpha)
|
|
||||||
Q_PROPERTY (bool selectionHalo READ isSelectionHaloEnabled WRITE setSelectionHaloEnabled)
|
|
||||||
Q_PROPERTY (QColor selectionHaloColor READ selectionHaloColor WRITE setSelectionHaloColor)
|
|
||||||
Q_PROPERTY (float selectionHaloFillAlpha READ selectionHaloFillAlpha WRITE setSelectionHaloFillAlpha)
|
|
||||||
Q_PROPERTY (Qt::MouseButton selectionButton READ selectionButton WRITE setSelectionButton)
|
|
||||||
Q_PROPERTY (Qt::KeyboardModifier selectionModifier READ selectionModifier WRITE setSelectionModifier)
|
|
||||||
Q_PROPERTY (Scene::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode)
|
|
||||||
|
|
||||||
public:
|
|
||||||
QGLView();
|
|
||||||
virtual ~QGLView();
|
|
||||||
|
|
||||||
enum CameraLightMode {
|
|
||||||
clmOff,
|
|
||||||
clmAuto,
|
|
||||||
clmOn,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Feature {
|
|
||||||
qglFXAA,
|
|
||||||
qglAnisotropicLevel,
|
|
||||||
qglEyeAccomodationEnabled,
|
|
||||||
qglEyeAccomodationTime,
|
|
||||||
qglEyeAccomodationMaxSpeed,
|
|
||||||
qglBloomEnabled,
|
|
||||||
qglBloomThreshold,
|
|
||||||
qglBloomFactor,
|
|
||||||
qglBloomRadius,
|
|
||||||
qglMotionBlurEnabled,
|
|
||||||
qglMotionBlurFactor,
|
|
||||||
qglMotionBlurSteps,
|
|
||||||
qglShadowsEnabled,
|
|
||||||
qglShadowsMapSize,
|
|
||||||
qglShadowsSoftEnabled,
|
|
||||||
qglReflectionsEnabled,
|
|
||||||
qglReflectionsBlur,
|
|
||||||
qglSSAOEnabled,
|
|
||||||
qglSSAORadius,
|
|
||||||
qglDepthOfFieldEnabled,
|
|
||||||
qglDepthOfFieldAutoFocusEnabled,
|
|
||||||
qglDepthOfFieldAutoFocusSpeed,
|
|
||||||
qglDepthOfFieldFocus,
|
|
||||||
qglDepthOfFieldDiaphragm
|
|
||||||
};
|
|
||||||
|
|
||||||
Q_ENUM(CameraLightMode)
|
|
||||||
|
|
||||||
void stop();
|
|
||||||
void start(float freq = 60.);
|
|
||||||
|
|
||||||
QColor backColor() const {return backColor_;}
|
|
||||||
float lineWidth() const {return lineWidth_;}
|
|
||||||
float FOV() const {return camera()->FOV();}
|
|
||||||
float depthStart() const {return camera()->depthStart();}
|
|
||||||
float currentFPS() const {return fps_;}
|
|
||||||
float gamma() const {return renderer_.gamma_;}
|
|
||||||
bool autoExposure() const {return renderer_.tone_proc.enabled;}
|
|
||||||
int maxAnisotropicLevel() const {return max_anisotropic;}
|
|
||||||
QString environmentMapFile() const {return renderer_.tex_env.fileHDR();}
|
|
||||||
|
|
||||||
QColor ambientColor() const {return ambientColor_;}
|
|
||||||
QColor fogColor() const {return fogColor_;}
|
|
||||||
float fogDensity() const {return fogDensity_;}
|
|
||||||
float fogDecay() const {return fogDecay_;}
|
|
||||||
bool isFogEnabled() const {return fogEnabled_;}
|
|
||||||
bool isLightEnabled() const {return lightEnabled_;}
|
|
||||||
bool isGrabMouseEnabled() const {return mouse.isGrabMouseEnabled();}
|
|
||||||
bool isMouseRotateEnabled() const {return mouse.isMouseRotateEnabled();}
|
|
||||||
bool isMouseSelectionEnabled() const {return mouse.isMouseSelectionEnabled();}
|
|
||||||
bool isCameraOrbit() const {return mouse.isCameraOrbit();}
|
|
||||||
bool isHoverHaloEnabled() const {return hoverHalo_;}
|
|
||||||
QColor hoverHaloColor() const {return hoverHaloColor_;}
|
|
||||||
float hoverHaloFillAlpha() const {return hoverHaloFill_;}
|
|
||||||
bool isSelectionHaloEnabled() const {return selectionHalo_;}
|
|
||||||
QColor selectionHaloColor() const {return selectionHaloColor_;}
|
|
||||||
float selectionHaloFillAlpha() const {return selectionHaloFill_;}
|
|
||||||
|
|
||||||
QVariant feature(Feature f) const {return features_.value(int(f));}
|
|
||||||
QVariant setFeature(Feature f, const QVariant & value) {QVariant ret = features_.value(int(f)); features_[int(f)] = value; return ret;}
|
|
||||||
bool isFeatureEnabled(Feature f) const {return features_[int(f)].toBool();}
|
|
||||||
|
|
||||||
int renderMode() const {return (int)rmode;}
|
|
||||||
void setRenderMode(int mode) {rmode = (ObjectBase::RenderMode)mode;}
|
|
||||||
|
|
||||||
bool isServiceMode() const {return renderer_.edit_mode;}
|
|
||||||
void setServiceMode(bool yes) {renderer_.edit_mode = yes;}
|
|
||||||
|
|
||||||
|
|
||||||
Scene::SelectionMode selectionMode() const {return scene_->selectionMode();}
|
|
||||||
Qt::MouseButton selectionButton() const {return mouse.selectionButton();}
|
|
||||||
Qt::KeyboardModifier selectionModifier() const {return mouse.selectionModifier();}
|
|
||||||
|
|
||||||
void setSelectionMode(Scene::SelectionMode m) {scene_->setSelectionMode(m);}
|
|
||||||
void setSelectionButton(Qt::MouseButton v) {mouse.setSelectionButton(v);}
|
|
||||||
void setSelectionModifier(Qt::KeyboardModifier v) {mouse.setSelectionModifier(v);}
|
|
||||||
|
|
||||||
void selectObject(ObjectBase * o, bool add_to_selection = false) {scene_->selectObject(o, add_to_selection);}
|
|
||||||
void clearSelection() {scene_->clearSelection();}
|
|
||||||
ObjectBaseList selectedObjects(bool top_only = false) const {return scene_->selectedObjects(top_only);}
|
|
||||||
QList<Light * > selectedLights() const;
|
|
||||||
QList<Camera * > selectedCameras() const;
|
|
||||||
ObjectBase * selectedObject() const {return scene_->selectedObject();}
|
|
||||||
|
|
||||||
TextureManager * textureManager() {return renderer_.textures_manager;}
|
|
||||||
void reloadTextures() {renderer_.markReloadTextures();}
|
|
||||||
|
|
||||||
Scene * scene() {return scene_;}
|
|
||||||
void focusOn(const Box3D & bb);
|
|
||||||
void setCameraLightMode(CameraLightMode m) {renderer_.setCameraLightMode(m);}
|
|
||||||
CameraLightMode cameraLightMode() const {return (CameraLightMode)renderer_.cameraLightMode();}
|
|
||||||
|
|
||||||
Camera * camera() {return camera_;}
|
|
||||||
const Camera * camera() const {return camera_;}
|
|
||||||
void setCamera(Camera * camera) {camera_ = camera;}
|
|
||||||
void setDefaultCamera() {camera_ = default_camera;}
|
|
||||||
QByteArray saveCamera();
|
|
||||||
void restoreCamera(const QByteArray & ba);
|
|
||||||
QByteArray saveFeatures();
|
|
||||||
void restoreFeatures(const QByteArray & ba);
|
|
||||||
|
|
||||||
QImage materialThumbnail(Material * m) {return renderer_.materialThumbnail(m);}
|
|
||||||
void setCurrentAction(RendererService::HandleAction ha) {renderer_.rend_service.setCurrentAction(ha);}
|
|
||||||
void setContextActions(QList<QAction*> al) {context_menu.clear(); context_menu.addActions(al);}
|
|
||||||
void popupMenu(const QPoint &pos, QAction *at = nullptr) {context_menu.popup(pos, at);}
|
|
||||||
|
|
||||||
GLfloat aspect, iaspect;
|
|
||||||
Renderer renderer_;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void render();
|
|
||||||
void resizeEvent(QResizeEvent * e);
|
|
||||||
|
|
||||||
void timerEvent(QTimerEvent * );
|
|
||||||
void initialize();
|
|
||||||
void resizeGL(int width, int height);
|
|
||||||
void mousePressEvent(QMouseEvent * e) {mouse.mousePressEvent(e);}
|
|
||||||
void mouseMoveEvent(QMouseEvent * e) {mouse.mouseMoveEvent(e);}
|
|
||||||
void mouseReleaseEvent(QMouseEvent * e) {mouse.mouseReleaseEvent(e);}
|
|
||||||
void wheelEvent(QWheelEvent * e) {mouse.wheelEvent(e);}
|
|
||||||
void mouseDoubleClickEvent(QMouseEvent * e) {mouse.mouseDoubleClickEvent(e);}
|
|
||||||
void leaveEvent(QEvent * );
|
|
||||||
|
|
||||||
void keyPressEvent(QKeyEvent * e);
|
|
||||||
void keyReleaseEvent(QKeyEvent * e);
|
|
||||||
void focusOutEvent(QFocusEvent *);
|
|
||||||
|
|
||||||
void checkCaps();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void processKeys();
|
|
||||||
bool setupViewport();
|
|
||||||
|
|
||||||
Scene * scene_;
|
|
||||||
Camera * camera_, * default_camera;
|
|
||||||
MouseController mouse;
|
|
||||||
QMenu context_menu;
|
|
||||||
QSet<int> keys_;
|
|
||||||
QColor backColor_, fogColor_, ambientColor_, hoverHaloColor_, selectionHaloColor_;
|
|
||||||
QElapsedTimer time, ktm_;
|
|
||||||
GLint max_anisotropic, max_texture_chanels;
|
|
||||||
ObjectBase::RenderMode rmode;
|
|
||||||
QHash<int, QVariant> features_;
|
|
||||||
QSize prev_size;
|
|
||||||
float lineWidth_;
|
|
||||||
float fps_, fps_tm, fogDensity_, fogDecay_;
|
|
||||||
float hoverHaloFill_, selectionHaloFill_, m_motionBlurFactor;
|
|
||||||
int timer, fps_cnt, sh_id_loc, deleting_;
|
|
||||||
bool is_first_draw, is_init, fogEnabled_, lightEnabled_;
|
|
||||||
bool shaders_supported, changed_, need_init_;
|
|
||||||
bool hoverHalo_, selectionHalo_, shaders_bind;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void __destroyed();
|
|
||||||
void __objectDeleted(ObjectBase * o);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void setBackColor(const QColor & arg) {backColor_ = arg;}
|
|
||||||
void setLineWidth(const float & arg) {lineWidth_ = arg;}
|
|
||||||
void setFOV(const float & arg) {camera()->setFOV(arg);}
|
|
||||||
void setDepthStart(const float & arg) {camera()->setDepthStart(arg);}
|
|
||||||
void setGamma(const float & arg) {renderer_.gamma_ = arg;}
|
|
||||||
void setAutoExposure(bool arg) {renderer_.tone_proc.enabled = arg;}
|
|
||||||
void setAmbientColor(const QColor & arg) {ambientColor_ = arg;}
|
|
||||||
void setEnvironmentMapFile(QString file) {renderer_.tex_env.setFileHDR(file); renderer_.recreateMaterialThumbnails(true);}
|
|
||||||
void setFogColor(const QColor & arg) {fogColor_ = arg;}
|
|
||||||
void setFogDensity(const float & arg) {fogDensity_ = arg;}
|
|
||||||
void setFogDecay(const float & arg) {fogDecay_ = arg;}
|
|
||||||
void setFogEnabled(const bool & arg) {fogEnabled_ = arg;}
|
|
||||||
void setLightEnabled(const bool & arg) {lightEnabled_ = arg;}
|
|
||||||
void setGrabMouseEnabled(const bool & arg) {mouse.setGrabMouseEnabled(arg);}
|
|
||||||
void setMouseRotateEnabled(const bool & arg) {mouse.setMouseRotateEnabled(arg);}
|
|
||||||
void setMouseSelectionEnabled(const bool & arg) {mouse.setMouseSelectionEnabled(arg);}
|
|
||||||
void setCustomMouseMove(const bool & arg) {mouse.setCustomMouseMove(arg);}
|
|
||||||
void setCameraOrbit(const bool & arg) {mouse.setCameraOrbit(arg);}
|
|
||||||
void setHoverHaloEnabled(const bool & arg) {hoverHalo_ = arg;}
|
|
||||||
void setHoverHaloColor(const QColor & arg) {hoverHaloColor_ = arg;}
|
|
||||||
void setHoverHaloFillAlpha(const float & arg) {hoverHaloFill_ = arg;}
|
|
||||||
void setSelectionHaloEnabled(const bool & arg) {selectionHalo_ = arg;}
|
|
||||||
void setSelectionHaloColor(const QColor & arg) {selectionHaloColor_ = arg;}
|
|
||||||
void setSelectionHaloFillAlpha(const float & arg) {selectionHaloFill_ = arg;}
|
|
||||||
|
|
||||||
void reloadShaders() {renderer_.reloadShaders();}
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void glBeginPaint();
|
|
||||||
void glEndPaint();
|
|
||||||
void glKeyPressEvent(QKeyEvent * e);
|
|
||||||
void glKeyReleaseEvent(QKeyEvent * e);
|
|
||||||
void glMousePressEvent(QMouseEvent * e);
|
|
||||||
void glMouseMoveEvent(QMouseEvent * e);
|
|
||||||
void glMouseReleaseEvent(QMouseEvent * e);
|
|
||||||
void glWheelEvent(QWheelEvent * e);
|
|
||||||
void glResize(int, int);
|
|
||||||
void glInitializeDone();
|
|
||||||
void cameraPosChanged(QVector3D pos);
|
|
||||||
void keyEvent(Qt::Key key, Qt::KeyboardModifiers mod);
|
|
||||||
void customMouseMoveEvent(QPoint curpos, QPoint lastpos, Qt::MouseButtons buttons);
|
|
||||||
|
|
||||||
void hoverChanged(ObjectBase * cur, ObjectBase * prev);
|
|
||||||
void selectionChanged();
|
|
||||||
void objectsPositionChanged();
|
|
||||||
void materialsChanged();
|
|
||||||
void materialThumbnailCreated(Material*);
|
|
||||||
void doubleClick();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // QGLVIEW_H
|
|
||||||
46
qglview.qrc
46
qglview.qrc
@@ -1,46 +0,0 @@
|
|||||||
<RCC>
|
|
||||||
<qresource prefix="/">
|
|
||||||
<file>coeffs_brdf.png</file>
|
|
||||||
<file>icons/add-type-camera.png</file>
|
|
||||||
<file>icons/add-type-geo.png</file>
|
|
||||||
<file>icons/add-type-light.png</file>
|
|
||||||
<file>icons/add-type-empty.png</file>
|
|
||||||
<file>icons/collapse.png</file>
|
|
||||||
<file>icons/expand.png</file>
|
|
||||||
<file>icons/edit-rename.png</file>
|
|
||||||
<file>icons/alpha.png</file>
|
|
||||||
<file>icons/application-exit.png</file>
|
|
||||||
<file>icons/configure.png</file>
|
|
||||||
<file>icons/dialog-close.png</file>
|
|
||||||
<file>icons/document-edit.png</file>
|
|
||||||
<file>icons/document-import.png</file>
|
|
||||||
<file>icons/document-new.png</file>
|
|
||||||
<file>icons/document-open.png</file>
|
|
||||||
<file>icons/document-save.png</file>
|
|
||||||
<file>icons/document-save-all.png</file>
|
|
||||||
<file>icons/edit-clear.png</file>
|
|
||||||
<file>icons/edit-clear-locationbar-rtl.png</file>
|
|
||||||
<file>icons/edit-copy.png</file>
|
|
||||||
<file>icons/edit-delete.png</file>
|
|
||||||
<file>icons/edit-find.png</file>
|
|
||||||
<file>icons/edit-paste.png</file>
|
|
||||||
<file>icons/go-jump.png</file>
|
|
||||||
<file>icons/go-top.png</file>
|
|
||||||
<file>icons/layer-visible-on.png</file>
|
|
||||||
<file>icons/layer-visible-off.png</file>
|
|
||||||
<file>icons/light-+.png</file>
|
|
||||||
<file>icons/list-add.png</file>
|
|
||||||
<file>icons/object-flip-horizontal.png</file>
|
|
||||||
<file>icons/object-flip-vertical.png</file>
|
|
||||||
<file>icons/picker.png</file>
|
|
||||||
<file>icons/qglview.png</file>
|
|
||||||
<file>icons/transform-move.png</file>
|
|
||||||
<file>icons/transform-rotate.png</file>
|
|
||||||
<file>icons/transform-scale.png</file>
|
|
||||||
<file>icons/type-camera.png</file>
|
|
||||||
<file>icons/type-geo.png</file>
|
|
||||||
<file>icons/type-light.png</file>
|
|
||||||
<file>icons/type-empty.png</file>
|
|
||||||
<file>icons/view-refresh.png</file>
|
|
||||||
</qresource>
|
|
||||||
</RCC>
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
QGLViewWindow
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QDir>
|
|
||||||
#include "qglview_window.h"
|
|
||||||
|
|
||||||
int main(int argc, char ** argv) {
|
|
||||||
QApplication a(argc, argv);
|
|
||||||
a.setAttribute(Qt::AA_UseHighDpiPixmaps, true);
|
|
||||||
QGLViewWindow w;
|
|
||||||
w.show();
|
|
||||||
QStringList al(a.arguments());
|
|
||||||
al.pop_front();
|
|
||||||
foreach (QString s, al)
|
|
||||||
w.loadFile(s);
|
|
||||||
return a.exec();
|
|
||||||
}
|
|
||||||
@@ -1,251 +0,0 @@
|
|||||||
/*
|
|
||||||
QGLViewWindow
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "qglview_window.h"
|
|
||||||
#include "renderer.h"
|
|
||||||
#include "glwidget.h"
|
|
||||||
#include "gltexture_manager.h"
|
|
||||||
#include <QGraphicsRectItem>
|
|
||||||
#include <QImageReader>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include "qad_types.h"
|
|
||||||
|
|
||||||
|
|
||||||
QGLViewWindow::QGLViewWindow(QWidget * parent): QMainWindow(parent), Ui::QGLViewWindow() {
|
|
||||||
setupUi(this);
|
|
||||||
session.setFile("session_qglview_test.conf");
|
|
||||||
session.addEntry(this);
|
|
||||||
|
|
||||||
extensions = "All(" + supportedFormats().join(" ") + " *.qgl)";
|
|
||||||
extensions += ";;QGLEngine(*.qgl)";
|
|
||||||
|
|
||||||
//view->view()->camera()->setPos(QVector3D(2, 2, 2));
|
|
||||||
//view->view()->camera()->setAim(QVector3D());
|
|
||||||
//view->view()->camera()->flyToDistance(2.);
|
|
||||||
// view->setFrameShape(QFrame::NoFrame);
|
|
||||||
view->view()->setMouseRotateEnabled(true);
|
|
||||||
view->view()->setMouseSelectionEnabled(true);
|
|
||||||
view->view()->setSelectionHaloEnabled(true);
|
|
||||||
view->view()->setHoverHaloEnabled(true);
|
|
||||||
view->view()->setBackColor(Qt::lightGray);
|
|
||||||
view->view()->setDepthStart(0.1);
|
|
||||||
view->view()->setSelectionMode(Scene::smMultiSelection);
|
|
||||||
|
|
||||||
|
|
||||||
groupShadows->setChecked(view->view()->isFeatureEnabled(QGLView::qglShadowsEnabled));
|
|
||||||
groupEyeAccomodation->setChecked(view->view()->isFeatureEnabled(QGLView::qglEyeAccomodationEnabled));
|
|
||||||
groupBloom->setChecked(view->view()->isFeatureEnabled(QGLView::qglBloomEnabled));
|
|
||||||
groupMotionBlur->setChecked(view->view()->isFeatureEnabled(QGLView::qglMotionBlurEnabled));
|
|
||||||
groupReflections->setChecked(view->view()->isFeatureEnabled(QGLView::qglReflectionsEnabled));
|
|
||||||
checkSoftShadows->setChecked(view->view()->isFeatureEnabled(QGLView::qglShadowsSoftEnabled));
|
|
||||||
groupSSAO->setChecked(view->view()->isFeatureEnabled(QGLView::qglSSAOEnabled));
|
|
||||||
spinAccom->setValue(view->view()->feature(QGLView::qglEyeAccomodationTime).toDouble());
|
|
||||||
spinAccomMS->setValue(view->view()->feature(QGLView::qglEyeAccomodationMaxSpeed).toDouble());
|
|
||||||
checkReflectionsBlur->setChecked(view->view()->isFeatureEnabled(QGLView::qglReflectionsBlur));
|
|
||||||
spinShadowmapSize->setValue(view->view()->feature(QGLView::qglShadowsMapSize).toInt());
|
|
||||||
spinMotionBlurFactor->setValue(view->view()->feature(QGLView::qglMotionBlurFactor).toDouble());
|
|
||||||
spinMotionBlurSteps->setValue(view->view()->feature(QGLView::qglMotionBlurSteps).toInt());
|
|
||||||
spinBloomFactor->setValue(view->view()->feature(QGLView::qglBloomFactor).toDouble());
|
|
||||||
spinBloomRadius->setValue(view->view()->feature(QGLView::qglBloomRadius).toInt());
|
|
||||||
spinBloomThreshold->setValue(view->view()->feature(QGLView::qglBloomThreshold).toDouble());
|
|
||||||
spinSSAORadius->setValue(view->view()->feature(QGLView::qglSSAORadius).toInt());
|
|
||||||
groupDOF->setChecked(view->view()->isFeatureEnabled(QGLView::qglDepthOfFieldEnabled));
|
|
||||||
checkDOFAutoFocus->setChecked(view->view()->isFeatureEnabled(QGLView::qglDepthOfFieldAutoFocusEnabled));
|
|
||||||
spinDOFFocus->setValue(view->view()->feature(QGLView::qglDepthOfFieldFocus).toDouble());
|
|
||||||
spinDOFDiaphragm->setValue(view->view()->feature(QGLView::qglDepthOfFieldDiaphragm).toDouble());
|
|
||||||
spinDOFSpeed->setValue(view->view()->feature(QGLView::qglDepthOfFieldAutoFocusSpeed).toDouble());
|
|
||||||
|
|
||||||
view->view()->start(-1);
|
|
||||||
startTimer(1000/60);
|
|
||||||
|
|
||||||
connect(view->view(), SIGNAL(keyEvent(Qt::Key, Qt::KeyboardModifiers)), this, SLOT(view_keyEvent(Qt::Key, Qt::KeyboardModifiers)));
|
|
||||||
//connect(matEditor, SIGNAL(changed()), this, SLOT(materialChanged()));
|
|
||||||
sceneTree->assignQGLView(view->view());
|
|
||||||
matEditor->assignQGLView(view->view());
|
|
||||||
objectEditor->assignQGLView(view->view());
|
|
||||||
primitiveEditor->assignQGLView(view->view());
|
|
||||||
viewEditor->assignQGLView(view->view());
|
|
||||||
|
|
||||||
session.load();
|
|
||||||
|
|
||||||
//loadFile("axis.DAE.qgl");
|
|
||||||
//matEditor->setMaterial(const_cast<ObjectBase*>(view->view()->scene()->rootObject()->child(0))->material());
|
|
||||||
/*Scene * sc = loadScene("truck.obj");
|
|
||||||
//view->view()->scene()->addScene(sc);
|
|
||||||
sc->rootObject()->moveY(-8);
|
|
||||||
for (int i = 0; i < 7; ++i) {
|
|
||||||
sc->rootObject()->moveY(2);
|
|
||||||
view->view()->scene()->addScene(sc);
|
|
||||||
}
|
|
||||||
//view->view()->scene()->dump();
|
|
||||||
delete sc;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QGLViewWindow::~QGLViewWindow() {
|
|
||||||
session.save();
|
|
||||||
//delete ps;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLViewWindow::changeEvent(QEvent * e) {
|
|
||||||
QMainWindow::changeEvent(e);
|
|
||||||
if (e->type() == QEvent::LanguageChange) {
|
|
||||||
retranslateUi(this);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLViewWindow::timerEvent(QTimerEvent * ) {
|
|
||||||
//static double t = 0.;
|
|
||||||
//((RendererSimple*)(view->view()->renderer()))->mpos = view->view()->mapFromGlobal(QCursor::pos());
|
|
||||||
statusBar()->showMessage(QString("FPS: %1").arg(QString::number(view->view()->currentFPS(), 'f', 2)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLViewWindow::loadFile(const QString & path, bool import) {
|
|
||||||
prev_path = path;
|
|
||||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
||||||
QFileInfo fi(path);
|
|
||||||
Scene * s = nullptr;
|
|
||||||
if (fi.suffix().toLower() == "qgl") s = loadFromQGLFile(path);
|
|
||||||
else s = loadScene(path);
|
|
||||||
QApplication::restoreOverrideCursor();
|
|
||||||
if (!s) {
|
|
||||||
QMessageBox::critical(this, "Import", "Can`t load " + path + "!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
s->setName(fi.baseName());
|
|
||||||
if (import) view->scene()->addScene(s);
|
|
||||||
else {
|
|
||||||
TextureManager::clearSearchPathes();
|
|
||||||
view->scene()->assignFrom(s);
|
|
||||||
view->view()->focusOn(view->scene()->boundingBox());
|
|
||||||
}
|
|
||||||
TextureManager::addSearchPath(fi.absoluteDir().path());
|
|
||||||
delete s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLViewWindow::on_actionReset_triggered() {
|
|
||||||
///view->view()->removeObject(axis, false);
|
|
||||||
view->view()->scene()->clear();
|
|
||||||
///view->view()->addObject(axis);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLViewWindow::on_actionImport_triggered() {
|
|
||||||
QStringList fl = QFileDialog::getOpenFileNames(this, "Select files", prev_path, extensions);
|
|
||||||
if (fl.isEmpty()) return;
|
|
||||||
prev_path = fl.back();
|
|
||||||
foreach (QString f, fl)
|
|
||||||
loadFile(f, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLViewWindow::on_actionSave_triggered() {
|
|
||||||
QString f = QFileDialog::getSaveFileName(this, "Select file", prev_path, "QGLView(*.qgl)");
|
|
||||||
if (f.isEmpty()) return;
|
|
||||||
if (f.right(4).toLower() != ".qgl")
|
|
||||||
f += ".qgl";
|
|
||||||
prev_path = f;
|
|
||||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
||||||
saveToQGLFile(f, view->scene());
|
|
||||||
QApplication::restoreOverrideCursor();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLViewWindow::on_actionSaveSelected_triggered() {
|
|
||||||
ObjectBase * sel_obj = view->view()->selectedObject();
|
|
||||||
if (!sel_obj) return;
|
|
||||||
QString f = QFileDialog::getSaveFileName(this, "Select file", prev_path, "QGLView(*.qgl)");
|
|
||||||
if (f.isEmpty()) return;
|
|
||||||
if (f.right(4).toLower() != ".qgl")
|
|
||||||
f += ".qgl";
|
|
||||||
prev_path = f;
|
|
||||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
||||||
///saveToQGLFile(f, sel_obj);
|
|
||||||
QApplication::restoreOverrideCursor();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLViewWindow::on_actionOpen_triggered() {
|
|
||||||
QString f = QFileDialog::getOpenFileName(this, "Select file", prev_path, extensions);
|
|
||||||
if (f.isEmpty()) return;
|
|
||||||
prev_path = f;
|
|
||||||
loadFile(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLViewWindow::view_keyEvent(Qt::Key k, Qt::KeyboardModifiers m) {
|
|
||||||
//qDebug() << k;
|
|
||||||
double spd = 0.2;
|
|
||||||
if (m.testFlag(Qt::ShiftModifier))
|
|
||||||
spd = 0.5;
|
|
||||||
switch (k) {
|
|
||||||
case Qt::Key_W: view->view()->camera()->moveForward(spd); break;
|
|
||||||
case Qt::Key_S: view->view()->camera()->moveBackward(spd); break;
|
|
||||||
case Qt::Key_A: view->view()->camera()->moveLeft(spd); break;
|
|
||||||
case Qt::Key_D: view->view()->camera()->moveRight(spd); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLViewWindow::on_actionArrow_triggered(bool on) {
|
|
||||||
actionArrow ->setChecked(true);
|
|
||||||
actionMove ->setChecked(false);
|
|
||||||
actionRotate->setChecked(false);
|
|
||||||
actionScale ->setChecked(false);
|
|
||||||
view->view()->setCurrentAction(RendererService::haNoAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLViewWindow::on_actionMove_triggered(bool on) {
|
|
||||||
actionArrow ->setChecked(false);
|
|
||||||
actionMove ->setChecked(true);
|
|
||||||
actionRotate->setChecked(false);
|
|
||||||
actionScale ->setChecked(false);
|
|
||||||
view->view()->setCurrentAction(RendererService::haMove);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLViewWindow::on_actionRotate_triggered(bool on) {
|
|
||||||
actionArrow ->setChecked(false);
|
|
||||||
actionMove ->setChecked(false);
|
|
||||||
actionRotate->setChecked(true);
|
|
||||||
actionScale ->setChecked(false);
|
|
||||||
view->view()->setCurrentAction(RendererService::haRotate);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QGLViewWindow::on_actionScale_triggered(bool on) {
|
|
||||||
actionArrow ->setChecked(false);
|
|
||||||
actionMove ->setChecked(false);
|
|
||||||
actionRotate->setChecked(false);
|
|
||||||
actionScale ->setChecked(true);
|
|
||||||
view->view()->setCurrentAction(RendererService::haScale);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#include "glcubemap.h"
|
|
||||||
void QGLViewWindow::on_pushButton_3_clicked() {
|
|
||||||
QString f = QFileDialog::getOpenFileName(this, "Select file", "", "*");
|
|
||||||
if (f.isEmpty()) return;
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
QGLViewWindow
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef QGLVIEWWINDOW_H
|
|
||||||
#define QGLVIEWWINDOW_H
|
|
||||||
|
|
||||||
#include <QTranslator>
|
|
||||||
#include <QInputDialog>
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QColorDialog>
|
|
||||||
#include <QCloseEvent>
|
|
||||||
#include <QClipboard>
|
|
||||||
#include <QRadioButton>
|
|
||||||
#include <QUrl>
|
|
||||||
#include <QThread>
|
|
||||||
#include <QTime>
|
|
||||||
#include <QSplitter>
|
|
||||||
#include "ui_qglview_window.h"
|
|
||||||
#include "formats/loader_qgl.h"
|
|
||||||
#include "formats/loader_assimp.h"
|
|
||||||
#include "session_manager.h"
|
|
||||||
//#include "renderer_rt.h"
|
|
||||||
#include "qglview.h"
|
|
||||||
#include "ui_qglview_window.h"
|
|
||||||
|
|
||||||
|
|
||||||
class QGLViewWindow: public QMainWindow, public Ui::QGLViewWindow
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
QGLViewWindow(QWidget * parent = 0);
|
|
||||||
~QGLViewWindow();
|
|
||||||
|
|
||||||
void loadFile(const QString & path, bool import = false);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Qt`s overloaded
|
|
||||||
void changeEvent(QEvent * e);
|
|
||||||
void timerEvent(QTimerEvent * );
|
|
||||||
|
|
||||||
QString extensions;
|
|
||||||
QTranslator translator;
|
|
||||||
QString prev_path;
|
|
||||||
//GLPrimitiveCube * box;
|
|
||||||
Material m;
|
|
||||||
SessionManager session;
|
|
||||||
bool isChanged;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void on_groupShadows_clicked(bool val) {view->view()->setFeature(QGLView::qglShadowsEnabled, val);}
|
|
||||||
void on_groupEyeAccomodation_clicked(bool val) {view->view()->setFeature(QGLView::qglEyeAccomodationEnabled, val);}
|
|
||||||
void on_groupBloom_clicked(bool val) {view->view()->setFeature(QGLView::qglBloomEnabled, val);}
|
|
||||||
void on_groupMotionBlur_clicked(bool val) {view->view()->setFeature(QGLView::qglMotionBlurEnabled, val);}
|
|
||||||
void on_groupReflections_clicked(bool val) {view->view()->setFeature(QGLView::qglReflectionsEnabled, val);}
|
|
||||||
void on_checkSoftShadows_clicked(bool val) {view->view()->setFeature(QGLView::qglShadowsSoftEnabled, val);}
|
|
||||||
void on_groupSSAO_clicked(bool val) {view->view()->setFeature(QGLView::qglSSAOEnabled, val);}
|
|
||||||
void on_groupDOF_clicked(bool val) {view->view()->setFeature(QGLView::qglDepthOfFieldEnabled, val);}
|
|
||||||
void on_checkDOFAutoFocus_clicked(bool val) {view->view()->setFeature(QGLView::qglDepthOfFieldAutoFocusEnabled, val);}
|
|
||||||
void on_spinDOFFocus_valueChanged(double val) {view->view()->setFeature(QGLView::qglDepthOfFieldFocus, val);}
|
|
||||||
void on_spinDOFDiaphragm_valueChanged(double val) {view->view()->setFeature(QGLView::qglDepthOfFieldDiaphragm, val);}
|
|
||||||
void on_spinDOFSpeed_valueChanged(double val) {view->view()->setFeature(QGLView::qglDepthOfFieldAutoFocusSpeed, val);}
|
|
||||||
void on_spinAccom_valueChanged(double val) {view->view()->setFeature(QGLView::qglEyeAccomodationTime, val);}
|
|
||||||
void on_spinAccomMS_valueChanged(double val) {view->view()->setFeature(QGLView::qglEyeAccomodationMaxSpeed, val);}
|
|
||||||
void on_checkReflectionsBlur_clicked(bool val) {view->view()->setFeature(QGLView::qglReflectionsBlur, val);}
|
|
||||||
void on_spinShadowmapSize_valueChanged(double val) {view->view()->setFeature(QGLView::qglShadowsMapSize, val);}
|
|
||||||
void on_spinMotionBlurFactor_valueChanged(double val) {view->view()->setFeature(QGLView::qglMotionBlurFactor, val);}
|
|
||||||
void on_spinMotionBlurSteps_valueChanged(int val) {view->view()->setFeature(QGLView::qglMotionBlurSteps, val);}
|
|
||||||
void on_spinBloomFactor_valueChanged(double val) {view->view()->setFeature(QGLView::qglBloomFactor, val);}
|
|
||||||
void on_spinBloomRadius_valueChanged(int val) {view->view()->setFeature(QGLView::qglBloomRadius, val);}
|
|
||||||
void on_spinBloomThreshold_valueChanged(double val) {view->view()->setFeature(QGLView::qglBloomThreshold, val);}
|
|
||||||
void on_spinSSAORadius_valueChanged(int val) {view->view()->setFeature(QGLView::qglSSAORadius, val);}
|
|
||||||
|
|
||||||
void on_actionExit_triggered() {close();}
|
|
||||||
void on_actionReset_triggered();
|
|
||||||
void on_actionImport_triggered();
|
|
||||||
void on_actionSave_triggered();
|
|
||||||
void on_actionSaveSelected_triggered();
|
|
||||||
void on_actionOpen_triggered();
|
|
||||||
|
|
||||||
void view_keyEvent(Qt::Key k, Qt::KeyboardModifiers m);
|
|
||||||
|
|
||||||
void on_pushButton_2_clicked() {view->view()->reloadShaders();}
|
|
||||||
|
|
||||||
void on_actionArrow_triggered(bool on);
|
|
||||||
void on_actionMove_triggered(bool on);
|
|
||||||
void on_actionRotate_triggered(bool on);
|
|
||||||
void on_actionScale_triggered(bool on);
|
|
||||||
|
|
||||||
void on_colorFogBack_colorChanged(const QColor & v) {view->view()->setFogColor(v);}
|
|
||||||
void on_spinFogDensity_valueChanged(double v) {view->view()->setFogDensity(v);}
|
|
||||||
void on_spinFogDecay_valueChanged(double v) {view->view()->setFogDecay(v);}
|
|
||||||
|
|
||||||
void on_pushButton_3_clicked();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
private:
|
|
||||||
QMatrix4x4 cam_mat;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // QGLVIEWWINDOW_H
|
|
||||||
361
renderer.cpp
361
renderer.cpp
@@ -1,361 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL Renderer
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define GL_GLEXT_PROTOTYPES
|
|
||||||
#include <QOpenGLExtraFunctions>
|
|
||||||
#include <qad_types.h>
|
|
||||||
#include "renderer.h"
|
|
||||||
#include "qglview.h"
|
|
||||||
#include "glmesh.h"
|
|
||||||
#include "gltexture_manager.h"
|
|
||||||
#include "glshaders.h"
|
|
||||||
|
|
||||||
|
|
||||||
using namespace QGLEngineShaders;
|
|
||||||
|
|
||||||
|
|
||||||
Renderer::Renderer(QGLView * view_): RendererBase(view_),
|
|
||||||
fbo_ds (view_, QVector<GLenum>() << GL_RGBA16F << GL_RGBA32F << GL_RGBA16F << GL_RGBA16F << GL_RGBA16F),
|
|
||||||
fbo_out (view_, obrBuffersCount, false, GL_RGBA16F),
|
|
||||||
rend_mat(this), rend_service(this), rend_selection(this), tone_proc(this), tex_env(view_, 512) {
|
|
||||||
quad = Primitive::plane(2., 2.);
|
|
||||||
cam_light = new Light();
|
|
||||||
cam_light->intensity = 0.75;
|
|
||||||
cam_light->setName("Camera_Light");
|
|
||||||
|
|
||||||
shader_files[srSelectionFill ] = "selection.glsl";
|
|
||||||
shader_files[srSelectionHalo ] = "selection_halo.glsl";
|
|
||||||
shader_files[srSelectionApply] = "selection_apply.glsl";
|
|
||||||
shader_files[srSelectionFrame] = "selection_frame.glsl";
|
|
||||||
|
|
||||||
shader_files[srServiceFill ] = "service_fill.glsl";
|
|
||||||
shader_files[srServiceFrame] = "service_frame.glsl";
|
|
||||||
shader_files[srServiceLine ] = "service_line.glsl";
|
|
||||||
|
|
||||||
shader_files[srGeometryPass ] = "ds_geom.glsl";
|
|
||||||
shader_files[srLightOmniPass] = "ds_light.glsl";
|
|
||||||
shader_files[srLightSpotPass] = "ds_light.glsl"; shader_defines[srLightSpotPass] << "SPOT";
|
|
||||||
shader_files[srFinalPass ] = "ds_final.glsl";
|
|
||||||
shader_files[srTonemapPass ] = "ds_tonemap.glsl";
|
|
||||||
|
|
||||||
shader_fxaa = 0;
|
|
||||||
gamma_ = 1.;
|
|
||||||
edit_mode = need_init_shaders = true;
|
|
||||||
camera_light_mode = QGLView::clmAuto;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Renderer::~Renderer() {
|
|
||||||
delete quad;
|
|
||||||
delete cam_light;
|
|
||||||
qDeleteAll(shaders.values());
|
|
||||||
if (shader_fxaa) delete shader_fxaa;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Renderer::init(int width, int height) {
|
|
||||||
resize(width, height);
|
|
||||||
rend_mat.init(width, height);
|
|
||||||
rend_service.init(width, height);
|
|
||||||
rend_selection.init(width, height);
|
|
||||||
tone_proc.init();
|
|
||||||
initQuad(quad);
|
|
||||||
initTextureArrays();
|
|
||||||
initCoeffTextures();
|
|
||||||
tex_env.init();
|
|
||||||
need_init_shaders = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Renderer::resize(int width, int height) {
|
|
||||||
rend_mat.resize(width, height);
|
|
||||||
rend_service.resize(width, height);
|
|
||||||
rend_selection.resize(width, height);
|
|
||||||
fbo_ds .resize(width, height);
|
|
||||||
fbo_out .resize(width, height);
|
|
||||||
tone_proc.resize();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Renderer::reloadShaders() {
|
|
||||||
QMapIterator<ShaderRole, QString> it(shader_files);
|
|
||||||
QString dir = ":shaders/";
|
|
||||||
while (it.hasNext()) {
|
|
||||||
it.next();
|
|
||||||
loadShadersMulti(shaders[it.key()], dir + it.value(), true, shader_defines.value(it.key()));
|
|
||||||
}
|
|
||||||
loadShadersMulti(tone_proc.shader_sum, dir + "sum.glsl", false);
|
|
||||||
QStringList fxaa_defs;
|
|
||||||
fxaa_defs << "FXAA_PC 1" << "FXAA_GLSL_130 1" << "FXAA_QUALITY__PRESET 15";
|
|
||||||
loadShaders(shader_fxaa, QStringList() << (dir + "fxaa.vert") << (dir + "fxaa.frag"), true, fxaa_defs);
|
|
||||||
need_init_shaders = true;
|
|
||||||
view->scene()->setLightsChanged();
|
|
||||||
view->scene()->setTreeStructChanged();
|
|
||||||
view->scene()->setMaterialsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Renderer::bindShader(Renderer::ShaderRole role, QOpenGLShaderProgram ** ret) {
|
|
||||||
QOpenGLShaderProgram * prog = shaders.value(role);
|
|
||||||
if (ret) *ret = prog;
|
|
||||||
if (!prog) return false;
|
|
||||||
if (!prog->isLinked()) return false;
|
|
||||||
prog->bind();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Renderer::bindShader(QOpenGLShaderProgram * sp) {
|
|
||||||
if (!sp) return true;
|
|
||||||
if (!sp->isLinked()) return true;
|
|
||||||
if (!sp->bind()) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Renderer::initShaders() {
|
|
||||||
if (!need_init_shaders) return;
|
|
||||||
need_init_shaders = false;
|
|
||||||
initUniformBuffer(shaders.value(srGeometryPass ), &buffer_materials , bpMaterials , "QGLMaterialData" );
|
|
||||||
initUniformBuffer(shaders.value(srLightOmniPass), &buffer_materials , bpMaterials , "QGLMaterialData" );
|
|
||||||
initUniformBuffer(shaders.value(srLightOmniPass), &buffer_lights , bpLightParameters, "QGLLightParameterData");
|
|
||||||
initUniformBuffer(shaders.value(srLightOmniPass), &buffer_lights_pos, bpLightPositions , "QGLLightPositionData" );
|
|
||||||
initUniformBuffer(shaders.value(srLightSpotPass), &buffer_materials , bpMaterials , "QGLMaterialData" );
|
|
||||||
initUniformBuffer(shaders.value(srLightSpotPass), &buffer_lights , bpLightParameters, "QGLLightParameterData");
|
|
||||||
initUniformBuffer(shaders.value(srLightSpotPass), &buffer_lights_pos, bpLightPositions , "QGLLightPositionData" );
|
|
||||||
ShaderRole roles[] = {srLightOmniPass, srLightSpotPass};
|
|
||||||
QOpenGLShaderProgram * prog = 0;
|
|
||||||
for (int p = 0; p < 2; ++p) {
|
|
||||||
if (!bindShader(roles[p], &prog)) continue;
|
|
||||||
for (int i = 0; i < 5; ++i)
|
|
||||||
prog->setUniformValue(QString("tex_%1").arg(i).toLatin1().constData(), i);
|
|
||||||
prog->setUniformValue("tex_coeffs[0]", (int)Renderer::dbrBuffersCount);
|
|
||||||
prog->setUniformValue("tex_env", (int)Renderer::dbrBuffersCount+1);
|
|
||||||
}
|
|
||||||
if (bindShader(srFinalPass, &prog)) {
|
|
||||||
prog->setUniformValue("tex_g1" , 0);
|
|
||||||
prog->setUniformValue("tex_s_0", 1);
|
|
||||||
prog->setUniformValue("tex_s_1", 2);
|
|
||||||
prog->setUniformValue("tex_t_0", 3);
|
|
||||||
prog->setUniformValue("tex_t_1", 4);
|
|
||||||
}
|
|
||||||
if (bindShader(srGeometryPass, &prog)) {
|
|
||||||
setUniformMaps(prog);
|
|
||||||
}
|
|
||||||
if (bindShader(srTonemapPass, &prog)) {
|
|
||||||
prog->setUniformValue("tex_0", 0);
|
|
||||||
prog->setUniformValue("tex_sum", 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Renderer::releaseShader() {
|
|
||||||
view->glUseProgram(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Renderer::fillObjectsBuffer(const ObjectBaseList & ol, RenderPass pass) {
|
|
||||||
cur_objects_.resize(ol.size());
|
|
||||||
for (int i = 0; i < ol.size(); ++i) {
|
|
||||||
Object & so(cur_objects_[i]);
|
|
||||||
ObjectBase * o = ol[i];
|
|
||||||
if (o->material()) {
|
|
||||||
so.material = o->material()->_index;
|
|
||||||
so.color = QVector4D(1,1,1,1);
|
|
||||||
} else {
|
|
||||||
so.material = 0;
|
|
||||||
so.color = QColor2QVector(o->color());
|
|
||||||
}
|
|
||||||
so.object_id = o->id();
|
|
||||||
o->worldTransform().transposed().copyDataTo(so.modelmatrix);
|
|
||||||
//qDebug() << "load obj" << o->name() << o->worldTransform();
|
|
||||||
}
|
|
||||||
//qDebug() << "fillObjectsBuffer" << ol.size();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Renderer::renderObjects(Scene & scene, RenderPass pass) {
|
|
||||||
QOpenGLExtraFunctions * f = view;
|
|
||||||
QMapIterator<Mesh*, ObjectBaseList> it(scene.geometries_used[pass]);
|
|
||||||
bool emit_pos_change = false;
|
|
||||||
while (it.hasNext()) {
|
|
||||||
it.next();
|
|
||||||
Mesh * mesh = it.key();
|
|
||||||
if (mesh->isObjectsChanged(pass)) {
|
|
||||||
mesh->setObjectsChanged(pass, false);
|
|
||||||
emit_pos_change = true;
|
|
||||||
fillObjectsBuffer(it.value(), pass);
|
|
||||||
//qDebug() << "loadObjects" << pass << cur_objects_.size();
|
|
||||||
mesh->loadObjects(f, cur_objects_, pass);
|
|
||||||
}
|
|
||||||
if (mesh->isSelectionChanged(pass) && edit_mode) {
|
|
||||||
mesh->setSelectionChanged(pass, false);
|
|
||||||
fillSelectionsBuffer(rend_selection.cur_selections_, it.value());
|
|
||||||
//qDebug() << "fillSelectionsBuffer" << pass << rend_selection.cur_selections_.size();
|
|
||||||
mesh->loadSelections(f, rend_selection.cur_selections_, pass);
|
|
||||||
}
|
|
||||||
//qDebug() << "draw" << pass << it.value().size();
|
|
||||||
mesh->draw(f, it.value().size(), pass);
|
|
||||||
}
|
|
||||||
if (emit_pos_change) emit view->objectsPositionChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Renderer::renderLight(int first_wr_buff, bool clear_only) {
|
|
||||||
QOpenGLShaderProgram * prog = 0;
|
|
||||||
Camera * cam = view->camera();
|
|
||||||
for (int i = 0; i < 2; ++i) {
|
|
||||||
view->glActiveTexture(GL_TEXTURE0 + Renderer::dbrBuffersCount + i);
|
|
||||||
view->glBindTexture(GL_TEXTURE_2D, tex_coeff[i]);
|
|
||||||
}
|
|
||||||
fbo_ds.bindColorTextures();
|
|
||||||
fbo_out.bind();
|
|
||||||
tex_env.bind((int)Renderer::dbrBuffersCount+1);
|
|
||||||
typedef QPair<Renderer::ShaderRole, Light::Type> PassPair;
|
|
||||||
QVector<PassPair> passes;
|
|
||||||
passes << PassPair(srLightOmniPass, Light::Omni) << PassPair(srLightSpotPass, Light::Cone);
|
|
||||||
QColor back = view->fogColor();
|
|
||||||
back.setAlpha(0);
|
|
||||||
foreach (PassPair pass, passes) {
|
|
||||||
if (bindShader(pass.first, &prog)) {
|
|
||||||
fbo_out.setWriteBuffer(first_wr_buff + pass.second);
|
|
||||||
glClearFramebuffer(back, false);
|
|
||||||
if (clear_only) continue;
|
|
||||||
setUniformCamera(prog, cam);
|
|
||||||
setUniformViewCorners(prog, cam);
|
|
||||||
prog->setUniformValue("lights_start", lights_start[pass.second]);
|
|
||||||
prog->setUniformValue("lights_count", (int)cur_lights[pass.second].size());
|
|
||||||
prog->setUniformValue("fog_color", view->fogColor());
|
|
||||||
prog->setUniformValue("fog_decay", qMax(view->fogDecay(), 0.001f));
|
|
||||||
prog->setUniformValue("fog_density", view->fogDensity());
|
|
||||||
prog->setUniformValue("view_mat", cam->viewMatrix().inverted().toGenericMatrix<3,3>());
|
|
||||||
renderQuad(prog, quad, cam);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Renderer::renderScene() {
|
|
||||||
initShaders();
|
|
||||||
tex_env.load();
|
|
||||||
QOpenGLExtraFunctions * f = view;
|
|
||||||
Scene & scene(*(view->scene()));
|
|
||||||
Camera * cam = view->camera();
|
|
||||||
QOpenGLShaderProgram * prog = 0;
|
|
||||||
bool scene_changed = scene.prepare();
|
|
||||||
scene.destroyUnused(f);
|
|
||||||
|
|
||||||
/// reload materials on change
|
|
||||||
if (scene_changed || scene.need_reload_materials) {
|
|
||||||
rend_selection.generateObjectsID(scene);
|
|
||||||
reloadMaterials(scene);
|
|
||||||
if (edit_mode)
|
|
||||||
recreateMaterialThumbnails();
|
|
||||||
emit view->materialsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// material thumbnails
|
|
||||||
if (edit_mode && !scene_changed) {
|
|
||||||
rend_mat.procQueue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// lights
|
|
||||||
cur_lights = scene.lights_used;
|
|
||||||
bool use_camlight = (camera_light_mode == QGLView::clmOn);
|
|
||||||
if ((camera_light_mode == QGLView::clmAuto) && cur_lights.isEmpty())
|
|
||||||
use_camlight = true;
|
|
||||||
if (use_camlight) {
|
|
||||||
cur_lights[Light::Omni] << cam_light;
|
|
||||||
cam_light->setPos(cam->pos());
|
|
||||||
}
|
|
||||||
if (scene.lights_changed) {
|
|
||||||
scene.lights_changed = false;
|
|
||||||
reloadLightsParameters(cur_lights);
|
|
||||||
}
|
|
||||||
reloadLightsPositions(cam);
|
|
||||||
|
|
||||||
/// selection
|
|
||||||
if (edit_mode) {
|
|
||||||
rend_selection.renderSelection(scene);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// solid geometry pass
|
|
||||||
fbo_ds.bind();
|
|
||||||
glEnableDepth();
|
|
||||||
glClearFramebuffer();
|
|
||||||
if (bindShader(srGeometryPass, &prog)) {
|
|
||||||
setUniformCamera(prog, cam);
|
|
||||||
textures_empty.bind(f, tarEmpty);
|
|
||||||
textures_maps .bind(f, tarMaps );
|
|
||||||
renderObjects(scene, rpSolid);
|
|
||||||
}
|
|
||||||
fbo_ds.release();
|
|
||||||
|
|
||||||
/// lighting passes
|
|
||||||
renderLight(obrSolidOmni, scene.geometries_used[rpSolid].isEmpty());
|
|
||||||
|
|
||||||
/// transparent geometry pass
|
|
||||||
fbo_ds.bind();
|
|
||||||
glEnableDepth();
|
|
||||||
glClearFramebuffer(Qt::black, false);
|
|
||||||
if (bindShader(srGeometryPass, &prog)) {
|
|
||||||
renderObjects(scene, rpTransparent);
|
|
||||||
}
|
|
||||||
fbo_ds.release();
|
|
||||||
|
|
||||||
/// lighting passes
|
|
||||||
renderLight(obrTransparentOmni, scene.geometries_used[rpTransparent].isEmpty());
|
|
||||||
|
|
||||||
/// blending layers
|
|
||||||
if (bindShader(srFinalPass, &prog)) {
|
|
||||||
fbo_out.bindColorTexture(obrSolidOmni , 1);
|
|
||||||
fbo_out.bindColorTexture(obrSolidSpot , 2);
|
|
||||||
fbo_out.bindColorTexture(obrTransparentOmni, 3);
|
|
||||||
fbo_out.bindColorTexture(obrTransparentSpot, 4);
|
|
||||||
fbo_out.setWriteBuffer(obrSum);
|
|
||||||
renderQuad(prog, quad);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// tonemapping
|
|
||||||
if (tone_proc.process())
|
|
||||||
fbo_out.bind();
|
|
||||||
if (bindShader(srTonemapPass, &prog)) {
|
|
||||||
prog->setUniformValue("gamma", gamma_);
|
|
||||||
prog->setUniformValue("frame_max", tone_proc.frameMax());
|
|
||||||
fbo_out.bindColorTexture(obrSum, 0);
|
|
||||||
fbo_out.setWriteBuffer(obrTonemap);
|
|
||||||
renderQuad(prog, quad);
|
|
||||||
} else
|
|
||||||
fbo_out.blit(obrSum, fbo_out.id(), obrTonemap, fbo_out.rect(), fbo_out.rect());
|
|
||||||
fbo_out.release();
|
|
||||||
|
|
||||||
/// apply hovers and selection frame
|
|
||||||
if (edit_mode) {
|
|
||||||
rend_selection.drawSelection(fbo_out, obrTonemap);
|
|
||||||
rend_service.renderService();
|
|
||||||
} else {
|
|
||||||
fbo_out.blit(obrTonemap, 0, 0, fbo_out.rect(), QRect(QPoint(), view->size()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Renderer::setCameraLightMode(int m) {
|
|
||||||
camera_light_mode = m;
|
|
||||||
view->scene()->setLightsChanged();
|
|
||||||
}
|
|
||||||
130
renderer.h
130
renderer.h
@@ -1,130 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL Renderer
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef RENDERER_H
|
|
||||||
#define RENDERER_H
|
|
||||||
|
|
||||||
#include "renderer_base.h"
|
|
||||||
#include "renderer_material.h"
|
|
||||||
#include "renderer_service.h"
|
|
||||||
#include "renderer_selection.h"
|
|
||||||
#include "tonemapping_proc.h"
|
|
||||||
#include "glcubemap.h"
|
|
||||||
#include <QQueue>
|
|
||||||
|
|
||||||
|
|
||||||
class Renderer: public RendererBase {
|
|
||||||
friend class QGLView;
|
|
||||||
friend class MouseController;
|
|
||||||
friend class RendererMaterial;
|
|
||||||
friend class RendererService;
|
|
||||||
friend class RendererSelection;
|
|
||||||
friend class TonemappingProc;
|
|
||||||
enum ShaderRole {
|
|
||||||
// Selection
|
|
||||||
srSelectionFill,
|
|
||||||
srSelectionHalo,
|
|
||||||
srSelectionApply,
|
|
||||||
srSelectionFrame,
|
|
||||||
|
|
||||||
// Service
|
|
||||||
srServiceFill,
|
|
||||||
srServiceFrame,
|
|
||||||
srServiceLine,
|
|
||||||
|
|
||||||
// Deferred shading
|
|
||||||
srGeometryPass,
|
|
||||||
srLightOmniPass,
|
|
||||||
srLightSpotPass,
|
|
||||||
srFinalPass,
|
|
||||||
srTonemapPass,
|
|
||||||
};
|
|
||||||
enum DeferredBufferRole {
|
|
||||||
dbrDiffuse,
|
|
||||||
dbrNormalZ,
|
|
||||||
dbrSpecularReflect,
|
|
||||||
dbrEmissionRough,
|
|
||||||
dbrSpeedBitangXY,
|
|
||||||
|
|
||||||
dbrBuffersCount,
|
|
||||||
};
|
|
||||||
enum OutBufferRole {
|
|
||||||
obrTonemap,
|
|
||||||
obrSum,
|
|
||||||
obrSolidOmni,
|
|
||||||
obrSolidSpot,
|
|
||||||
obrTransparentOmni,
|
|
||||||
obrTransparentSpot,
|
|
||||||
|
|
||||||
obrBuffersCount,
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
Renderer(QGLView * view_);
|
|
||||||
virtual ~Renderer();
|
|
||||||
|
|
||||||
void init(int width, int height);
|
|
||||||
void resize(int width, int height);
|
|
||||||
void reloadShaders();
|
|
||||||
void renderScene();
|
|
||||||
void setCameraLightMode(int m);
|
|
||||||
int cameraLightMode() const {return camera_light_mode;}
|
|
||||||
|
|
||||||
QImage materialThumbnail(Material * m) {return rend_mat.materialThumbnail(m);}
|
|
||||||
void recreateMaterialThumbnails(bool force_all = false) {rend_mat.recreateMaterialThumbnails(force_all);}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void fillObjectsBuffer(const ObjectBaseList & ol, RenderPass pass);
|
|
||||||
void reloadObjects();
|
|
||||||
void renderObjects(Scene & scene, RenderPass pass);
|
|
||||||
void renderLight(int first_wr_buff, bool clear_only);
|
|
||||||
|
|
||||||
bool bindShader(ShaderRole role, QOpenGLShaderProgram ** ret = 0);
|
|
||||||
bool bindShader(QOpenGLShaderProgram * sp);
|
|
||||||
void initShaders();
|
|
||||||
void releaseShader();
|
|
||||||
|
|
||||||
private:
|
|
||||||
float gamma_;
|
|
||||||
int camera_light_mode;
|
|
||||||
bool edit_mode, need_init_shaders, need_render_sum;
|
|
||||||
Framebuffer fbo_ds, fbo_out;
|
|
||||||
QMap<ShaderRole, QString> shader_files;
|
|
||||||
QMap<ShaderRole, QStringList> shader_defines;
|
|
||||||
QMap<ShaderRole, QOpenGLShaderProgram*> shaders;
|
|
||||||
QOpenGLShaderProgram * shader_fxaa;
|
|
||||||
|
|
||||||
RendererMaterial rend_mat;
|
|
||||||
RendererService rend_service;
|
|
||||||
RendererSelection rend_selection;
|
|
||||||
TonemappingProc tone_proc;
|
|
||||||
|
|
||||||
Mesh * quad;
|
|
||||||
Light * cam_light;
|
|
||||||
CubeTexture tex_env;
|
|
||||||
|
|
||||||
QPoint mouse_pos;
|
|
||||||
QRect mouse_rect;
|
|
||||||
QMatrix4x4 prev_view, prev_proj;
|
|
||||||
QMatrix3x3 nm;
|
|
||||||
QVector4D corner_dirs[4];
|
|
||||||
QVector<QVector3D> hcontent;
|
|
||||||
QMap<int, QList<Light*>> cur_lights;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // RENDERER_H
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL RendererBase
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef RENDERER_BASE_H
|
|
||||||
#define RENDERER_BASE_H
|
|
||||||
|
|
||||||
#include "glshaders_types.h"
|
|
||||||
#include "gltexturearray.h"
|
|
||||||
#include "glbuffer.h"
|
|
||||||
|
|
||||||
|
|
||||||
class RendererBase {
|
|
||||||
public:
|
|
||||||
RendererBase(QGLView * view_);
|
|
||||||
~RendererBase();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void initTextureArrays();
|
|
||||||
void initUniformBuffer (QOpenGLShaderProgram * prog, Buffer * buffer, int bind_point, const char * blockName);
|
|
||||||
void setUniformHalo (QOpenGLShaderProgram * prog, const char * type, QColor color, float fill);
|
|
||||||
void setUniformMaps (QOpenGLShaderProgram * prog);
|
|
||||||
void setUniformCamera (QOpenGLShaderProgram * prog, Camera * cam, bool matrices = true, QSize viewport = QSize());
|
|
||||||
void setUniformViewCorners(QOpenGLShaderProgram * prog, Camera * cam, QSize viewport = QSize());
|
|
||||||
void fillSelectionsBuffer(QVector<uchar> & buffer, const ObjectBaseList & ol);
|
|
||||||
void fillSelectionsBuffer(QVector<uchar> & buffer, bool yes, int size);
|
|
||||||
void reloadMaterials(Scene & scene);
|
|
||||||
void reloadLightsParameters(const QMap<int, QList<Light*>> & lights);
|
|
||||||
void reloadLightsPositions (Camera * cam);
|
|
||||||
void markReloadTextures();
|
|
||||||
void setMapsSize(QSize sz);
|
|
||||||
void initQuad(Mesh * mesh, QMatrix4x4 mat = QMatrix4x4());
|
|
||||||
void renderQuad(QOpenGLShaderProgram * prog, Mesh * mesh, Camera * cam = 0, bool uniforms = true);
|
|
||||||
void initCoeffTextures();
|
|
||||||
void createCoeffTexture(GLuint & id, const void * data, int size, int channels = 1);
|
|
||||||
|
|
||||||
QGLView * view;
|
|
||||||
TextureManager * textures_manager;
|
|
||||||
QVector<QGLEngineShaders::Object> cur_objects_;
|
|
||||||
QVector<QGLEngineShaders::QGLMaterial> cur_materials_;
|
|
||||||
QVector<QGLEngineShaders::QGLLightParameter> cur_lights_params_;
|
|
||||||
QVector<QGLEngineShaders::QGLLightPosition> cur_lights_pos_;
|
|
||||||
Buffer buffer_materials;
|
|
||||||
Buffer buffer_lights, buffer_lights_pos;
|
|
||||||
Texture2DArray textures_empty, textures_maps;
|
|
||||||
QSize maps_size;
|
|
||||||
uint maps_hash;
|
|
||||||
GLuint tex_coeff[2];
|
|
||||||
QMap<int, int> lights_start;
|
|
||||||
QList<Light*> current_lights;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // RENDERER_BASE_H
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
QGL RendererMaterial
|
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef RENDERER_MATERIAL_H
|
|
||||||
#define RENDERER_MATERIAL_H
|
|
||||||
|
|
||||||
#include "glframebuffer.h"
|
|
||||||
#include <QQueue>
|
|
||||||
|
|
||||||
|
|
||||||
class RendererMaterial {
|
|
||||||
friend class QGLView;
|
|
||||||
public:
|
|
||||||
RendererMaterial(Renderer * r_);
|
|
||||||
virtual ~RendererMaterial();
|
|
||||||
|
|
||||||
void init(int width, int height);
|
|
||||||
void resize(int width, int height);
|
|
||||||
|
|
||||||
QImage materialThumbnail(Material * m);
|
|
||||||
void recreateMaterialThumbnails(bool force_all = false);
|
|
||||||
void renderMaterial(Material * m);
|
|
||||||
void procQueue();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Renderer * r;
|
|
||||||
Framebuffer fbo_mat_thumb;
|
|
||||||
Mesh * mat_sphere;
|
|
||||||
Camera * mat_camera;
|
|
||||||
Light * mat_light;
|
|
||||||
QMap<Material*, QImage> mat_thumbnails;
|
|
||||||
Material * last_thumb_material;
|
|
||||||
QQueue<Material*> mat_thumb_queue;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // RENDERER_MATERIAL_H
|
|
||||||
19
shaders.qrc
19
shaders.qrc
@@ -1,19 +0,0 @@
|
|||||||
<RCC>
|
|
||||||
<qresource prefix="/">
|
|
||||||
<file>shaders/ds_final.glsl</file>
|
|
||||||
<file>shaders/ds_geom.glsl</file>
|
|
||||||
<file>shaders/ds_light.glsl</file>
|
|
||||||
<file>shaders/ds_tonemap.glsl</file>
|
|
||||||
<file>shaders/fxaa.frag</file>
|
|
||||||
<file>shaders/fxaa.vert</file>
|
|
||||||
<file>shaders/fxaa_v3.h</file>
|
|
||||||
<file>shaders/selection.glsl</file>
|
|
||||||
<file>shaders/selection_apply.glsl</file>
|
|
||||||
<file>shaders/selection_frame.glsl</file>
|
|
||||||
<file>shaders/selection_halo.glsl</file>
|
|
||||||
<file>shaders/service_fill.glsl</file>
|
|
||||||
<file>shaders/service_frame.glsl</file>
|
|
||||||
<file>shaders/service_line.glsl</file>
|
|
||||||
<file>shaders/sum.glsl</file>
|
|
||||||
</qresource>
|
|
||||||
</RCC>
|
|
||||||
@@ -3,15 +3,21 @@
|
|||||||
out vec3 geom_normal;
|
out vec3 geom_normal;
|
||||||
out mat3 TBN;
|
out mat3 TBN;
|
||||||
out vec4 object_color;
|
out vec4 object_color;
|
||||||
|
out float object_flags;
|
||||||
|
|
||||||
|
const vec3 luma = vec3(0.299, 0.587, 0.114);
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
qgl_MaterialIndex = qgl_Material;
|
qgl_MaterialIndex = qgl_Material;
|
||||||
qgl_FragTexture = qgl_Texture;
|
qgl_FragTexture = qgl_getFragTexture();
|
||||||
gl_Position = qgl_ftransform();
|
|
||||||
|
|
||||||
geom_normal = normalize(qgl_Normal * qgl_getNormalMatrix());
|
geom_normal = normalize(qgl_Normal * qgl_getNormalMatrix());
|
||||||
TBN = qgl_getTangentMatrix() * mat3(qgl_Tangent, qgl_Bitangent, qgl_Normal);
|
TBN = qgl_getTangentMatrix() * mat3(qgl_Tangent, qgl_Bitangent, qgl_Normal);
|
||||||
object_color = qgl_ObjectColor;
|
object_color = qgl_ObjectColor;
|
||||||
|
object_flags = qgl_ObjectFlags;
|
||||||
|
|
||||||
|
float height = dot(qgl_materialTexture(QGL_MAP_RELIEF, qgl_FragTexture, vec4(0.)).rgb, luma);
|
||||||
|
gl_Position = qgl_ViewProjMatrix * (qgl_ModelMatrix * (vec4(qgl_Vertex + qgl_Normal * height, 1.)));//qgl_ftransform();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -20,9 +26,11 @@ void main(void) {
|
|||||||
in vec3 geom_normal;
|
in vec3 geom_normal;
|
||||||
in mat3 TBN;
|
in mat3 TBN;
|
||||||
in vec4 object_color;
|
in vec4 object_color;
|
||||||
|
in float object_flags;
|
||||||
|
|
||||||
uniform vec2 dt;
|
uniform vec2 dt;
|
||||||
uniform float z_near;
|
uniform float z_near;
|
||||||
|
uniform int out_index_normal = dbrNormalZ, out_index_metal = dbrMetalRoughReflectFlags;
|
||||||
|
|
||||||
const vec3 luma = vec3(0.299, 0.587, 0.114);
|
const vec3 luma = vec3(0.299, 0.587, 0.114);
|
||||||
const float _pe = 2.4e-7;
|
const float _pe = 2.4e-7;
|
||||||
@@ -30,9 +38,13 @@ const float _pe = 2.4e-7;
|
|||||||
void main(void) {
|
void main(void) {
|
||||||
vec2 tc = qgl_FragTexture.xy;
|
vec2 tc = qgl_FragTexture.xy;
|
||||||
|
|
||||||
vec4 diffuse = qgl_materialTexture(QGL_MAP_DIFFUSE, tc, vec4(0)) * object_color;
|
vec4 diffuse = qgl_materialTexture(QGL_MAP_DIFFUSE, tc, vec4(0.)) * object_color;
|
||||||
diffuse.rgb *= qgl_material[qgl_MaterialIndex].color_diffuse.rgb;
|
diffuse.rgb *= qgl_material[qgl_MaterialIndex].color_diffuse.rgb;
|
||||||
diffuse.a *= (1.f - qgl_material[qgl_MaterialIndex].transparency);
|
#ifdef SOLID
|
||||||
|
if(diffuse.a < 0.5)
|
||||||
|
discard;
|
||||||
|
#endif
|
||||||
|
diffuse.a *= (1. - qgl_material[qgl_MaterialIndex].transparency);
|
||||||
|
|
||||||
vec3 normal, dn;
|
vec3 normal, dn;
|
||||||
dn = qgl_materialTexture(QGL_MAP_NORMAL, tc, -vec4(0.5, 0.5, 1., 0.)).xyz;
|
dn = qgl_materialTexture(QGL_MAP_NORMAL, tc, -vec4(0.5, 0.5, 1., 0.)).xyz;
|
||||||
@@ -42,28 +54,27 @@ void main(void) {
|
|||||||
dn *= dn_sl / (length(dn) + 1E-6);
|
dn *= dn_sl / (length(dn) + 1E-6);
|
||||||
normal = normalize(geom_normal + dn);
|
normal = normalize(geom_normal + dn);
|
||||||
|
|
||||||
float metalness = dot(qgl_materialTexture(QGL_MAP_METALNESS, tc, vec4(0)).rgb, luma);
|
float metalness = dot(qgl_materialTexture(QGL_MAP_METALNESS, tc, vec4(0.)).rgb, luma);
|
||||||
metalness = clamp(metalness, 0, 1);
|
metalness = clamp(metalness, 0, 1);
|
||||||
|
|
||||||
float roughness = dot(qgl_materialTexture(QGL_MAP_ROUGHNESS, tc, vec4(0)).rgb, luma);
|
float roughness = dot(qgl_materialTexture(QGL_MAP_ROUGHNESS, tc, vec4(0.)).rgb, luma);
|
||||||
roughness = clamp(roughness, 0.0001, 0.9999);
|
roughness = clamp(roughness, 0.0001, 0.9999);
|
||||||
|
|
||||||
float reflectivity = clamp(qgl_material[qgl_MaterialIndex].reflectivity, 0., 1.);
|
float reflectivity = clamp(qgl_material[qgl_MaterialIndex].reflectivity, 0., 1.);
|
||||||
|
|
||||||
vec4 emission = qgl_materialTexture(QGL_MAP_EMISSION, tc, vec4(0));
|
vec4 emission = qgl_materialTexture(QGL_MAP_EMISSION, tc, vec4(0.));
|
||||||
emission *= qgl_material[qgl_MaterialIndex].color_emission;
|
emission *= qgl_material[qgl_MaterialIndex].color_emission;
|
||||||
|
|
||||||
float height = dot(qgl_materialTexture(QGL_MAP_RELIEF, tc, vec4(0)).rgb, luma);
|
|
||||||
|
|
||||||
float z = gl_FragCoord.z;
|
float z = gl_FragCoord.z;
|
||||||
z = z + z - 1;
|
z = z + z - 1.;
|
||||||
z = ((_pe - 2.) * z_near) / (z + _pe - 1.); // infinite depth
|
z = ((_pe - 2.) * z_near) / (z + _pe - 1.); // infinite depth
|
||||||
|
|
||||||
qgl_FragData[0] = vec4(diffuse .rgba);
|
qgl_FragData[dbrDiffuse ] = vec4(diffuse .rgba);
|
||||||
qgl_FragData[1] = vec4(normal .xyz, z);
|
qgl_FragData[out_index_normal] = vec4(normal .xyz, z);
|
||||||
qgl_FragData[2] = vec4(metalness, roughness, reflectivity, 0);
|
qgl_FragData[out_index_metal ] = vec4(metalness, roughness, reflectivity, object_flags);
|
||||||
qgl_FragData[3] = vec4(emission.rgb, 0/*bn.x*/);
|
qgl_FragData[dbrEmission ] = vec4(emission.rgb, 0./*bn.x*/);
|
||||||
//qgl_FragData[4] = vec4(speed.xy, bn.yz);
|
//qgl_FragData[dbrSpeedBitangXY] = vec4(speed.xy, bn.yz);
|
||||||
|
qgl_FragData[dbrGeoNormal ] = vec4(normalize(geom_normal), 1.);
|
||||||
|
|
||||||
//ivec2 itc = ivec2(gl_FragCoord.xy);
|
//ivec2 itc = ivec2(gl_FragCoord.xy);
|
||||||
//qgl_FragData[0].rgb = vec3(dot(n,vec3(0,0,1)));
|
//qgl_FragData[0].rgb = vec3(dot(n,vec3(0,0,1)));
|
||||||
|
|||||||
@@ -18,22 +18,143 @@ in vec3 view_dir, world_dir;
|
|||||||
|
|
||||||
uniform vec2 dt;
|
uniform vec2 dt;
|
||||||
uniform float z_near;
|
uniform float z_near;
|
||||||
uniform sampler2D tex_coeffs[2];
|
uniform sampler2D tex_coeff_brdf, tex_noise;
|
||||||
uniform sampler2D tex_0, tex_1, tex_2, tex_3, tex_4;
|
uniform sampler2D tex_0, tex_1, tex_2, tex_3, tex_4, tex_5, tex_sh;
|
||||||
|
//uniform sampler2DShadow tex_shadow[16];
|
||||||
|
#ifdef SHADOWS
|
||||||
|
uniform vec2 shadow_size;
|
||||||
|
uniform sampler2DArrayShadow tex_shadows_cone;
|
||||||
|
uniform sampler2DArray tex_depths_cone;
|
||||||
|
uniform samplerCubeArrayShadow tex_shadows_omni;
|
||||||
|
uniform samplerCubeArray tex_depths_omni;
|
||||||
|
uniform bool soft_shadows_enabled = false;
|
||||||
|
uniform float soft_shadows_quality = 1.;
|
||||||
|
uniform int soft_shadows_samples = 16, noise_size = 64;
|
||||||
|
#endif
|
||||||
uniform samplerCube tex_env;
|
uniform samplerCube tex_env;
|
||||||
uniform int lights_start, lights_count;
|
uniform int lights_start, lights_count;
|
||||||
|
uniform vec4 fog_color = vec4(0.5, 0.5, 0.5, 1.);
|
||||||
uniform vec4 fog_color = vec4(0.5, 0.5, 0.5, 1);
|
uniform float fog_decay = 10., fog_density = 0.;
|
||||||
uniform float fog_decay = 10, fog_density = 0;
|
|
||||||
uniform mat3 view_mat;
|
uniform mat3 view_mat;
|
||||||
|
const float _pe = 2.4e-7;
|
||||||
|
|
||||||
const vec3 luma = vec3(0.299, 0.587, 0.114);
|
const vec3 luma = vec3(0.299, 0.587, 0.114);
|
||||||
const float _min_rough = 1.e-8, max_lod = 8;
|
const float _min_rough = 1.e-8, max_lod = 8.;
|
||||||
|
const float PI = 3.1416;
|
||||||
|
|
||||||
|
ivec2 tc;
|
||||||
vec4 pos, lpos, shp;
|
vec4 pos, lpos, shp;
|
||||||
vec3 li, si, ldir, halfV, bn, bn2, lwdir;
|
vec3 li, si, ldir, halfV, bn, bn2, lwdir;
|
||||||
//vec3 vds, vds2;
|
vec3 normal, geom_normal, vds, vds2;
|
||||||
float rough_diff, rough_spec, dist, NdotL, NdotH, spot, ldist, diff, spec, sdist, shadow;
|
float rough_diff, rough_spec, dist, NdotL, NdotH, spot, ldist, diff, spec, sdist;
|
||||||
|
uint flags;
|
||||||
|
|
||||||
|
|
||||||
|
vec4 mapScreenToShadow(in int light_index, in vec3 offset) {
|
||||||
|
vec4 shp = qgl_light_position[light_index].shadow_matrix * (pos + vec4(offset, 0));
|
||||||
|
//shp.z += 0.5;
|
||||||
|
return shp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef SHADOWS
|
||||||
|
#ifdef SPOT
|
||||||
|
|
||||||
|
float getShadowCone(in vec3 uvz, in int layer) {
|
||||||
|
/*vec2 uvpix = uvz.xy * shadow_size + vec2(0.5f);
|
||||||
|
vec2 uvp = fract(uvpix), iuvp = vec2(1.f) - uvp;
|
||||||
|
vec4 gt = textureGather(tex_shadows_cone, vec3(floor(uvpix.xy) / shadow_size, layer), 0);
|
||||||
|
vec4 uvv;
|
||||||
|
uvv[0] = iuvp.x * uvp.y;
|
||||||
|
uvv[1] = uvp.x * uvp.y;
|
||||||
|
uvv[2] = uvp.x * iuvp.y;
|
||||||
|
uvv[3] = iuvp.x * iuvp.y;
|
||||||
|
shadow_dz = max(max(uvz.z - gt[0], uvz.z - gt[1]), max(uvz.z - gt[2], uvz.z - gt[3]));
|
||||||
|
return clamp(dot(step(vec4(uvz.z), gt), uvv), 0, 1);*/
|
||||||
|
float z = 1. - 1. / (uvz.z - z_near + 1.);
|
||||||
|
return texture(tex_shadows_cone, vec4(uvz.xy, layer, z));
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
float getShadowOmni(in vec4 uvwz, in int layer) {
|
||||||
|
/*vec3 uvpix = uvwz.xyz * vec3(shadow_size.x) + vec3(0.5f);
|
||||||
|
vec3 uvp = fract(uvpix), iuvp = vec3(1.f) - uvp;
|
||||||
|
vec4 gt = textureGather(tex_shadows_omni, vec4(floor(uvpix.xyz) / vec3(shadow_size.x), layer), 0);
|
||||||
|
vec4 uvv;
|
||||||
|
uvv[0] = iuvp.y * uvp.z;
|
||||||
|
uvv[1] = uvp.y * uvp.z;
|
||||||
|
uvv[2] = uvp.y * iuvp.z;
|
||||||
|
uvv[3] = iuvp.y * iuvp.z;
|
||||||
|
return clamp(dot(step(vec4(uvwz.w), gt), uvv), 0, 1);*/
|
||||||
|
float d = 1. - 1. / (uvwz.w - z_near + 1.);
|
||||||
|
return texture(tex_shadows_omni, vec4(uvwz.xyz, layer), d);
|
||||||
|
//return step(uvwz.w, gt[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
uint hash(uint x) {
|
||||||
|
x += (x << 10u);
|
||||||
|
x ^= (x >> 6u);
|
||||||
|
x += (x << 3u);
|
||||||
|
x ^= (x >> 11u);
|
||||||
|
x += (x << 15u);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
uint hash( uvec2 v ) { return hash( v.x ^ hash(v.y) ); }
|
||||||
|
uint hash( uvec3 v ) { return hash( v.x ^ hash(v.y) ^ hash(v.z) ); }
|
||||||
|
uint hash( uvec4 v ) { return hash( v.x ^ hash(v.y) ^ hash(v.z) ^ hash(v.w) ); }
|
||||||
|
float floatConstruct( uint m ) {
|
||||||
|
const uint ieeeMantissa = 0x007FFFFFu; // binary32 mantissa bitmask
|
||||||
|
const uint ieeeOne = 0x3F800000u; // 1.0 in IEEE binary32
|
||||||
|
|
||||||
|
m &= ieeeMantissa; // Keep only mantissa bits (fractional part)
|
||||||
|
m |= ieeeOne; // Add fractional part to 1.0
|
||||||
|
|
||||||
|
float f = uintBitsToFloat( m ); // Range [1:2]
|
||||||
|
return f - 1.; // Range [0:1]
|
||||||
|
}
|
||||||
|
float random( float x ) { return floatConstruct(hash(floatBitsToUint(x))); }
|
||||||
|
float random( vec2 v ) { return floatConstruct(hash(floatBitsToUint(v))); }
|
||||||
|
float random( vec3 v ) { return floatConstruct(hash(floatBitsToUint(v))); }
|
||||||
|
float random( vec4 v ) { return floatConstruct(hash(floatBitsToUint(v))); }
|
||||||
|
float random( int x ) { return floatConstruct(hash(x)); }
|
||||||
|
float random( ivec2 v ) { return floatConstruct(hash(v)); }
|
||||||
|
float random( ivec3 v ) { return floatConstruct(hash(v)); }
|
||||||
|
float random( ivec4 v ) { return floatConstruct(hash(v)); }
|
||||||
|
|
||||||
|
uvec2 noise_hash;
|
||||||
|
void noise2init(vec2 v) {
|
||||||
|
noise_hash = uvec2(hash(uint(v.x + 1)), hash(uint(v.y - 1)));
|
||||||
|
}
|
||||||
|
vec2 noise2() {
|
||||||
|
noise2init(vec2(noise_hash));
|
||||||
|
//return vec2(floatConstruct(noise_hash.x), floatConstruct(noise_hash.y)) * 2 - vec2(1.);
|
||||||
|
float r = floatConstruct(noise_hash.x);
|
||||||
|
float a = floatConstruct(noise_hash.y) * 2 * PI;
|
||||||
|
return r * vec2(cos(a), sin(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
float rand(vec2 co) {
|
||||||
|
float a = 12.9898;
|
||||||
|
float b = 78.233;
|
||||||
|
float c = 43758.5453;
|
||||||
|
float d = dot(co.xy, vec2(a, b));
|
||||||
|
float e = sin(mod(d, 3.14)) * c;
|
||||||
|
return fract(e) - 0.5;
|
||||||
|
}
|
||||||
|
#endif // SHADOWS
|
||||||
|
|
||||||
|
vec4 qgl_lightTexture(int index, vec2 coord, vec4 tex_shift) {
|
||||||
|
coord *= qgl_light_parameter[index].map.scale;
|
||||||
|
vec4 t = texture(qgl_texture_array[qgl_light_parameter[index].map.array_index],
|
||||||
|
vec3(coord, qgl_light_parameter[index].map.map_index));
|
||||||
|
t += tex_shift;
|
||||||
|
t.rgb *= qgl_light_parameter[index].map.amount + qgl_light_parameter[index].map.offset;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
void calcLight(in int index, in vec3 n, in vec3 v) {
|
void calcLight(in int index, in vec3 n, in vec3 v) {
|
||||||
lpos = qgl_light_position[index].position;
|
lpos = qgl_light_position[index].position;
|
||||||
@@ -45,42 +166,109 @@ void calcLight(in int index, in vec3 n, in vec3 v) {
|
|||||||
NdotL = max(dot(n, ldir), 1E-8);
|
NdotL = max(dot(n, ldir), 1E-8);
|
||||||
NdotH = max(dot(n, halfV), 1E-8);
|
NdotH = max(dot(n, halfV), 1E-8);
|
||||||
spot = step(1.001E-8, NdotL) * qgl_light_parameter[index].decay_intensity.w;
|
spot = step(1.001E-8, NdotL) * qgl_light_parameter[index].decay_intensity.w;
|
||||||
|
vec3 light_color = qgl_light_parameter[index].color.rgb;
|
||||||
#ifdef SPOT
|
#ifdef SPOT
|
||||||
float scos = max(dot(-ldir, qgl_light_position[index].direction.xyz), 0.);
|
float scos = max(dot(-ldir, qgl_light_position[index].direction.xyz), 0.);
|
||||||
spot *= scos * step(qgl_light_parameter[index].angles.w, scos);
|
spot *= scos * step(qgl_light_parameter[index].angles.w, scos);
|
||||||
spot *= smoothstep(qgl_light_parameter[index].angles.w, qgl_light_parameter[index].angles.y, scos);
|
spot *= smoothstep(qgl_light_parameter[index].angles.w, qgl_light_parameter[index].angles.y, scos);
|
||||||
/*//lwdir = mat3(mat_viewi) * qgl_Light[index].direction.xyz;
|
vec4 shp = mapScreenToShadow(index, vec3(0));
|
||||||
//bn = normalize(cross(lwdir, vec3(1, 0, 0)));
|
shp.xy /= shp.w;
|
||||||
//bn2 = normalize(cross(lwdir, bn));
|
vec4 light_map_pix = qgl_lightTexture(index, shp.xy, vec4(0));
|
||||||
float ds = ldist/200.;//max(abs(sdist) / 5000, 0.02);
|
light_color *= light_map_pix.rgb;
|
||||||
//spot *= clamp(1. - sdist, 0, 1);
|
spot *= light_map_pix.a;
|
||||||
vds = ds * bn.xyz;
|
|
||||||
vds2 = ds * bn2.xyz;
|
|
||||||
float shadow = getShadow(index, pos.xyz, vec3(0)) * 3.;
|
|
||||||
shadow += getShadow(index, pos.xyz, vds ) * 2.;
|
|
||||||
shadow += getShadow(index, pos.xyz, - vds ) * 2.;
|
|
||||||
shadow += getShadow(index, pos.xyz, - vds2 ) * 2.;
|
|
||||||
shadow += getShadow(index, pos.xyz, + vds2 ) * 2.;
|
|
||||||
//shadow += getShadow(index, pos.xyz, vds - vds2 ) * 1.5;
|
|
||||||
//shadow += getShadow(index, pos.xyz, vds + vds2 ) * 1.5;
|
|
||||||
//shadow += getShadow(index, pos.xyz, - vds - vds2 ) * 1.5;
|
|
||||||
//shadow += getShadow(index, pos.xyz, - vds + vds2 ) * 1.5;
|
|
||||||
//shadow += getShadow(index, pos.xyz, vds + vds );
|
|
||||||
//shadow += getShadow(index, pos.xyz, - vds - vds );
|
|
||||||
//shadow += getShadow(index, pos.xyz, - vds2 - vds2);
|
|
||||||
//shadow += getShadow(index, pos.xyz, + vds2 + vds2);
|
|
||||||
//shadow += getShadow(index, pos.xyz, vds + vds - vds2 );
|
|
||||||
//shadow += getShadow(index, pos.xyz, - vds - vds - vds2 );
|
|
||||||
//shadow += getShadow(index, pos.xyz, vds + vds + vds2 );
|
|
||||||
//shadow += getShadow(index, pos.xyz, - vds - vds + vds2 );
|
|
||||||
//shadow += getShadow(index, pos.xyz, vds - vds2 - vds2);
|
|
||||||
//shadow += getShadow(index, pos.xyz, vds + vds2 + vds2);
|
|
||||||
//shadow += getShadow(index, pos.xyz, - vds - vds2 - vds2);
|
|
||||||
//shadow += getShadow(index, pos.xyz, - vds + vds2 + vds2);
|
|
||||||
//shadow += shadow += getShadow(index, pos.xyz, vds+vds2)*10;
|
|
||||||
spot *= mix(1., shadow / 11., shadow_on);*/
|
|
||||||
#endif
|
#endif
|
||||||
vec3 dist_decay = vec3(1, ldist, ldist*ldist);
|
|
||||||
|
#ifdef SHADOWS
|
||||||
|
if (int(round(qgl_light_parameter[index].flags)) == 1 && bitfieldExtract(flags, 3, 1) == 1 && (spot > 1E-4)) {
|
||||||
|
#ifndef SPOT
|
||||||
|
vec3 odir = -(view_mat * ldir);
|
||||||
|
#endif
|
||||||
|
int layer = index - lights_start;
|
||||||
|
float shadow = 0.;
|
||||||
|
//float bias = abs(tan(PI/2.*(1 - abs(dot(normal, ldir)))) + 1) * z_near * 1;
|
||||||
|
float bias = (1. + 1. / abs(dot(geom_normal, ldir))) * z_near * 2.;
|
||||||
|
//bias = bias * bias + z_near;
|
||||||
|
|
||||||
|
if (soft_shadows_enabled) {
|
||||||
|
|
||||||
|
float depth = 1.;
|
||||||
|
#ifdef SPOT
|
||||||
|
const int gm_size = 2;
|
||||||
|
for (int i = -gm_size; i <= gm_size; ++i) {
|
||||||
|
for (int j = -gm_size; j <= gm_size; ++j) {
|
||||||
|
//depth = min(depth, textureOffset(tex_depths_cone, vec3(shp.xy, layer), ivec2(i, j)).x);
|
||||||
|
depth = min(depth, texture(tex_depths_cone, vec3(shp.xy + vec2(i, j) / vec2(shadow_size.x), layer)).x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
const int gm_size = 2;
|
||||||
|
for (int i = -gm_size; i <= gm_size; ++i) {
|
||||||
|
for (int j = -gm_size; j <= gm_size; ++j) {
|
||||||
|
for (int k = -gm_size; k <= gm_size; ++k) {
|
||||||
|
depth = min(depth, texture(tex_depths_omni, vec4(odir + vec3(i, j, k) / vec3(shadow_size.x), layer)).r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shp.z = ldist;
|
||||||
|
#endif
|
||||||
|
depth = 1. / (1. - depth) - 1. + z_near;
|
||||||
|
float dz = max(0., shp.z - depth);
|
||||||
|
float ds = qgl_light_parameter[index].size * dz / (ldist - dz);
|
||||||
|
//float ds = (ldist / 2.) / qgl_light_parameter[index].size;
|
||||||
|
float srate = abs(ds / pos.z) * 10. * soft_shadows_quality;
|
||||||
|
//qgl_FragColor.rgb = vec3(srate);
|
||||||
|
|
||||||
|
int samples = clamp(int(round(srate * float(soft_shadows_samples))), 1, soft_shadows_samples);
|
||||||
|
vds = ds * bn.xyz;
|
||||||
|
vds2 = ds * bn2.xyz;
|
||||||
|
vec2 so;
|
||||||
|
ivec2 sotc = tc;
|
||||||
|
|
||||||
|
noise2init(vec2(hash(ivec2(tc.x * 2. + 1., tc.y)), hash(ivec2(tc.x, (tc.y * 2. + 1.)))));
|
||||||
|
for (int i = 0; i < samples; ++i) {
|
||||||
|
so = noise2();
|
||||||
|
#ifdef SPOT
|
||||||
|
//vec4 nc = texelFetch(tex_noise, sotc % noise_size, 0);
|
||||||
|
//sotc += ivec2(nc.ba * 256) % noise_size;
|
||||||
|
//so = (nc.rg - vec2(0.5));
|
||||||
|
|
||||||
|
//so = vec2(rand(vec2(shp.x + i, shp.y)), rand(vec2(shp.x + i + 1, shp.y)));
|
||||||
|
|
||||||
|
vec4 shp = mapScreenToShadow(index, vds * so.x + vds2 * so.y);
|
||||||
|
shp.xy /= shp.w;
|
||||||
|
shp.z -= bias;
|
||||||
|
shadow += getShadowCone(shp.xyz, layer);
|
||||||
|
#else
|
||||||
|
//so = vec2(rand(vec2(odir.x + i, odir.y)), rand(vec2(odir.x + i + 1, odir.y)))*1.25;
|
||||||
|
|
||||||
|
vec3 old = lpos.xyz - ((pos.xyz + vec3(vds * so.x + vds2 * so.y)) * lpos.w);
|
||||||
|
odir = -(view_mat * old);
|
||||||
|
shadow += getShadowOmni(vec4(odir, length(old) - bias), layer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
spot *= min(1., 2. * shadow / samples);
|
||||||
|
//spot *= shadow / soft_shadows_samples;
|
||||||
|
//spot *= shadow / soft_shadows_samples + 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
#ifdef SPOT
|
||||||
|
shp.xy;
|
||||||
|
shp.z -= bias;
|
||||||
|
spot *= getShadowCone(shp.xyz, layer);
|
||||||
|
#else
|
||||||
|
spot *= getShadowOmni(vec4(odir, ldist - bias), layer);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
//shp.z -= bias;
|
||||||
|
//shadow += getShadowCone(shp.xyz, layer, vec2(0));
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // SHADOWS
|
||||||
|
|
||||||
|
vec3 dist_decay = vec3(1., ldist, ldist*ldist);
|
||||||
spot /= dot(qgl_light_parameter[index].decay_intensity.xyz, dist_decay);
|
spot /= dot(qgl_light_parameter[index].decay_intensity.xyz, dist_decay);
|
||||||
|
|
||||||
float NdotLs = NdotL*NdotL;
|
float NdotLs = NdotL*NdotL;
|
||||||
@@ -89,53 +277,36 @@ void calcLight(in int index, in vec3 n, in vec3 v) {
|
|||||||
float ndlc = (1. - NdotLs) / NdotLs;
|
float ndlc = (1. - NdotLs) / NdotLs;
|
||||||
diff = 2. / (1. + sqrt(1. + (1. - rough_diff) * ndlc));
|
diff = 2. / (1. + sqrt(1. + (1. - rough_diff) * ndlc));
|
||||||
//diff = texture(tex_coeffs[0], vec2(roughness, (NdotLs))).r;
|
//diff = texture(tex_coeffs[0], vec2(roughness, (NdotLs))).r;
|
||||||
li += spot * diff * qgl_light_parameter[index].color.rgb;
|
li += spot * diff * light_color;
|
||||||
|
|
||||||
ndlc = (1. - NdotHs) / NdotHs;
|
ndlc = (1. - NdotHs) / NdotHs;
|
||||||
float der = NdotHs * (rough_spec + ndlc);
|
float der = NdotHs * (rough_spec + ndlc);
|
||||||
spec = rough_spec / (der*der) / 3.1416;
|
spec = rough_spec / (der*der) / PI;
|
||||||
//spec = texture(tex_coeffs[1], vec2(roughness, (NdotHs))).r;
|
//spec = texture(tex_coeffs[1], vec2(roughness, (NdotHs))).r;
|
||||||
si += spot * spec * qgl_light_parameter[index].color.rgb;
|
si += spot * spec * light_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
float GeometrySchlickGGX(float NdotV, float roughness) {
|
|
||||||
float a = roughness;
|
|
||||||
float k = (a * a) / 2.0;
|
|
||||||
float nom = NdotV;
|
|
||||||
float denom = NdotV * (1.0 - k) + k;
|
|
||||||
return nom / denom;
|
|
||||||
}
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) {
|
|
||||||
float NdotV = max(dot(N, V), 0.0);
|
|
||||||
float NdotL = max(dot(N, L), 0.0);
|
|
||||||
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
|
||||||
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
|
||||||
return ggx1 * ggx2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
ivec2 tc = ivec2(gl_FragCoord.xy);
|
tc = ivec2(gl_FragCoord.xy);
|
||||||
vec4 v1 = texelFetch(tex_1, tc, 0);
|
vec4 v1 = texelFetch(tex_1, tc, 0);
|
||||||
float z = v1.w;
|
float z = v1.w;
|
||||||
if (z == 1.) {
|
if (z == 1.) {
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
pos.w = 1;
|
pos.w = 1.;
|
||||||
pos.xyz = view_dir * z;
|
pos.xyz = view_dir * z;
|
||||||
vec3 v = normalize(-pos.xyz);
|
vec3 v = normalize(-pos.xyz);
|
||||||
|
|
||||||
vec4 v0 = texelFetch(tex_0, tc, 0),
|
vec4 v0 = texelFetch(tex_0, tc, 0),
|
||||||
v2 = texelFetch(tex_2, tc, 0),
|
v2 = texelFetch(tex_2, tc, 0),
|
||||||
v3 = texelFetch(tex_3, tc, 0),
|
v3 = texelFetch(tex_3, tc, 0),
|
||||||
v4 = texelFetch(tex_4, tc, 0);
|
v4 = texelFetch(tex_4, tc, 0),
|
||||||
|
v5 = texelFetch(tex_5, tc, 0);
|
||||||
|
|
||||||
vec3 diffuse = v0.rgb;
|
vec3 diffuse = v0.rgb;
|
||||||
vec3 normal = v1.xyz;
|
normal = v1.xyz;
|
||||||
|
geom_normal = v5.xyz;
|
||||||
vec3 emission = v3.rgb;
|
vec3 emission = v3.rgb;
|
||||||
float alpha = v0.a;
|
float alpha = v0.a;
|
||||||
float metalness = v2.r;
|
float metalness = v2.r;
|
||||||
@@ -143,35 +314,79 @@ void main(void) {
|
|||||||
float reflectivity = v2.b;
|
float reflectivity = v2.b;
|
||||||
float NdotV = dot(normal, v);
|
float NdotV = dot(normal, v);
|
||||||
float roughness3 = roughness*roughness*roughness;
|
float roughness3 = roughness*roughness*roughness;
|
||||||
//bn = normalize(vec3(v3.w, v4.zw));
|
bn = normalize(cross(normal, vec3(1.,0.,0.)) + cross(normal, vec3(0.,1.,0.)));
|
||||||
//bn2 = normalize(cross(n, bn));
|
bn2 = normalize(cross(normal, bn));
|
||||||
|
bn = cross(normal, bn2);
|
||||||
rough_diff = max(roughness, _min_rough);
|
rough_diff = max(roughness, _min_rough);
|
||||||
rough_spec = max(roughness3, _min_rough);
|
rough_spec = max(roughness3, _min_rough);
|
||||||
float shlick = clamp(metalness + (1 - metalness) * pow(1 - NdotV, 5), 0, 1);
|
float shlick = clamp(metalness + (1. - metalness) * pow(1. - NdotV, 5.), 0., 1.);
|
||||||
|
flags = uint(round(v2.w));
|
||||||
|
|
||||||
|
//qgl_FragColor.rgba = vec4(0);
|
||||||
|
|
||||||
li = vec3(0.);//qgl_AmbientLight.color.rgb * qgl_AmbientLight.intensity;
|
li = vec3(0.);//qgl_AmbientLight.color.rgb * qgl_AmbientLight.intensity;
|
||||||
si = vec3(0.);
|
si = vec3(0.);
|
||||||
for (int i = 0; i < lights_count; ++i)
|
if (bitfieldExtract(flags, 0, 1) == 1) {
|
||||||
calcLight(lights_start + i, normal, v);
|
for (int i = 0; i < lights_count; ++i)
|
||||||
|
calcLight(lights_start + i, normal, v);
|
||||||
|
} else {
|
||||||
|
li = vec3(1.);
|
||||||
|
}
|
||||||
si *= shlick;
|
si *= shlick;
|
||||||
li *= (1 - shlick);
|
li *= (1. - shlick);
|
||||||
alpha = min(1, alpha * (1 + shlick));
|
alpha = min(1., alpha * (1. + shlick));
|
||||||
|
|
||||||
vec2 brdf = texture(tex_coeffs[0], vec2(NdotV*0.99, roughness*0.995)).rg;
|
vec2 brdf = texture(tex_coeff_brdf, vec2(NdotV*0.99, roughness*0.995)).rg;
|
||||||
float env_spec = shlick * brdf.x + brdf.y;
|
float env_spec = shlick * brdf.x + brdf.y;
|
||||||
vec3 spec_col = mix(vec3(1), diffuse, metalness);
|
vec3 spec_col = mix(vec3(1.), diffuse, metalness);
|
||||||
vec3 env_dir = view_mat * reflect(-v, normal);
|
vec3 env_dir = view_mat * reflect(-v, normal);
|
||||||
vec3 env_col = textureLod(tex_env, env_dir, sqrt(roughness) * max_lod).rgb * spec_col;
|
vec3 env_col = textureLod(tex_env, env_dir, sqrt(roughness) * max_lod).rgb * spec_col;
|
||||||
|
|
||||||
vec3 res_col = max(vec3(0), li * diffuse + si * spec_col + emission);
|
vec3 res_col = max(vec3(0.), li * diffuse + si * spec_col + emission);
|
||||||
res_col = mix(res_col, env_col, env_spec * reflectivity);
|
res_col = mix(res_col, env_col, env_spec * reflectivity);
|
||||||
|
|
||||||
float plen = length(pos.xyz);
|
if (bitfieldExtract(flags, 1, 1) == 1) {
|
||||||
float fog = 1 - exp(-plen / fog_decay);
|
float plen = length(pos.xyz);
|
||||||
fog = clamp(fog * fog_color.a * fog_density, 0, 1);
|
float fog = 1. - exp(-plen / fog_decay);
|
||||||
res_col = mix(res_col, fog_color.rgb, fog);
|
fog = clamp(fog * fog_color.a * fog_density, 0., 1.);
|
||||||
|
res_col = mix(res_col, fog_color.rgb, fog);
|
||||||
|
}
|
||||||
|
|
||||||
qgl_FragColor = vec4(res_col, alpha);
|
qgl_FragColor = vec4(res_col, alpha);
|
||||||
|
//qgl_FragColor = vec4(diffuse.rgb, 0.25);
|
||||||
|
//qgl_FragColor.a = alpha;
|
||||||
|
//qgl_FragColor.rgb = vec3(geom_normal.rgb);
|
||||||
|
//qgl_FragColor.rgba = vec4(vec3(0), 0.5);
|
||||||
|
|
||||||
|
#ifdef SPOT
|
||||||
|
//vec4 shp = mapScreenToShadow(0, vec3(0));
|
||||||
|
//shp.xy /= shp.w;
|
||||||
|
//float depth = texture(tex_depths_cone, vec3(shp.xy, 0)).r;
|
||||||
|
////depth = 1 / (1 - depth) - 1 + z_near;
|
||||||
|
//float dz = max(0, shp.z - depth);
|
||||||
|
//shp.z -= bias;
|
||||||
|
//for (int xi = -2; xi <= 2; ++xi) {
|
||||||
|
// for (int yi = -2; yi <= 2; ++yi) {
|
||||||
|
//qgl_FragColor.rgb = vec3(step(shp.z, texture(tex_shadows_cone, vec3(shp.xy, 0)).r));
|
||||||
|
//qgl_FragColor.r = texture(tex_shadows_cone, vec3(0)).r;
|
||||||
|
//qgl_FragColor.rgb = vec3(abs(depth) + 1);
|
||||||
|
//float _d = texture(tex_depths_cone, vec3(shp.xy, 0)).r;
|
||||||
|
//_d = 1 / (1 - _d) - 1 + z_near;
|
||||||
|
//qgl_FragColor.rgb = vec3(texelFetch(tex_noise, tc % noise_size, 0).b);//vec4(res_col, alpha);
|
||||||
|
|
||||||
|
//shp.z += 0.095;
|
||||||
|
//qgl_FragColor.rgb = vec3(texture(tex_sh, shp.xy).rgb);
|
||||||
|
//qgl_FragColor.rgb = vec3(textureProj(tex_shadow[0], shp));
|
||||||
|
//vec4 rp = qgl_ViewProjMatrix*vec4(qgl_FragTexture.xy,z,1);
|
||||||
|
//qgl_FragColor.rgb = vec3(texture(tex_shadows_cone, vec3(gl_FragCoord.xy/1000, 0)).r);
|
||||||
|
#else
|
||||||
|
//vec3 odir = -(view_mat * ldir);
|
||||||
|
//float otex = texture(tex_shadows_omni, vec4(odir, 0), 0.8);
|
||||||
|
//qgl_FragColor.rgb = vec3(otex);
|
||||||
|
//qgl_FragColor.rgb = vec3(ldist/50);
|
||||||
|
//qgl_FragColor.rgb = vec3(abs(otex - ldist) * 1.);
|
||||||
|
//qgl_FragColor.rgb = vec3(tan((1-abs(dot(view_mat*normal, odir)))));
|
||||||
|
#endif
|
||||||
|
|
||||||
//vec3 specular = prefilteredColor * (F * envBRDF.x + envBRDF.y);
|
//vec3 specular = prefilteredColor * (F * envBRDF.x + envBRDF.y);
|
||||||
//qgl_FragColor.rgb = vec3(shlick * brdf.x + brdf.y);
|
//qgl_FragColor.rgb = vec3(shlick * brdf.x + brdf.y);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ void main(void) {
|
|||||||
float l = dot(res, luma) * 0.75;
|
float l = dot(res, luma) * 0.75;
|
||||||
float g = gamma / frame_max;
|
float g = gamma / frame_max;
|
||||||
res /= l;
|
res /= l;
|
||||||
l = 1 - exp(-l*g);
|
l = 1. - exp(-l*g);
|
||||||
res *= l;
|
res = max(vec3(0.), res * l);
|
||||||
qgl_FragColor = vec4(res, dot(res, luma));
|
qgl_FragColor = vec4(res, dot(res, luma));
|
||||||
}
|
}
|
||||||
|
|||||||
50
shaders/shadow.glsl
Normal file
50
shaders/shadow.glsl
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
// vert //
|
||||||
|
|
||||||
|
flat out uint object_flags;
|
||||||
|
out float distance;
|
||||||
|
out vec4 pos;
|
||||||
|
|
||||||
|
const vec3 luma = vec3(0.299, 0.587, 0.114);
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
object_flags = qgl_ObjectFlags;
|
||||||
|
if (bitfieldExtract(object_flags, 2, 1) == 0)
|
||||||
|
return;
|
||||||
|
qgl_MaterialIndex = qgl_Material;
|
||||||
|
qgl_FragTexture = qgl_getFragTexture();
|
||||||
|
float height = dot(qgl_materialTexture(QGL_MAP_RELIEF, qgl_FragTexture, vec4(0.)).rgb, luma);
|
||||||
|
pos = qgl_ViewProjMatrix * (qgl_ModelMatrix * (vec4(qgl_Vertex + qgl_Normal * height, 1.)));//qgl_ftransform();
|
||||||
|
gl_Position = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// frag //
|
||||||
|
|
||||||
|
flat in uint object_flags;
|
||||||
|
in float distance;
|
||||||
|
in vec4 pos;
|
||||||
|
|
||||||
|
float z_near = 0.1f;
|
||||||
|
const float _pe = 2.4e-7;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
if (bitfieldExtract(object_flags, 2, 1) == 0)
|
||||||
|
discard;
|
||||||
|
vec4 diffuse = qgl_materialTexture(QGL_MAP_DIFFUSE, qgl_FragTexture.xy, vec4(0.f));
|
||||||
|
if(diffuse.a < 0.5f)
|
||||||
|
discard;
|
||||||
|
|
||||||
|
//float z = gl_FragCoord.z;
|
||||||
|
//z = z + z - 1;
|
||||||
|
//z = ((_pe - 2.) * z_near) / (z + z + _pe - 2.); // infinite depth
|
||||||
|
|
||||||
|
#ifdef OMNI
|
||||||
|
float z = length(pos.xyz);
|
||||||
|
#else
|
||||||
|
float z = pos.z;
|
||||||
|
#endif
|
||||||
|
z = 1.f - 1.f / (z - z_near + 1.f);
|
||||||
|
gl_FragDepth = z;
|
||||||
|
qgl_FragData[0].r = z;
|
||||||
|
//qgl_FragData[0].r = length(vec3(pos.xy, z));//1/gl_FragCoord.w;
|
||||||
|
}
|
||||||
9
src/CMakeLists.txt
Normal file
9
src/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#if (NOT DEFINED ANDROID_PLATFORM)
|
||||||
|
# if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/plugin")
|
||||||
|
# #add_subdirectory(plugin)
|
||||||
|
# endif()
|
||||||
|
#endif()
|
||||||
|
foreach (_d "core" "widgets" "qglview_test") # "plugin")
|
||||||
|
add_subdirectory("${_d}")
|
||||||
|
endforeach()
|
||||||
|
shstk_copy_to_parent()
|
||||||
36
src/core/CMakeLists.txt
Normal file
36
src/core/CMakeLists.txt
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
project(qglengine_core)
|
||||||
|
if (POLICY CMP0017)
|
||||||
|
cmake_policy(SET CMP0017 NEW)
|
||||||
|
endif()
|
||||||
|
qad_find_qt(Core Gui OpenGL OpenGLWidgets Xml)
|
||||||
|
find_package(OpenGL REQUIRED)
|
||||||
|
qad_sources(SRC)
|
||||||
|
set(_includes "${_qglengine_root_build}")
|
||||||
|
foreach (_d "formats" "core" "scene" "render" "view")
|
||||||
|
qad_sources(FSRC DIR "${_d}")
|
||||||
|
list(APPEND SRC ${FSRC})
|
||||||
|
list(APPEND _includes "${CMAKE_CURRENT_SOURCE_DIR}/${_d}")
|
||||||
|
endforeach()
|
||||||
|
qad_wrap(${SRC} HDRS out_HDR CPPS out_CPP QMS out_QM)
|
||||||
|
file(GLOB PHS "*_p.h")
|
||||||
|
list(REMOVE_ITEM out_HDR "${PHS}")
|
||||||
|
import_version(${PROJECT_NAME} QGLEngine)
|
||||||
|
set_deploy_property(${PROJECT_NAME} ${QGLEngine_LIB_TYPE}
|
||||||
|
LABEL "QGLEngine core library"
|
||||||
|
FULLNAME "${QGLEngine_DOMAIN}.qglengine_core"
|
||||||
|
COMPANY "${QGLEngine_COMPANY}"
|
||||||
|
INFO "QGLEngine core library")
|
||||||
|
make_rc(${PROJECT_NAME} _RC)
|
||||||
|
pip_code_model(CCM "render/renderer.h" OPTIONS "-DQGLENGINE_CORE_EXPORT" "-Es")
|
||||||
|
qad_add_library(${PROJECT_NAME} ${QGLEngine_LIB_TYPE} out_CPP ${_RC} ${CCM})
|
||||||
|
qad_generate_export_header(${PROJECT_NAME})
|
||||||
|
list(APPEND out_HDR "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_export.h")
|
||||||
|
qad_target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" ${_includes})
|
||||||
|
qad_target_link_libraries(${PROJECT_NAME} QAD::Widgets QAD::PIQtUtils assimp ${OPENGL_LIBRARIES})
|
||||||
|
message(STATUS "Building QGLEngine version ${QGLEngine_VERSION} (${QGLEngine_LIB_TYPE_MSG}) for ${QtVersions}")
|
||||||
|
|
||||||
|
list(APPEND QT_MULTILIB_LIST ${PROJECT_NAME})
|
||||||
|
shstk_copy_to_parent()
|
||||||
|
#message(STATUS "Building ${PROJECT_NAME}")
|
||||||
|
shstk_qad_install("qglengine" FALSE "${PROJECT_NAME}" "${out_HDR}" "out_QM")
|
||||||
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
@@ -1,36 +1,36 @@
|
|||||||
/*
|
/*
|
||||||
QGL Buffer
|
QGL Buffer
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU Lesser General Public License for more details.
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define GL_GLEXT_PROTOTYPES
|
#define GL_GLEXT_PROTOTYPES
|
||||||
#include <QOpenGLExtraFunctions>
|
|
||||||
#include "glbuffer.h"
|
#include "glbuffer.h"
|
||||||
|
|
||||||
|
#include <QOpenGLExtraFunctions>
|
||||||
|
|
||||||
|
|
||||||
Buffer::Buffer(GLenum target, GLenum _usage) {
|
Buffer::Buffer(GLenum target, GLenum _usage) {
|
||||||
target_ = target;
|
target_ = target;
|
||||||
usage_ = _usage;
|
usage_ = _usage;
|
||||||
buffer_ = 0;
|
buffer_ = 0;
|
||||||
prev_size = 0;
|
prev_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Buffer::~Buffer() {
|
Buffer::~Buffer() {}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Buffer::init(QOpenGLExtraFunctions * f) {
|
void Buffer::init(QOpenGLExtraFunctions * f) {
|
||||||
@@ -48,8 +48,14 @@ void Buffer::destroy(QOpenGLExtraFunctions * f) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Buffer::reinit() {
|
||||||
|
buffer_ = 0;
|
||||||
|
prev_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Buffer::bind(QOpenGLExtraFunctions * f) {
|
void Buffer::bind(QOpenGLExtraFunctions * f) {
|
||||||
//qDebug() << "bind" << target_ << buffer_;
|
// qDebug() << "bind" << target_ << buffer_;
|
||||||
f->glBindBuffer(target_, buffer_);
|
f->glBindBuffer(target_, buffer_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,10 +78,10 @@ void Buffer::unmap(QOpenGLExtraFunctions * f) {
|
|||||||
|
|
||||||
bool Buffer::resize(QOpenGLExtraFunctions * f, int new_size) {
|
bool Buffer::resize(QOpenGLExtraFunctions * f, int new_size) {
|
||||||
if (new_size <= 0) return false;
|
if (new_size <= 0) return false;
|
||||||
//qDebug() << "check resize buffer" << buffer_ << "bytes" << new_size << ", old =" << prev_size;
|
// qDebug() << "check resize buffer" << buffer_ << "bytes" << new_size << ", old =" << prev_size;
|
||||||
if (new_size <= prev_size) return false;
|
if (new_size <= prev_size) return false;
|
||||||
prev_size = new_size;
|
prev_size = new_size;
|
||||||
//qDebug() << "resize buffer " << buffer_ << target_ << "for" << new_size << "bytes";
|
// qDebug() << "resize buffer " << buffer_ << target_ << "for" << new_size << "bytes";
|
||||||
f->glBufferData(target_, new_size, 0, usage_);
|
f->glBufferData(target_, new_size, 0, usage_);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -83,6 +89,6 @@ bool Buffer::resize(QOpenGLExtraFunctions * f, int new_size) {
|
|||||||
|
|
||||||
void Buffer::load(QOpenGLExtraFunctions * f, const void * data, int size, int offset) {
|
void Buffer::load(QOpenGLExtraFunctions * f, const void * data, int size, int offset) {
|
||||||
if (!data || size <= 0) return;
|
if (!data || size <= 0) return;
|
||||||
//qDebug() << "load buffer" << buffer_ << "bytes" << size;
|
// qDebug() << "load buffer" << buffer_ << "bytes" << size;
|
||||||
f->glBufferSubData(target_, offset, size, data);
|
f->glBufferSubData(target_, offset, size, data);
|
||||||
}
|
}
|
||||||
58
src/core/core/glbuffer.h
Normal file
58
src/core/core/glbuffer.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
QGL Buffer
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLBUFFER_H
|
||||||
|
#define GLBUFFER_H
|
||||||
|
|
||||||
|
#include "gltypes.h"
|
||||||
|
|
||||||
|
|
||||||
|
class QGLENGINE_CORE_EXPORT Buffer {
|
||||||
|
friend class ObjectBase;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Buffer(GLenum target, GLenum usage = GL_DYNAMIC_DRAW);
|
||||||
|
~Buffer();
|
||||||
|
|
||||||
|
void init(QOpenGLExtraFunctions * f);
|
||||||
|
void destroy(QOpenGLExtraFunctions * f);
|
||||||
|
void reinit();
|
||||||
|
|
||||||
|
void bind(QOpenGLExtraFunctions * f);
|
||||||
|
void release(QOpenGLExtraFunctions * f);
|
||||||
|
void * map(QOpenGLExtraFunctions * f, GLbitfield mode, int size = -1);
|
||||||
|
void unmap(QOpenGLExtraFunctions * f);
|
||||||
|
|
||||||
|
// returns true if size changed
|
||||||
|
bool resize(QOpenGLExtraFunctions * f, int new_size);
|
||||||
|
void load(QOpenGLExtraFunctions * f, const void * data, int size, int offset = 0);
|
||||||
|
|
||||||
|
GLuint ID() const { return buffer_; }
|
||||||
|
GLenum usage() const { return usage_; }
|
||||||
|
GLenum target() const { return target_; }
|
||||||
|
void setTarget(GLenum t) { target_ = t; }
|
||||||
|
bool isInit() const { return buffer_ != 0; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLenum target_, usage_;
|
||||||
|
GLuint buffer_;
|
||||||
|
int prev_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // GLBUFFER_H
|
||||||
@@ -1,23 +1,24 @@
|
|||||||
/*
|
/*
|
||||||
QGL CubeTexture
|
QGL CubeTexture
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU Lesser General Public License for more details.
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "gltypes.h"
|
|
||||||
#include "glcubemap.h"
|
#include "glcubemap.h"
|
||||||
|
|
||||||
|
#include "gltypes.h"
|
||||||
#include "hdr_p.h"
|
#include "hdr_p.h"
|
||||||
|
|
||||||
using namespace QGLEngineShaders;
|
using namespace QGLEngineShaders;
|
||||||
@@ -51,9 +52,9 @@ QVector<QVector3D> loadFileHDR(const QString & path, QSize * size) {
|
|||||||
qDebug() << "[QGLEngine] File" << path << "has unknown size!";
|
qDebug() << "[QGLEngine] File" << path << "has unknown size!";
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
sz.setWidth (sl[3].toInt());
|
sz.setWidth(sl[3].toInt());
|
||||||
sz.setHeight(sl[1].toInt());
|
sz.setHeight(sl[1].toInt());
|
||||||
//qDebug() << "found size" << sz;
|
// qDebug() << "found size" << sz;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,26 +62,23 @@ QVector<QVector3D> loadFileHDR(const QString & path, QSize * size) {
|
|||||||
f.seek(ts.pos());
|
f.seek(ts.pos());
|
||||||
QDataStream ds(&f);
|
QDataStream ds(&f);
|
||||||
int count = sz.width() * sz.height();
|
int count = sz.width() * sz.height();
|
||||||
QVector<float> data(count*3);
|
QVector<float> data(count * 3);
|
||||||
if (!RGBE_ReadPixels_RLE(&ds, data.data(), sz.width(), sz.height()))
|
if (!RGBE_ReadPixels_RLE(&ds, data.data(), sz.width(), sz.height())) return ret;
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (size) *size = sz;
|
if (size) *size = sz;
|
||||||
ret.resize(count);
|
ret.resize(count);
|
||||||
//QColor col;
|
// QColor col;
|
||||||
//QImage im(sz, QImage::Format_ARGB32);
|
// QImage im(sz, QImage::Format_ARGB32);
|
||||||
//QRgb * imdata = (QRgb*)im.bits();
|
// QRgb * imdata = (QRgb*)im.bits();
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
QVector3D p(pow(data[i*3 + 2], 1. / 2.2),
|
QVector3D p(pow(data[i * 3 + 2], 1. / 2.2), pow(data[i * 3 + 1], 1. / 2.2), pow(data[i * 3 + 0], 1. / 2.2));
|
||||||
pow(data[i*3 + 1], 1. / 2.2),
|
|
||||||
pow(data[i*3 + 0], 1. / 2.2));
|
|
||||||
ret[i] = p;
|
ret[i] = p;
|
||||||
//col = QColor::fromRgbF(piClamp(p[0], 0.f, 1.f),
|
// col = QColor::fromRgbF(piClamp(p[0], 0.f, 1.f),
|
||||||
// piClamp(p[1], 0.f, 1.f),
|
// piClamp(p[1], 0.f, 1.f),
|
||||||
// piClamp(p[2], 0.f, 1.f));
|
// piClamp(p[2], 0.f, 1.f));
|
||||||
//imdata[i] = col.rgb();
|
// imdata[i] = col.rgb();
|
||||||
}
|
}
|
||||||
//im.save("_hdr.png");
|
// im.save("_hdr.png");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -90,72 +88,71 @@ QVector<QVector3D> faceHDR(const QVector<QVector3D> & data, QSize sz, QSize & fs
|
|||||||
QVector<QVector3D> ret;
|
QVector<QVector3D> ret;
|
||||||
if (data.isEmpty() || sz.isNull()) return ret;
|
if (data.isEmpty() || sz.isNull()) return ret;
|
||||||
QRect fr;
|
QRect fr;
|
||||||
int fw = sz.width () / 4;
|
int fw = sz.width() / 4;
|
||||||
int fh = sz.height() / 3;
|
int fh = sz.height() / 3;
|
||||||
fsz = QSize(fw, fh);
|
fsz = QSize(fw, fh);
|
||||||
ret.reserve(fw * fh);
|
ret.reserve(fw * fh);
|
||||||
switch (face) {
|
switch (face) {
|
||||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
|
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
|
||||||
fr.setRect(fw, fh, fw, fh);
|
fr.setRect(fw, fh, fw, fh);
|
||||||
for (int x = fr.left(); x <= fr.right(); ++x) {
|
for (int x = fr.left(); x <= fr.right(); ++x) {
|
||||||
for (int y = fr.top(); y <= fr.bottom(); ++y) {
|
for (int y = fr.top(); y <= fr.bottom(); ++y) {
|
||||||
ret << data[y*sz.width() + x];
|
ret << data[y * sz.width() + x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
|
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
|
||||||
fr.setRect(fw*3, fh, fw, fh);
|
fr.setRect(fw * 3, fh, fw, fh);
|
||||||
for (int x = fr.right(); x >= fr.left(); --x) {
|
for (int x = fr.right(); x >= fr.left(); --x) {
|
||||||
for (int y = fr.bottom(); y >= fr.top(); --y) {
|
for (int y = fr.bottom(); y >= fr.top(); --y) {
|
||||||
ret << data[y*sz.width() + x];
|
ret << data[y * sz.width() + x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
|
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
|
||||||
fr.setRect( 0, fh, fw, fh);
|
fr.setRect(0, fh, fw, fh);
|
||||||
for (int y = fr.bottom(); y >= fr.top(); --y) {
|
for (int y = fr.bottom(); y >= fr.top(); --y) {
|
||||||
for (int x = fr.left(); x <= fr.right(); ++x) {
|
for (int x = fr.left(); x <= fr.right(); ++x) {
|
||||||
ret << data[y*sz.width() + x];
|
ret << data[y * sz.width() + x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
|
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
|
||||||
fr.setRect(fw*2, fh, fw, fh);
|
fr.setRect(fw * 2, fh, fw, fh);
|
||||||
for (int y = fr.top(); y <= fr.bottom(); ++y) {
|
for (int y = fr.top(); y <= fr.bottom(); ++y) {
|
||||||
for (int x = fr.right(); x >= fr.left(); --x) {
|
for (int x = fr.right(); x >= fr.left(); --x) {
|
||||||
ret << data[y*sz.width() + x];
|
ret << data[y * sz.width() + x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
|
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
|
||||||
fr.setRect(fw, 0, fw, fh);
|
fr.setRect(fw, 0, fw, fh);
|
||||||
for (int x = fr.left(); x <= fr.right(); ++x) {
|
for (int x = fr.left(); x <= fr.right(); ++x) {
|
||||||
for (int y = fr.top(); y <= fr.bottom(); ++y) {
|
for (int y = fr.top(); y <= fr.bottom(); ++y) {
|
||||||
ret << data[y*sz.width() + x];
|
ret << data[y * sz.width() + x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
|
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
|
||||||
fr.setRect(fw, fh*2, fw, fh);
|
fr.setRect(fw, fh * 2, fw, fh);
|
||||||
for (int x = fr.left(); x <= fr.right(); ++x) {
|
for (int x = fr.left(); x <= fr.right(); ++x) {
|
||||||
for (int y = fr.top(); y <= fr.bottom(); ++y) {
|
for (int y = fr.top(); y <= fr.bottom(); ++y) {
|
||||||
ret << data[y*sz.width() + x];
|
ret << data[y * sz.width() + x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
if (fr.isEmpty()) return ret;
|
if (fr.isEmpty()) return ret;
|
||||||
//qDebug() << ret.size() << fr;
|
// qDebug() << ret.size() << fr;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CubeTexture::CubeTexture(QOpenGLExtraFunctions * f_, int _size, const GLenum & _format): f(f_) {
|
CubeTexture::CubeTexture(QOpenGLExtraFunctions * f_, int _size, const GLenum & _format): f(f_) {
|
||||||
size = _size;
|
size = _size;
|
||||||
format_ = _format;
|
format_ = _format;
|
||||||
id_ = 0;
|
id_ = 0;
|
||||||
changed_ = false;
|
changed_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,9 +196,17 @@ void CubeTexture::loadHDR(const QVector<QVector3D> & data, QSize sz) {
|
|||||||
QVector<QVector3D> fd;
|
QVector<QVector3D> fd;
|
||||||
for (int i = 0; i < 6; ++i) {
|
for (int i = 0; i < 6; ++i) {
|
||||||
fd = faceHDR(data, sz, fsz, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i);
|
fd = faceHDR(data, sz, fsz, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i);
|
||||||
//qDebug() << "load cube" << fd[0];
|
// qDebug() << "load cube" << fd[0];
|
||||||
f->glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, format_, fsz.width(), fsz.height(), 0, GL_RGB, GL_FLOAT, fd.isEmpty() ? 0 : fd.constData());
|
f->glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
|
||||||
//qDebug() << QString::number(GetLastError(), 16);
|
0,
|
||||||
|
format_,
|
||||||
|
fsz.width(),
|
||||||
|
fsz.height(),
|
||||||
|
0,
|
||||||
|
GL_RGB,
|
||||||
|
GL_FLOAT,
|
||||||
|
fd.isEmpty() ? 0 : fd.constData());
|
||||||
|
// qDebug() << QString::number(GetLastError(), 16);
|
||||||
}
|
}
|
||||||
f->glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
f->glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
||||||
}
|
}
|
||||||
@@ -230,4 +235,3 @@ void CubeTexture::load() {
|
|||||||
}
|
}
|
||||||
changed_ = false;
|
changed_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
60
src/core/core/glcubemap.h
Normal file
60
src/core/core/glcubemap.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
QGL CubeTexture
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLCUBEMAP_H
|
||||||
|
#define GLCUBEMAP_H
|
||||||
|
|
||||||
|
#include "chunkstream.h"
|
||||||
|
#include "glshaders_types.h"
|
||||||
|
|
||||||
|
QVector<QVector3D> QGLENGINE_CORE_EXPORT loadFileHDR(const QString & path, QSize * size = 0);
|
||||||
|
|
||||||
|
class QGLENGINE_CORE_EXPORT CubeTexture {
|
||||||
|
public:
|
||||||
|
CubeTexture(QOpenGLExtraFunctions * f_, int _size, const GLenum & _format = GL_RGB16F);
|
||||||
|
bool init();
|
||||||
|
void destroy();
|
||||||
|
void bind(int channel = 0);
|
||||||
|
void release();
|
||||||
|
void resize(int _size) {
|
||||||
|
size = _size;
|
||||||
|
changed_ = true;
|
||||||
|
}
|
||||||
|
void loadHDR(const QVector<QVector3D> & data, QSize sz);
|
||||||
|
void setFileHDR(const QString & path);
|
||||||
|
QString fileHDR() const { return hdr_path; }
|
||||||
|
GLenum format() const { return format_; }
|
||||||
|
void setFormat(GLenum f) {
|
||||||
|
format_ = f;
|
||||||
|
changed_ = true;
|
||||||
|
}
|
||||||
|
GLuint id() const { return id_; }
|
||||||
|
bool isInit() const { return id_ != 0; }
|
||||||
|
void load();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QOpenGLExtraFunctions * f;
|
||||||
|
bool changed_;
|
||||||
|
int size;
|
||||||
|
GLenum format_;
|
||||||
|
GLuint id_;
|
||||||
|
QString hdr_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // GLCUBEMAP_H
|
||||||
108
src/core/core/glcubemaparray.cpp
Normal file
108
src/core/core/glcubemaparray.cpp
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
QGL CubeMapArray
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GL_GLEXT_PROTOTYPES
|
||||||
|
#include "glcubemaparray.h"
|
||||||
|
|
||||||
|
#include <QOpenGLExtraFunctions>
|
||||||
|
|
||||||
|
|
||||||
|
CubeMapArray::CubeMapArray(GLenum format, bool filter) {
|
||||||
|
target_ = GL_TEXTURE_CUBE_MAP_ARRAY;
|
||||||
|
format_ = format;
|
||||||
|
texture_ = 0;
|
||||||
|
layers_ = 0;
|
||||||
|
filtering_ = filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CubeMapArray::~CubeMapArray() {}
|
||||||
|
|
||||||
|
|
||||||
|
void CubeMapArray::init(QOpenGLExtraFunctions * f) {
|
||||||
|
if (!isInit()) {
|
||||||
|
f->glGenTextures(1, &texture_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CubeMapArray::destroy(QOpenGLExtraFunctions * f) {
|
||||||
|
if (texture_ != 0) {
|
||||||
|
f->glDeleteTextures(1, &texture_);
|
||||||
|
}
|
||||||
|
texture_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CubeMapArray::reinit() {
|
||||||
|
texture_ = 0;
|
||||||
|
layers_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CubeMapArray::bind(QOpenGLExtraFunctions * f, int channel) {
|
||||||
|
f->glActiveTexture(GL_TEXTURE0 + channel);
|
||||||
|
f->glBindTexture(target_, texture_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CubeMapArray::release(QOpenGLExtraFunctions * f) {
|
||||||
|
f->glBindTexture(target_, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CubeMapArray::resize(QOpenGLExtraFunctions * f, QSize new_size, int layers_count) {
|
||||||
|
if (new_size.isNull() || layers_count <= 0) return false;
|
||||||
|
if ((size_ == new_size) && (layers_ >= layers_count)) return false;
|
||||||
|
size_ = new_size;
|
||||||
|
layers_ = layers_count;
|
||||||
|
f->glBindTexture(target_, texture_);
|
||||||
|
f->glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
f->glTexParameteri(target_, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
if (filtering_) {
|
||||||
|
f->glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
f->glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
f->glTexParameteri(target_, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
|
||||||
|
} else {
|
||||||
|
f->glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
f->glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
}
|
||||||
|
GLenum bformat = format_;
|
||||||
|
GLenum btype = GL_UNSIGNED_BYTE;
|
||||||
|
if (format_ == GL_R16F || format_ == GL_R32F) {
|
||||||
|
bformat = GL_RED;
|
||||||
|
btype = GL_FLOAT;
|
||||||
|
}
|
||||||
|
f->glTexImage3D(target_, 0, format_, size_.width(), size_.height(), layers_ * 6, 0, bformat, btype, nullptr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CubeMapArray::load(QOpenGLExtraFunctions * f, const QImage & image, int layer) {
|
||||||
|
if (image.isNull() || size_.isNull() || layer < 0 || layer >= layers_) return;
|
||||||
|
QImage im =
|
||||||
|
image.mirrored(false, true).scaled(size_, Qt::IgnoreAspectRatio, Qt::SmoothTransformation).convertToFormat(QImage::Format_RGBA8888);
|
||||||
|
// qDebug() << "CubeMapArray::load image" << image.size() << "to layer" << layer;
|
||||||
|
// f->glTexSubImage3D(target_, 0, 0, 0, layer, size_.width(), size_.height(), 1, GL_RGBA, GL_UNSIGNED_BYTE, im.constBits());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CubeMapArray::mipmaps(QOpenGLExtraFunctions * f) {
|
||||||
|
f->glBindTexture(target_, texture_);
|
||||||
|
f->glGenerateMipmap(target_);
|
||||||
|
}
|
||||||
55
src/core/core/glcubemaparray.h
Normal file
55
src/core/core/glcubemaparray.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
QGL Texture2DArray
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLCUBEMAPARRAY_H
|
||||||
|
#define GLCUBEMAPARRAY_H
|
||||||
|
|
||||||
|
#include "gltypes.h"
|
||||||
|
|
||||||
|
|
||||||
|
class QGLENGINE_CORE_EXPORT CubeMapArray {
|
||||||
|
public:
|
||||||
|
CubeMapArray(GLenum format, bool filter);
|
||||||
|
~CubeMapArray();
|
||||||
|
|
||||||
|
void init(QOpenGLExtraFunctions * f);
|
||||||
|
void destroy(QOpenGLExtraFunctions * f);
|
||||||
|
void reinit();
|
||||||
|
|
||||||
|
void bind(QOpenGLExtraFunctions * f, int channel = 0);
|
||||||
|
void release(QOpenGLExtraFunctions * f);
|
||||||
|
|
||||||
|
// returns true if size changed
|
||||||
|
bool resize(QOpenGLExtraFunctions * f, QSize new_size, int layers_count);
|
||||||
|
void load(QOpenGLExtraFunctions * f, const QImage & image, int layer);
|
||||||
|
void mipmaps(QOpenGLExtraFunctions * f);
|
||||||
|
|
||||||
|
GLuint ID() const { return texture_; }
|
||||||
|
bool isInit() const { return texture_ != 0; }
|
||||||
|
int layersCount() const { return layers_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLenum target_, format_;
|
||||||
|
GLuint texture_;
|
||||||
|
QSize size_;
|
||||||
|
int layers_;
|
||||||
|
bool filtering_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // GLCUBEMAPARRAY_H
|
||||||
@@ -1,56 +1,59 @@
|
|||||||
/*
|
/*
|
||||||
QGL Framebuffer
|
QGL Framebuffer
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU Lesser General Public License for more details.
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QOpenGLExtraFunctions>
|
|
||||||
#include "glframebuffer.h"
|
#include "glframebuffer.h"
|
||||||
|
|
||||||
|
#include <QOpenGLExtraFunctions>
|
||||||
#include <QTime>
|
#include <QTime>
|
||||||
|
|
||||||
|
|
||||||
Framebuffer::Framebuffer(QOpenGLExtraFunctions * f_, int colorAttachments_, bool withDepth, GLenum colorFormat_, GLenum _target)
|
Framebuffer::Framebuffer(QOpenGLExtraFunctions * f_, int colorAttachments_, bool withDepth, GLenum colorFormat_, GLenum _target)
|
||||||
: f(f_), pbo(GL_PIXEL_PACK_BUFFER, GL_STREAM_DRAW) {
|
: f(f_)
|
||||||
|
, pbo(GL_PIXEL_PACK_BUFFER, GL_STREAM_DRAW) {
|
||||||
is_depth = withDepth;
|
is_depth = withDepth;
|
||||||
target_ = _target;
|
target_ = _target;
|
||||||
color_formats.fill(colorFormat_, colorAttachments_);
|
color_formats.fill(colorFormat_, colorAttachments_);
|
||||||
colors.fill(0, colorAttachments_);
|
colors.fill(0, colorAttachments_);
|
||||||
fbo = drbo = 0;
|
fbo = drbo = 0;
|
||||||
tex_d = 0;
|
tex_d = 0;
|
||||||
wid = hei = 0;
|
wid = hei = 0;
|
||||||
pbo_queried = 0;
|
pbo_queried = 0;
|
||||||
is_changed = false;
|
is_changed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Framebuffer::Framebuffer(QOpenGLExtraFunctions * f_, QVector<GLenum> colors_, bool withDepth, GLenum _target)
|
Framebuffer::Framebuffer(QOpenGLExtraFunctions * f_, QVector<GLenum> colors_, bool withDepth, GLenum _target)
|
||||||
: f(f_), pbo(GL_PIXEL_PACK_BUFFER, GL_STREAM_DRAW) {
|
: f(f_)
|
||||||
is_depth = withDepth;
|
, pbo(GL_PIXEL_PACK_BUFFER, GL_STREAM_DRAW) {
|
||||||
target_ = _target;
|
is_depth = withDepth;
|
||||||
|
target_ = _target;
|
||||||
color_formats = colors_;
|
color_formats = colors_;
|
||||||
colors.fill(0, colors_.size());
|
colors.fill(0, colors_.size());
|
||||||
fbo = drbo = 0;
|
fbo = drbo = 0;
|
||||||
tex_d = 0;
|
tex_d = 0;
|
||||||
wid = hei = 0;
|
wid = hei = 0;
|
||||||
pbo_queried = 0;
|
pbo_queried = 0;
|
||||||
is_changed = false;
|
is_changed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Framebuffer::~Framebuffer() {
|
Framebuffer::~Framebuffer() {
|
||||||
deleteGLFramebuffer(fbo);
|
if (fbo > 0) deleteGLFramebuffer(fbo);
|
||||||
deleteGLRenderbuffer(drbo);
|
deleteGLRenderbuffer(drbo);
|
||||||
for (int i = 0; i < colors.size(); ++i)
|
for (int i = 0; i < colors.size(); ++i)
|
||||||
deleteGLTexture(f, colors[i]);
|
deleteGLTexture(f, colors[i]);
|
||||||
@@ -59,12 +62,15 @@ Framebuffer::~Framebuffer() {
|
|||||||
|
|
||||||
|
|
||||||
void Framebuffer::resize(int width, int height, bool force) {
|
void Framebuffer::resize(int width, int height, bool force) {
|
||||||
if ((wid == width) && (hei == height) && !force) return;
|
if (fbo > 0) {
|
||||||
|
if ((wid == width) && (hei == height) && !force) return;
|
||||||
|
}
|
||||||
wid = width;
|
wid = width;
|
||||||
hei = height;
|
hei = height;
|
||||||
deleteGLFramebuffer(fbo);
|
if (fbo > 0) deleteGLFramebuffer(fbo);
|
||||||
f->glGenFramebuffers(1, &fbo);
|
f->glGenFramebuffers(1, &fbo);
|
||||||
f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||||
|
// qDebug() << "resize" << f << wid << hei << fbo << colors.size();
|
||||||
for (int i = 0; i < colors.size(); ++i) {
|
for (int i = 0; i < colors.size(); ++i) {
|
||||||
deleteGLTexture(f, colors[i]);
|
deleteGLTexture(f, colors[i]);
|
||||||
createGLTexture(f, colors[i], width, height, color_formats[i], target_);
|
createGLTexture(f, colors[i], width, height, color_formats[i], target_);
|
||||||
@@ -77,7 +83,7 @@ void Framebuffer::resize(int width, int height, bool force) {
|
|||||||
}
|
}
|
||||||
if (is_depth) {
|
if (is_depth) {
|
||||||
deleteGLTexture(f, tex_d);
|
deleteGLTexture(f, tex_d);
|
||||||
deleteGLRenderbuffer(drbo);
|
if (drbo > 0) deleteGLRenderbuffer(drbo);
|
||||||
f->glGenRenderbuffers(1, &drbo);
|
f->glGenRenderbuffers(1, &drbo);
|
||||||
f->glBindRenderbuffer(GL_RENDERBUFFER, drbo);
|
f->glBindRenderbuffer(GL_RENDERBUFFER, drbo);
|
||||||
f->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
|
f->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
|
||||||
@@ -88,6 +94,7 @@ void Framebuffer::resize(int width, int height, bool force) {
|
|||||||
f->glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
f->glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
f->glTexParameteri(target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
f->glTexParameteri(target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, target_, tex_d, 0);
|
f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, target_, tex_d, 0);
|
||||||
|
// f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, target_, tex_d, 0);
|
||||||
}
|
}
|
||||||
f->glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
f->glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
if (pbo.isInit()) {
|
if (pbo.isInit()) {
|
||||||
@@ -97,6 +104,17 @@ void Framebuffer::resize(int width, int height, bool force) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Framebuffer::reinit(QOpenGLExtraFunctions * f_) {
|
||||||
|
if (f_) f = f_;
|
||||||
|
pbo.reinit();
|
||||||
|
colors.fill(0);
|
||||||
|
fbo = drbo = 0;
|
||||||
|
tex_d = 0;
|
||||||
|
pbo_queried = 0;
|
||||||
|
is_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QImage Framebuffer::grab() const {
|
QImage Framebuffer::grab() const {
|
||||||
return QImage();
|
return QImage();
|
||||||
}
|
}
|
||||||
@@ -139,8 +157,7 @@ uint Framebuffer::getPoint() const {
|
|||||||
uint ret = 0;
|
uint ret = 0;
|
||||||
pbo.bind(f);
|
pbo.bind(f);
|
||||||
void * map = pbo.map(f, GL_MAP_READ_BIT, sizeof(uint));
|
void * map = pbo.map(f, GL_MAP_READ_BIT, sizeof(uint));
|
||||||
if (map)
|
if (map) memcpy(&ret, map, sizeof(uint));
|
||||||
memcpy(&ret, map, sizeof(uint));
|
|
||||||
pbo.unmap(f);
|
pbo.unmap(f);
|
||||||
pbo.release(f);
|
pbo.release(f);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -153,8 +170,7 @@ QVector<uint> Framebuffer::getPointsByte() const {
|
|||||||
ret.resize(pbo_queried);
|
ret.resize(pbo_queried);
|
||||||
pbo.bind(f);
|
pbo.bind(f);
|
||||||
void * map = pbo.map(f, GL_MAP_READ_BIT, pbo_queried * sizeof(uint));
|
void * map = pbo.map(f, GL_MAP_READ_BIT, pbo_queried * sizeof(uint));
|
||||||
if (map)
|
if (map) memcpy(ret.data(), map, pbo_queried * sizeof(uint));
|
||||||
memcpy(ret.data(), map, pbo_queried * sizeof(uint));
|
|
||||||
pbo.unmap(f);
|
pbo.unmap(f);
|
||||||
pbo.release(f);
|
pbo.release(f);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -167,8 +183,7 @@ QVector<QVector4D> Framebuffer::getPointsFloat() const {
|
|||||||
ret.resize(pbo_queried);
|
ret.resize(pbo_queried);
|
||||||
pbo.bind(f);
|
pbo.bind(f);
|
||||||
void * map = pbo.map(f, GL_MAP_READ_BIT, pbo_queried * sizeof(QVector4D));
|
void * map = pbo.map(f, GL_MAP_READ_BIT, pbo_queried * sizeof(QVector4D));
|
||||||
if (map)
|
if (map) memcpy(ret.data(), map, pbo_queried * sizeof(QVector4D));
|
||||||
memcpy(ret.data(), map, pbo_queried * sizeof(QVector4D));
|
|
||||||
pbo.unmap(f);
|
pbo.unmap(f);
|
||||||
pbo.release(f);
|
pbo.release(f);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -178,12 +193,11 @@ QVector<QVector4D> Framebuffer::getPointsFloat() const {
|
|||||||
QImage Framebuffer::getImage() const {
|
QImage Framebuffer::getImage() const {
|
||||||
QImage ret;
|
QImage ret;
|
||||||
if (!pbo.isInit() || (pbo_queried == 0)) return ret;
|
if (!pbo.isInit() || (pbo_queried == 0)) return ret;
|
||||||
ret = QImage(size(), QImage::Format_RGBA8888);
|
ret = QImage(size(), QImage::Format_RGBA8888);
|
||||||
int bytes = width() * height() * 4;
|
int bytes = width() * height() * 4;
|
||||||
pbo.bind(f);
|
pbo.bind(f);
|
||||||
void * map = pbo.map(f, GL_MAP_READ_BIT, bytes);
|
void * map = pbo.map(f, GL_MAP_READ_BIT, bytes);
|
||||||
if (map)
|
if (map) memcpy(ret.bits(), map, bytes);
|
||||||
memcpy(ret.bits(), map, bytes);
|
|
||||||
pbo.unmap(f);
|
pbo.unmap(f);
|
||||||
pbo.release(f);
|
pbo.release(f);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -264,7 +278,7 @@ void Framebuffer::unsetWriteBuffers() {
|
|||||||
void Framebuffer::enablePixelBuffer() {
|
void Framebuffer::enablePixelBuffer() {
|
||||||
pbo.init(f);
|
pbo.init(f);
|
||||||
pbo.bind(f);
|
pbo.bind(f);
|
||||||
pbo.resize(f, width()*height()*4*4);
|
pbo.resize(f, width() * height() * 4 * 4);
|
||||||
pbo.release(f);
|
pbo.release(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,6 +297,14 @@ void Framebuffer::bindColorTexture(int index, int channel) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Framebuffer::bindColorTextures(const QVector<int> & indeces) {
|
||||||
|
for (int i = indeces.size() - 1; i >= 0; --i) {
|
||||||
|
f->glActiveTexture(GL_TEXTURE0 + i);
|
||||||
|
f->glBindTexture(GL_TEXTURE_2D, colors[indeces[i]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Framebuffer::bindColorTextures() {
|
void Framebuffer::bindColorTextures() {
|
||||||
for (int i = colors.size() - 1; i >= 0; --i) {
|
for (int i = colors.size() - 1; i >= 0; --i) {
|
||||||
f->glActiveTexture(GL_TEXTURE0 + i);
|
f->glActiveTexture(GL_TEXTURE0 + i);
|
||||||
@@ -298,14 +320,12 @@ void Framebuffer::bindDepthTexture(int channel) {
|
|||||||
|
|
||||||
|
|
||||||
void Framebuffer::deleteGLRenderbuffer(GLuint & drbo) {
|
void Framebuffer::deleteGLRenderbuffer(GLuint & drbo) {
|
||||||
if (drbo != 0)
|
if (drbo != 0) f->glDeleteRenderbuffers(1, &drbo);
|
||||||
f->glDeleteRenderbuffers(1, &drbo);
|
|
||||||
drbo = 0;
|
drbo = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Framebuffer::deleteGLFramebuffer(GLuint & fbo) {
|
void Framebuffer::deleteGLFramebuffer(GLuint & fbo) {
|
||||||
if (fbo != 0)
|
if (fbo != 0) f->glDeleteFramebuffers(1, &fbo);
|
||||||
f->glDeleteFramebuffers(1, &fbo);
|
|
||||||
fbo = 0;
|
fbo = 0;
|
||||||
}
|
}
|
||||||
99
src/core/core/glframebuffer.h
Normal file
99
src/core/core/glframebuffer.h
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
QGL Framebuffer
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLFRAMEBUFFER_H
|
||||||
|
#define GLFRAMEBUFFER_H
|
||||||
|
|
||||||
|
#include "glbuffer.h"
|
||||||
|
|
||||||
|
|
||||||
|
class QGLENGINE_CORE_EXPORT Framebuffer {
|
||||||
|
friend class FramebufferMipmap;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Framebuffer(QOpenGLExtraFunctions * f_,
|
||||||
|
int colorAttachments = 1,
|
||||||
|
bool withDepth = true,
|
||||||
|
GLenum colorFormat = GL_RGBA8,
|
||||||
|
GLenum _target = GL_TEXTURE_2D);
|
||||||
|
Framebuffer(QOpenGLExtraFunctions * f_, QVector<GLenum> colors_, bool withDepth = true, GLenum _target = GL_TEXTURE_2D);
|
||||||
|
virtual ~Framebuffer();
|
||||||
|
|
||||||
|
GLuint id() const { return fbo; }
|
||||||
|
GLuint colorTexture(int index = 0) const { return colors[index]; }
|
||||||
|
GLuint depthTexture() const { return tex_d; }
|
||||||
|
GLenum target() const { return target_; }
|
||||||
|
bool isInit() const { return fbo != 0; }
|
||||||
|
int width() const { return wid; }
|
||||||
|
int height() const { return hei; }
|
||||||
|
QSize size() const { return QSize(wid, hei); }
|
||||||
|
QRect rect() const { return QRect(0, 0, wid, hei); }
|
||||||
|
QImage grab() const;
|
||||||
|
QVector<float> grabF(int index) const;
|
||||||
|
void queryPoint(int index, QPoint p);
|
||||||
|
void queryPoints(int index, QRect rect, GLenum pixel_format = GL_UNSIGNED_BYTE);
|
||||||
|
void queryImage(int index);
|
||||||
|
uint getPoint() const;
|
||||||
|
QVector<uint> getPointsByte() const;
|
||||||
|
QVector<QVector4D> getPointsFloat() const;
|
||||||
|
QImage getImage() const;
|
||||||
|
int queriedPoints() const { return pbo_queried; }
|
||||||
|
void blit(int index_from,
|
||||||
|
GLuint fb_to,
|
||||||
|
int index_to,
|
||||||
|
QRect from,
|
||||||
|
QRect to,
|
||||||
|
GLbitfield mask = GL_COLOR_BUFFER_BIT,
|
||||||
|
GLenum filter = GL_NEAREST) const;
|
||||||
|
|
||||||
|
void resize(QSize sz, bool force = false) { resize(sz.width(), sz.height(), force); }
|
||||||
|
void resize(int width, int height, bool force = false);
|
||||||
|
void reinit(QOpenGLExtraFunctions * f_ = nullptr);
|
||||||
|
void bind();
|
||||||
|
void release();
|
||||||
|
void setReadBuffer(int index) { glReadBuffer(GL_COLOR_ATTACHMENT0 + index); }
|
||||||
|
void setWriteBuffer(int index);
|
||||||
|
void setWriteBuffers(const int * indeces, int count);
|
||||||
|
void setWriteBuffers(const QVector<int> & indeces) { setWriteBuffers(indeces.constData(), indeces.size()); }
|
||||||
|
void setWriteBuffers();
|
||||||
|
void unsetWriteBuffers();
|
||||||
|
void enablePixelBuffer();
|
||||||
|
void setColorTextureFiltering(int index, GLenum filter);
|
||||||
|
|
||||||
|
void copyDepthFrom(GLuint tex) { ; }
|
||||||
|
void bindColorTexture(int index, int channel = 0);
|
||||||
|
void bindColorTextures(const QVector<int> & indeces);
|
||||||
|
void bindColorTextures();
|
||||||
|
void bindDepthTexture(int channel);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void deleteGLRenderbuffer(GLuint & drbo);
|
||||||
|
void deleteGLFramebuffer(GLuint & fbo);
|
||||||
|
|
||||||
|
bool is_depth, is_changed;
|
||||||
|
int pbo_queried;
|
||||||
|
QOpenGLExtraFunctions * f;
|
||||||
|
mutable Buffer pbo;
|
||||||
|
QVector<GLuint> colors;
|
||||||
|
QVector<GLenum> color_formats;
|
||||||
|
GLenum target_;
|
||||||
|
GLuint fbo, drbo, tex_d;
|
||||||
|
GLint prev_view[4], wid, hei;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GLFRAMEBUFFER_H
|
||||||
60
src/core/core/glframebuffer_mipmap.cpp
Normal file
60
src/core/core/glframebuffer_mipmap.cpp
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
QGL FramebufferMipmap
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "glframebuffer_mipmap.h"
|
||||||
|
|
||||||
|
#include <QOpenGLExtraFunctions>
|
||||||
|
#include <QTime>
|
||||||
|
|
||||||
|
|
||||||
|
FramebufferMipmap::FramebufferMipmap(const Framebuffer & fb, int index_from_, int levels): src_fb(fb) {
|
||||||
|
index_from = index_from_;
|
||||||
|
for (int i = 0; i < levels; ++i)
|
||||||
|
fbo << new Framebuffer(fb.f, 1, false, fb.color_formats[index_from]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FramebufferMipmap::~FramebufferMipmap() {}
|
||||||
|
|
||||||
|
|
||||||
|
void FramebufferMipmap::setIndexFrom(int index) {
|
||||||
|
index_from = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FramebufferMipmap::resize() {
|
||||||
|
QSize sz = src_fb.size();
|
||||||
|
for (int i = 0; i < fbo.size(); ++i) {
|
||||||
|
sz /= 2;
|
||||||
|
fbo[i]->resize(sz.width(), sz.height());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FramebufferMipmap::create() {
|
||||||
|
if (fbo.isEmpty()) return;
|
||||||
|
src_fb.blit(index_from, fbo[0]->id(), 0, src_fb.rect(), fbo[0]->rect(), GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||||
|
for (int i = 0; i < fbo.size() - 1; ++i)
|
||||||
|
fbo[i]->blit(0, fbo[i + 1]->id(), 0, fbo[i]->rect(), fbo[i + 1]->rect(), GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FramebufferMipmap::reinit() {
|
||||||
|
for (auto * f: fbo)
|
||||||
|
f->reinit();
|
||||||
|
}
|
||||||
50
src/core/core/glframebuffer_mipmap.h
Normal file
50
src/core/core/glframebuffer_mipmap.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
QGL FramebufferMipmap
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLFRAMEBUFFER_MIPMAP_H
|
||||||
|
#define GLFRAMEBUFFER_MIPMAP_H
|
||||||
|
|
||||||
|
#include "glframebuffer.h"
|
||||||
|
|
||||||
|
|
||||||
|
class QGLENGINE_CORE_EXPORT FramebufferMipmap {
|
||||||
|
public:
|
||||||
|
FramebufferMipmap(const Framebuffer & fb, int index_from_, int levels = 2);
|
||||||
|
virtual ~FramebufferMipmap();
|
||||||
|
|
||||||
|
int levelsCount() const { return fbo.size(); }
|
||||||
|
int lastLevel() const { return fbo.size() - 1; }
|
||||||
|
Framebuffer & plane(int level) { return *fbo[level]; }
|
||||||
|
Framebuffer & lastPlane() { return *fbo[lastLevel()]; }
|
||||||
|
int width(int level) const { return fbo[level]->wid; }
|
||||||
|
int height(int level) const { return fbo[level]->hei; }
|
||||||
|
QSize size(int level) const { return fbo[level]->size(); }
|
||||||
|
QRect rect(int level) const { return fbo[level]->rect(); }
|
||||||
|
void setIndexFrom(int index);
|
||||||
|
|
||||||
|
void resize();
|
||||||
|
void create();
|
||||||
|
void reinit();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int index_from;
|
||||||
|
const Framebuffer & src_fb;
|
||||||
|
QVector<Framebuffer *> fbo;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GLFRAMEBUFFER_MIPMAP_H
|
||||||
145
src/core/core/glframebuffereffectbase.cpp
Normal file
145
src/core/core/glframebuffereffectbase.cpp
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
QGL Framebuffer effect basic
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "glframebuffereffectbase.h"
|
||||||
|
|
||||||
|
#include "renderer.h"
|
||||||
|
|
||||||
|
#include <QTime>
|
||||||
|
|
||||||
|
|
||||||
|
FramebufferEffectBase::FramebufferEffectBase() {}
|
||||||
|
|
||||||
|
|
||||||
|
FramebufferEffectBase::~FramebufferEffectBase() {
|
||||||
|
/*if (fbo > 0) deleteGLFramebuffer(fbo);
|
||||||
|
deleteGLRenderbuffer(drbo);
|
||||||
|
for (int i = 0; i < colors.size(); ++i)
|
||||||
|
deleteGLTexture(f, colors[i]);
|
||||||
|
deleteGLTexture(f, tex_d);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FramebufferEffectBase::resize(int width, int height, bool force) {
|
||||||
|
/*if (fbo > 0) {
|
||||||
|
if ((wid == width) && (hei == height) && !force) return;
|
||||||
|
}
|
||||||
|
wid = width;
|
||||||
|
hei = height;
|
||||||
|
if (fbo > 0) deleteGLFramebuffer(fbo);
|
||||||
|
f->glGenFramebuffers(1, &fbo);
|
||||||
|
f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||||
|
// qDebug() << "resize" << f << wid << hei << fbo;
|
||||||
|
for (int i = 0; i < colors.size(); ++i) {
|
||||||
|
deleteGLTexture(f, colors[i]);
|
||||||
|
createGLTexture(f, colors[i], width, height, color_formats[i], target_);
|
||||||
|
f->glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
f->glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
f->glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
f->glTexParameteri(target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
f->glTexParameteri(target_, GL_TEXTURE_MAX_LEVEL, 4);
|
||||||
|
f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, target_, colors[i], 0);
|
||||||
|
}
|
||||||
|
if (is_depth) {
|
||||||
|
deleteGLTexture(f, tex_d);
|
||||||
|
if (drbo > 0) deleteGLRenderbuffer(drbo);
|
||||||
|
f->glGenRenderbuffers(1, &drbo);
|
||||||
|
f->glBindRenderbuffer(GL_RENDERBUFFER, drbo);
|
||||||
|
f->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
|
||||||
|
f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, drbo);
|
||||||
|
createGLTexture(f, tex_d, width, height, GL_DEPTH_COMPONENT);
|
||||||
|
f->glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
f->glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
f->glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
f->glTexParameteri(target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, target_, tex_d, 0);
|
||||||
|
}
|
||||||
|
f->glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
if (pbo.isInit()) {
|
||||||
|
enablePixelBuffer();
|
||||||
|
}
|
||||||
|
is_changed = false;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FramebufferEffectBase::reinit() {
|
||||||
|
/*pbo.reinit();
|
||||||
|
colors.fill(0);
|
||||||
|
fbo = drbo = 0;
|
||||||
|
tex_d = 0;
|
||||||
|
pbo_queried = 0;
|
||||||
|
is_changed = true;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FramebufferEffectBase::bindDeferredBuffer(int role, int channel) {
|
||||||
|
r->fbo_ds.bindColorTexture(role, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FramebufferEffectBase::bindDepthBuffer(int channel) {
|
||||||
|
r->fbo_ds.bindDepthTexture(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FramebufferEffectBase::bindPreviousOutput(int channel) {
|
||||||
|
r->fbo_out.bindColorTexture(r->prev_write_plane, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FramebufferEffectBase::setOutputPlane(int channel) {
|
||||||
|
r->fbo_out.setWriteBuffer(channel);
|
||||||
|
r->prev_write_plane = r->cur_write_plane;
|
||||||
|
r->cur_write_plane = channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FramebufferEffectBase::drawScreen(QOpenGLShaderProgram * prog) {
|
||||||
|
r->renderQuad(prog, r->quad, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FramebufferEffectBase::drawInternal() {
|
||||||
|
if (!r) return;
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FramebufferEffectBase::reloadShadersInternal() {
|
||||||
|
if (!r) return;
|
||||||
|
if (is_loaded) return;
|
||||||
|
reloadShaders();
|
||||||
|
is_loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QVector<int> FramebufferEffectBase::getFreePlanes(int count) {
|
||||||
|
return r->getFreePlanes(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int FramebufferEffectBase::previousOutputPlane() const {
|
||||||
|
return r->prev_write_plane;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FramebufferEffectBase::deleteShader(QOpenGLShaderProgram *& s) {
|
||||||
|
if (!s) return;
|
||||||
|
delete s;
|
||||||
|
s = nullptr;
|
||||||
|
}
|
||||||
68
src/core/core/glframebuffereffectbase.h
Normal file
68
src/core/core/glframebuffereffectbase.h
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
QGL Framebuffer effect basic
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef glframebuffereffectbase_H
|
||||||
|
#define glframebuffereffectbase_H
|
||||||
|
|
||||||
|
#include "gltypes.h"
|
||||||
|
#include "parameteredobject.h"
|
||||||
|
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
|
||||||
|
|
||||||
|
class QGLENGINE_CORE_EXPORT FramebufferEffectBase: public ParameteredObject {
|
||||||
|
friend class FramebufferMipmap;
|
||||||
|
friend class Renderer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FramebufferEffectBase();
|
||||||
|
virtual ~FramebufferEffectBase();
|
||||||
|
|
||||||
|
virtual QString name() const = 0;
|
||||||
|
|
||||||
|
void setEnabled(bool on) { enabled_ = on; }
|
||||||
|
bool isEnabled() const { return enabled_; }
|
||||||
|
|
||||||
|
virtual void draw() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void resize(int width, int height, bool force = false);
|
||||||
|
void reinit();
|
||||||
|
|
||||||
|
virtual int maxPlanesUsed() const { return 1; }
|
||||||
|
virtual void reloadShaders() {}
|
||||||
|
|
||||||
|
void bindDeferredBuffer(int role, int channel);
|
||||||
|
void bindDepthBuffer(int channel);
|
||||||
|
void bindPreviousOutput(int channel);
|
||||||
|
void setOutputPlane(int channel);
|
||||||
|
void drawScreen(QOpenGLShaderProgram * prog);
|
||||||
|
void drawInternal();
|
||||||
|
void reloadShadersInternal();
|
||||||
|
QVector<int> getFreePlanes(int count);
|
||||||
|
int previousOutputPlane() const;
|
||||||
|
static void deleteShader(QOpenGLShaderProgram *& s);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool enabled_ = true;
|
||||||
|
bool is_loaded = false;
|
||||||
|
Renderer * r = nullptr;
|
||||||
|
GLint wid, hei;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
179
src/core/core/glmaterial.cpp
Normal file
179
src/core/core/glmaterial.cpp
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
/*
|
||||||
|
QGL Material
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gltexture_manager.h"
|
||||||
|
|
||||||
|
using namespace QGLEngineShaders;
|
||||||
|
|
||||||
|
|
||||||
|
Map::Map() {
|
||||||
|
bitmap_id = 0;
|
||||||
|
color_amount = 1.f;
|
||||||
|
color_offset = 0.f;
|
||||||
|
bitmap_scale = QPointF(1., 1.);
|
||||||
|
use_bitmap = false;
|
||||||
|
_changed = true;
|
||||||
|
_layer = 0;
|
||||||
|
_bitmap_hash = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Map::setBitmapPath(const QString & p) {
|
||||||
|
bitmap_path = p;
|
||||||
|
_changed = true;
|
||||||
|
_bitmap_hash = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Map::load(TextureManager * tm) {
|
||||||
|
_bitmap_hash = 0;
|
||||||
|
if (!bitmap_path.isEmpty()) tm->loadTextureImage(bitmap_path, _type == mtNormal, bake_options, &_bitmap_hash);
|
||||||
|
_changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Map::setMapLayer(TextureManager * tm) {
|
||||||
|
if (loadedBitmap())
|
||||||
|
_layer = tm->textureLayer(_bitmap_hash);
|
||||||
|
else
|
||||||
|
_layer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Map::copyToQGLMap(QGLMap & m) const {
|
||||||
|
m.amount = color_amount;
|
||||||
|
m.offset = color_offset;
|
||||||
|
m.scale = QVector2D(bitmap_scale);
|
||||||
|
if (loadedBitmap() && use_bitmap) {
|
||||||
|
m.array_index = 1;
|
||||||
|
m.map_index = _layer;
|
||||||
|
} else {
|
||||||
|
m.array_index = 0;
|
||||||
|
m.map_index = emptyMapIndex(_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLuint Map::emptyMapIndex(int type) {
|
||||||
|
switch (type) {
|
||||||
|
case mtNormal: return emrBlue;
|
||||||
|
case mtRelief: return emrBlack;
|
||||||
|
default: return emrWhite;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Material::Material(const QString _name) {
|
||||||
|
setTypes();
|
||||||
|
name = _name;
|
||||||
|
color_diffuse = Qt::white;
|
||||||
|
color_emission = Qt::black;
|
||||||
|
glass = false;
|
||||||
|
transparency = reflectivity = 0.f;
|
||||||
|
map_roughness.color_amount = 0.75f;
|
||||||
|
map_metalness.color_amount = 0.25f;
|
||||||
|
iof = 1.f;
|
||||||
|
dispersion = 0.05f;
|
||||||
|
_changed = true;
|
||||||
|
_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint Material::hash() {
|
||||||
|
return qHash(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Material::hasTransparency() const {
|
||||||
|
return float(color_diffuse.alphaF()) * (1.f - transparency) < 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Material::isMapsChanged() const {
|
||||||
|
return map_diffuse._changed || map_normal._changed || map_metalness._changed || map_roughness._changed || map_emission._changed ||
|
||||||
|
map_relief._changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Material::isMapChanged(int type) const {
|
||||||
|
switch (type) {
|
||||||
|
case mtDiffuse: return map_diffuse._changed;
|
||||||
|
case mtNormal: return map_normal._changed;
|
||||||
|
case mtMetalness: return map_metalness._changed;
|
||||||
|
case mtRoughness: return map_roughness._changed;
|
||||||
|
case mtEmission: return map_emission._changed;
|
||||||
|
case mtRelief: return map_relief._changed;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Material::load(TextureManager * tm) {
|
||||||
|
map_diffuse.load(tm);
|
||||||
|
map_normal.load(tm);
|
||||||
|
map_metalness.load(tm);
|
||||||
|
map_roughness.load(tm);
|
||||||
|
map_emission.load(tm);
|
||||||
|
map_relief.load(tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Material::setMapsLayers(TextureManager * tm) {
|
||||||
|
map_diffuse.setMapLayer(tm);
|
||||||
|
map_normal.setMapLayer(tm);
|
||||||
|
map_metalness.setMapLayer(tm);
|
||||||
|
map_roughness.setMapLayer(tm);
|
||||||
|
map_emission.setMapLayer(tm);
|
||||||
|
map_relief.setMapLayer(tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Material::setMapsChanged() {
|
||||||
|
map_diffuse._changed = true;
|
||||||
|
map_normal._changed = true;
|
||||||
|
map_metalness._changed = true;
|
||||||
|
map_roughness._changed = true;
|
||||||
|
map_emission._changed = true;
|
||||||
|
map_relief._changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Material::setTypes() {
|
||||||
|
map_diffuse._type = mtDiffuse;
|
||||||
|
map_normal._type = mtNormal;
|
||||||
|
map_metalness._type = mtMetalness;
|
||||||
|
map_roughness._type = mtRoughness;
|
||||||
|
map_emission._type = mtEmission;
|
||||||
|
map_relief._type = mtRelief;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Material::detectMaps() {
|
||||||
|
map_diffuse.use_bitmap = !map_diffuse.bitmap_path.isEmpty();
|
||||||
|
map_normal.use_bitmap = !map_normal.bitmap_path.isEmpty();
|
||||||
|
map_metalness.use_bitmap = !map_metalness.bitmap_path.isEmpty();
|
||||||
|
map_roughness.use_bitmap = !map_roughness.bitmap_path.isEmpty();
|
||||||
|
map_emission.use_bitmap = !map_emission.bitmap_path.isEmpty();
|
||||||
|
map_relief.use_bitmap = !map_relief.bitmap_path.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint MapBakeOptions::hash() const {
|
||||||
|
return qHash((uint)invert_R + ((uint)invert_G << 1) + ((uint)invert_B << 2));
|
||||||
|
}
|
||||||
168
src/core/core/glmaterial.h
Normal file
168
src/core/core/glmaterial.h
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
/*
|
||||||
|
QGL Material
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLMATERIAL_H
|
||||||
|
#define GLMATERIAL_H
|
||||||
|
|
||||||
|
#include "glshaders_types.h"
|
||||||
|
|
||||||
|
#include <chunkstream.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct QGLENGINE_CORE_EXPORT MapBakeOptions {
|
||||||
|
uint hash() const;
|
||||||
|
bool invert_R = false;
|
||||||
|
bool invert_G = false;
|
||||||
|
bool invert_B = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class QGLENGINE_CORE_EXPORT Map {
|
||||||
|
public:
|
||||||
|
Map();
|
||||||
|
void setBitmapPath(const QString & p);
|
||||||
|
void clearBitmap() { setBitmapPath(QString()); }
|
||||||
|
bool hasBitmap() const { return !bitmap_path.isEmpty(); }
|
||||||
|
bool loadedBitmap() const { return _bitmap_hash != 0; }
|
||||||
|
void load(TextureManager * tm);
|
||||||
|
void setMapLayer(TextureManager * tm);
|
||||||
|
void copyToQGLMap(QGLEngineShaders::QGLMap & m) const;
|
||||||
|
static GLuint emptyMapIndex(int type);
|
||||||
|
QString bitmap_path;
|
||||||
|
GLuint bitmap_id;
|
||||||
|
QPointF bitmap_offset;
|
||||||
|
QPointF bitmap_scale;
|
||||||
|
float color_amount;
|
||||||
|
float color_offset;
|
||||||
|
bool use_bitmap;
|
||||||
|
MapBakeOptions bake_options;
|
||||||
|
|
||||||
|
bool _changed;
|
||||||
|
int _type, _layer;
|
||||||
|
uint _bitmap_hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QGLENGINE_CORE_EXPORT Material {
|
||||||
|
public:
|
||||||
|
Material(const QString _name = QString());
|
||||||
|
uint hash();
|
||||||
|
bool hasTransparency() const;
|
||||||
|
bool isMapsChanged() const;
|
||||||
|
bool isMapChanged(int type) const;
|
||||||
|
void load(TextureManager * tm);
|
||||||
|
void setMapsLayers(TextureManager * tm);
|
||||||
|
void setMapsChanged();
|
||||||
|
void setTypes();
|
||||||
|
void detectMaps();
|
||||||
|
QString name;
|
||||||
|
QColor color_diffuse;
|
||||||
|
QColor color_emission;
|
||||||
|
bool glass;
|
||||||
|
float transparency;
|
||||||
|
float reflectivity;
|
||||||
|
float iof;
|
||||||
|
float dispersion;
|
||||||
|
Map map_diffuse;
|
||||||
|
Map map_normal;
|
||||||
|
Map map_metalness;
|
||||||
|
Map map_roughness;
|
||||||
|
Map map_emission;
|
||||||
|
Map map_relief;
|
||||||
|
bool _changed;
|
||||||
|
int _index;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline QDataStream & operator<<(QDataStream & s, const MapBakeOptions & m) {
|
||||||
|
ChunkStream cs;
|
||||||
|
cs.add(1, m.invert_R).add(2, m.invert_G).add(3, m.invert_B);
|
||||||
|
s << cs.data();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
inline QDataStream & operator>>(QDataStream & s, MapBakeOptions & m) {
|
||||||
|
ChunkStream cs(s);
|
||||||
|
cs.readAll();
|
||||||
|
cs.get(1, m.invert_R).get(2, m.invert_G).get(3, m.invert_B);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline QDataStream & operator<<(QDataStream & s, const Map & m) {
|
||||||
|
ChunkStream cs;
|
||||||
|
cs.add(1, m.bitmap_path)
|
||||||
|
.add(2, m.color_amount)
|
||||||
|
.add(3, m.color_offset)
|
||||||
|
.add(6, m.bitmap_scale)
|
||||||
|
.add(7, m.use_bitmap)
|
||||||
|
.add(11, m.bake_options);
|
||||||
|
s << cs.data();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
inline QDataStream & operator>>(QDataStream & s, Map & m) {
|
||||||
|
ChunkStream cs(s);
|
||||||
|
cs.readAll();
|
||||||
|
cs.get(1, m.bitmap_path)
|
||||||
|
.get(2, m.color_amount)
|
||||||
|
.get(3, m.color_offset)
|
||||||
|
.get(6, m.bitmap_scale)
|
||||||
|
.get(7, m.use_bitmap)
|
||||||
|
.get(11, m.bake_options);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QDataStream & operator<<(QDataStream & s, const Material * m) {
|
||||||
|
ChunkStream cs;
|
||||||
|
cs.add(1, m->name)
|
||||||
|
.add(2, m->color_diffuse)
|
||||||
|
.add(4, m->color_emission)
|
||||||
|
.add(5, m->transparency)
|
||||||
|
.add(6, m->reflectivity)
|
||||||
|
.add(7, m->glass)
|
||||||
|
.add(8, m->map_diffuse)
|
||||||
|
.add(9, m->map_normal)
|
||||||
|
.add(10, m->map_relief)
|
||||||
|
.add(11, m->map_metalness)
|
||||||
|
.add(12, m->map_roughness)
|
||||||
|
.add(13, m->map_emission);
|
||||||
|
s << (cs.data());
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
inline QDataStream & operator>>(QDataStream & s, Material *& m) {
|
||||||
|
m = new Material();
|
||||||
|
ChunkStream cs(s);
|
||||||
|
while (!cs.atEnd()) {
|
||||||
|
switch (cs.read()) {
|
||||||
|
case 1: cs.get(m->name); break;
|
||||||
|
case 2: cs.get(m->color_diffuse); break;
|
||||||
|
case 4: cs.get(m->color_emission); break;
|
||||||
|
case 5: cs.get(m->transparency); break;
|
||||||
|
case 6: cs.get(m->reflectivity); break;
|
||||||
|
case 7: cs.get(m->glass); break;
|
||||||
|
case 8: cs.get(m->map_diffuse); break;
|
||||||
|
case 9: cs.get(m->map_normal); break;
|
||||||
|
case 10: cs.get(m->map_relief); break;
|
||||||
|
case 11: cs.get(m->map_metalness); break;
|
||||||
|
case 12: cs.get(m->map_roughness); break;
|
||||||
|
case 13: cs.get(m->map_emission); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m->setTypes();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GLMATERIAL_H
|
||||||
@@ -1,56 +1,59 @@
|
|||||||
/*
|
/*
|
||||||
QGL Mesh
|
QGL Mesh
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU Lesser General Public License for more details.
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define GL_GLEXT_PROTOTYPES
|
#define GL_GLEXT_PROTOTYPES
|
||||||
#include <QOpenGLExtraFunctions>
|
|
||||||
#include "glmesh.h"
|
#include "glmesh.h"
|
||||||
|
|
||||||
#include "globject.h"
|
#include "globject.h"
|
||||||
|
|
||||||
|
#include <QOpenGLExtraFunctions>
|
||||||
#include <QTime>
|
#include <QTime>
|
||||||
|
|
||||||
using namespace QGLEngineShaders;
|
using namespace QGLEngineShaders;
|
||||||
|
|
||||||
//static int _count = 0;
|
// static int _count = 0;
|
||||||
|
|
||||||
Mesh::Mesh(GLenum geom_type_): geom_type(geom_type_),
|
Mesh::Mesh(GLenum geom_type_)
|
||||||
buffer_geom(GL_ARRAY_BUFFER, GL_STATIC_DRAW),
|
: geom_type(geom_type_)
|
||||||
buffer_ind (GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW) {
|
, buffer_geom(GL_ARRAY_BUFFER, GL_STATIC_DRAW)
|
||||||
hash_ = 0;
|
, buffer_ind(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW) {
|
||||||
|
hash_ = 0;
|
||||||
changed = hash_changed = true;
|
changed = hash_changed = true;
|
||||||
//qDebug() << "Mesh, now" << ++_count;
|
// qDebug() << "Mesh, now" << ++_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Mesh::~Mesh() {
|
Mesh::~Mesh() {
|
||||||
//qDebug() << "~Mesh, now" << --_count;
|
// qDebug() << "~Mesh, now" << --_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Mesh * Mesh::clone() {
|
Mesh * Mesh::clone() {
|
||||||
Mesh * c = new Mesh();
|
Mesh * c = new Mesh();
|
||||||
c->vertices_ = vertices_ ;
|
c->vertices_ = vertices_;
|
||||||
c->normals_ = normals_ ;
|
c->normals_ = normals_;
|
||||||
c->texcoords_ = texcoords_;
|
c->texcoords_ = texcoords_;
|
||||||
c->triangles_ = triangles_;
|
c->triangles_ = triangles_;
|
||||||
c->lines_ = lines_;
|
c->lines_ = lines_;
|
||||||
c->geom_type = geom_type;
|
c->geom_type = geom_type;
|
||||||
c->hash_ = hash_;
|
c->hash_ = hash_;
|
||||||
c->hash_changed = hash_changed;
|
c->hash_changed = hash_changed;
|
||||||
//qDebug() << "clone VBO";
|
// qDebug() << "clone VBO";
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,17 +61,27 @@ Mesh * Mesh::clone() {
|
|||||||
void Mesh::init(QOpenGLExtraFunctions * f) {
|
void Mesh::init(QOpenGLExtraFunctions * f) {
|
||||||
if (!isInit()) {
|
if (!isInit()) {
|
||||||
buffer_geom.init(f);
|
buffer_geom.init(f);
|
||||||
buffer_ind .init(f);
|
buffer_ind.init(f);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Mesh::reinit() {
|
||||||
|
buffer_geom.reinit();
|
||||||
|
buffer_ind.reinit();
|
||||||
|
QMapIterator<int, VertexObject *> it(vao_map);
|
||||||
|
while (it.hasNext())
|
||||||
|
it.next().value()->reinit();
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Mesh::destroy(QOpenGLExtraFunctions * f) {
|
void Mesh::destroy(QOpenGLExtraFunctions * f) {
|
||||||
buffer_geom.destroy(f);
|
buffer_geom.destroy(f);
|
||||||
buffer_ind .destroy(f);
|
buffer_ind.destroy(f);
|
||||||
QList<VertexObject*> vaol = vao_map.values();
|
QList<VertexObject *> vaol = vao_map.values();
|
||||||
foreach (VertexObject* vao, vaol)
|
foreach(VertexObject * vao, vaol)
|
||||||
vao->destroy(f);
|
vao->destroy(f);
|
||||||
qDeleteAll(vao_map);
|
qDeleteAll(vao_map);
|
||||||
vao_map.clear();
|
vao_map.clear();
|
||||||
@@ -78,12 +91,12 @@ void Mesh::destroy(QOpenGLExtraFunctions * f) {
|
|||||||
void Mesh::calculateNormals() {
|
void Mesh::calculateNormals() {
|
||||||
normals_.resize(vertices_.size());
|
normals_.resize(vertices_.size());
|
||||||
QVector3D dv1, dv2, n;
|
QVector3D dv1, dv2, n;
|
||||||
foreach (const Vector3i & t, triangles_) {
|
foreach(const Vector3i & t, triangles_) {
|
||||||
QVector3D & v0(vertices_[t.p0]);
|
QVector3D & v0(vertices_[t.p0]);
|
||||||
QVector3D & v1(vertices_[t.p1]);
|
QVector3D & v1(vertices_[t.p1]);
|
||||||
QVector3D & v2(vertices_[t.p2]);
|
QVector3D & v2(vertices_[t.p2]);
|
||||||
dv1 = v1 - v0, dv2 = v2 - v0;
|
dv1 = v1 - v0, dv2 = v2 - v0;
|
||||||
n = QVector3D::crossProduct(dv1, dv2).normalized();
|
n = QVector3D::crossProduct(dv1, dv2).normalized();
|
||||||
normals_[t.p0] = n;
|
normals_[t.p0] = n;
|
||||||
normals_[t.p1] = n;
|
normals_[t.p1] = n;
|
||||||
normals_[t.p2] = n;
|
normals_[t.p2] = n;
|
||||||
@@ -94,32 +107,32 @@ void Mesh::calculateNormals() {
|
|||||||
void Mesh::calculateTangents() {
|
void Mesh::calculateTangents() {
|
||||||
if (vertices_.isEmpty() || texcoords_.isEmpty()) return;
|
if (vertices_.isEmpty() || texcoords_.isEmpty()) return;
|
||||||
if (texcoords_.size() != vertices_.size()) return;
|
if (texcoords_.size() != vertices_.size()) return;
|
||||||
tangents_ .resize(vertices_.size());
|
tangents_.resize(vertices_.size());
|
||||||
bitangents_.resize(vertices_.size());
|
bitangents_.resize(vertices_.size());
|
||||||
//qDebug() << "calculateBinormals" << vcnt << tcnt << vertices_.size() << texcoords_.size() << "...";
|
// qDebug() << "calculateBinormals" << vcnt << tcnt << vertices_.size() << texcoords_.size() << "...";
|
||||||
QVector3D dv1, dv2;
|
QVector3D dv1, dv2;
|
||||||
QVector2D dt1, dt2;
|
QVector2D dt1, dt2;
|
||||||
QVector3D tan, bitan;
|
QVector3D tan, bitan;
|
||||||
foreach (const Vector3i & t, triangles_) {
|
foreach(const Vector3i & t, triangles_) {
|
||||||
QVector3D & v0(vertices_ [t.p0]);
|
QVector3D & v0(vertices_[t.p0]);
|
||||||
QVector3D & v1(vertices_ [t.p1]);
|
QVector3D & v1(vertices_[t.p1]);
|
||||||
QVector3D & v2(vertices_ [t.p2]);
|
QVector3D & v2(vertices_[t.p2]);
|
||||||
QVector2D & t0(texcoords_[t.p0]);
|
QVector2D & t0(texcoords_[t.p0]);
|
||||||
QVector2D & t1(texcoords_[t.p1]);
|
QVector2D & t1(texcoords_[t.p1]);
|
||||||
QVector2D & t2(texcoords_[t.p2]);
|
QVector2D & t2(texcoords_[t.p2]);
|
||||||
dv1 = v1 - v0, dv2 = v2 - v0;
|
dv1 = v1 - v0, dv2 = v2 - v0;
|
||||||
dt1 = t1 - t0, dt2 = t2 - t0;
|
dt1 = t1 - t0, dt2 = t2 - t0;
|
||||||
tan = (dv1 * dt2.y() - dv2 * dt1.y()).normalized();
|
tan = (dv1 * dt2.y() - dv2 * dt1.y()).normalized();
|
||||||
bitan = (dv2 * dt1.x() - dv1 * dt2.x()).normalized();
|
bitan = (dv2 * dt1.x() - dv1 * dt2.x()).normalized();
|
||||||
tangents_ [t.p0] = tan;
|
tangents_[t.p0] = tan;
|
||||||
tangents_ [t.p1] = tan;
|
tangents_[t.p1] = tan;
|
||||||
tangents_ [t.p2] = tan;
|
tangents_[t.p2] = tan;
|
||||||
bitangents_[t.p0] = bitan;
|
bitangents_[t.p0] = bitan;
|
||||||
bitangents_[t.p1] = bitan;
|
bitangents_[t.p1] = bitan;
|
||||||
bitangents_[t.p2] = bitan;
|
bitangents_[t.p2] = bitan;
|
||||||
//qDebug() << " t" << t << vi << ti << dv1.toQVector3D() << "...";
|
// qDebug() << " t" << t << vi << ti << dv1.toQVector3D() << "...";
|
||||||
}
|
}
|
||||||
//qDebug() << "calculateBinormals" << vcnt << tcnt << tangents_.size();
|
// qDebug() << "calculateBinormals" << vcnt << tcnt << tangents_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -135,8 +148,7 @@ VertexObject * Mesh::vaoByType(int type) {
|
|||||||
bool Mesh::rebuffer(QOpenGLExtraFunctions * f) {
|
bool Mesh::rebuffer(QOpenGLExtraFunctions * f) {
|
||||||
changed = false;
|
changed = false;
|
||||||
if (vertices_.isEmpty()) return true;
|
if (vertices_.isEmpty()) return true;
|
||||||
if (normals_.isEmpty())
|
if (normals_.isEmpty()) calculateNormals();
|
||||||
calculateNormals();
|
|
||||||
calculateTangents();
|
calculateTangents();
|
||||||
vert_count = qMin(vertices_.size(), normals_.size());
|
vert_count = qMin(vertices_.size(), normals_.size());
|
||||||
vert_count = qMin(vert_count, tangents_.size());
|
vert_count = qMin(vert_count, tangents_.size());
|
||||||
@@ -145,11 +157,11 @@ bool Mesh::rebuffer(QOpenGLExtraFunctions * f) {
|
|||||||
data_.resize(vert_count);
|
data_.resize(vert_count);
|
||||||
for (int i = 0; i < vert_count; ++i) {
|
for (int i = 0; i < vert_count; ++i) {
|
||||||
Vertex & v(data_[i]);
|
Vertex & v(data_[i]);
|
||||||
v.pos = vertices_ [i];
|
v.pos = vertices_[i];
|
||||||
v.normal = normals_ [i];
|
v.normal = normals_[i];
|
||||||
v.tangent = tangents_ [i];
|
v.tangent = tangents_[i];
|
||||||
v.bitangent = bitangents_[i];
|
v.bitangent = bitangents_[i];
|
||||||
v.tex = texcoords_ [i];
|
v.tex = texcoords_[i];
|
||||||
}
|
}
|
||||||
int gsize = data_.size() * sizeof(Vertex);
|
int gsize = data_.size() * sizeof(Vertex);
|
||||||
int tsize = triangles_.size() * sizeof(Vector3i);
|
int tsize = triangles_.size() * sizeof(Vector3i);
|
||||||
@@ -176,7 +188,7 @@ void Mesh::draw(QOpenGLExtraFunctions * f, int count, int type) {
|
|||||||
if (isEmpty()) return;
|
if (isEmpty()) return;
|
||||||
if (!isInit()) init(f);
|
if (!isInit()) init(f);
|
||||||
if (changed) rebuffer(f);
|
if (changed) rebuffer(f);
|
||||||
//qDebug() << "draw" << geom_type << vert_count << count;
|
// qDebug() << "draw" << geom_type << vert_count << count;
|
||||||
|
|
||||||
VertexObject * vao = vaoByType(type);
|
VertexObject * vao = vaoByType(type);
|
||||||
vao->bindBuffers(f, buffer_geom, buffer_ind);
|
vao->bindBuffers(f, buffer_geom, buffer_ind);
|
||||||
@@ -188,14 +200,14 @@ void Mesh::draw(QOpenGLExtraFunctions * f, int count, int type) {
|
|||||||
|
|
||||||
|
|
||||||
void Mesh::clear() {
|
void Mesh::clear() {
|
||||||
vertices_ .clear();
|
vertices_.clear();
|
||||||
normals_ .clear();
|
normals_.clear();
|
||||||
tangents_ .clear();
|
tangents_.clear();
|
||||||
bitangents_.clear();
|
bitangents_.clear();
|
||||||
texcoords_ .clear();
|
texcoords_.clear();
|
||||||
triangles_ .clear();
|
triangles_.clear();
|
||||||
lines_ .clear();
|
lines_.clear();
|
||||||
data_ .clear();
|
data_.clear();
|
||||||
changed = hash_changed = true;
|
changed = hash_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,23 +233,23 @@ void Mesh::loadSelections(QOpenGLExtraFunctions * f, const QVector<uchar> & sels
|
|||||||
uint Mesh::hash() const {
|
uint Mesh::hash() const {
|
||||||
if (hash_changed) {
|
if (hash_changed) {
|
||||||
hash_changed = false;
|
hash_changed = false;
|
||||||
hash_ = qHashBits(vertices_ .constData(), vertices_ .size() * sizeof(QVector3D));
|
hash_ = qHashBits(vertices_.constData(), vertices_.size() * sizeof(QVector3D));
|
||||||
hash_ ^= qHashBits(normals_ .constData(), normals_ .size() * sizeof(QVector3D));
|
hash_ ^= qHashBits(normals_.constData(), normals_.size() * sizeof(QVector3D));
|
||||||
hash_ ^= qHashBits(texcoords_.constData(), texcoords_.size() * sizeof(QVector2D));
|
hash_ ^= qHashBits(texcoords_.constData(), texcoords_.size() * sizeof(QVector2D));
|
||||||
hash_ ^= qHashBits(triangles_.constData(), triangles_.size() * sizeof( Vector3i));
|
hash_ ^= qHashBits(triangles_.constData(), triangles_.size() * sizeof(Vector3i));
|
||||||
hash_ ^= qHashBits(lines_ .constData(), lines_ .size() * sizeof( Vector2i));
|
hash_ ^= qHashBits(lines_.constData(), lines_.size() * sizeof(Vector2i));
|
||||||
}
|
}
|
||||||
return hash_;
|
return hash_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Mesh::isObjectsChanged(int type) const {
|
bool Mesh::isObjectsChanged(int type) const {
|
||||||
return (const_cast<Mesh*>(this))->vaoByType(type)->isObjectsChanged();
|
return (const_cast<Mesh *>(this))->vaoByType(type)->isObjectsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Mesh::isSelectionChanged(int type) const {
|
bool Mesh::isSelectionChanged(int type) const {
|
||||||
return (const_cast<Mesh*>(this))->vaoByType(type)->isSelectionChanged();
|
return (const_cast<Mesh *>(this))->vaoByType(type)->isSelectionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -252,14 +264,14 @@ void Mesh::setSelectionChanged(int type, bool yes) {
|
|||||||
|
|
||||||
|
|
||||||
void Mesh::setAllObjectsChanged(bool yes) {
|
void Mesh::setAllObjectsChanged(bool yes) {
|
||||||
QMapIterator<int, VertexObject * > it(vao_map);
|
QMapIterator<int, VertexObject *> it(vao_map);
|
||||||
while (it.hasNext())
|
while (it.hasNext())
|
||||||
it.next().value()->setObjectsChanged(yes);
|
it.next().value()->setObjectsChanged(yes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Mesh::setAllSelectionChanged(bool yes) {
|
void Mesh::setAllSelectionChanged(bool yes) {
|
||||||
QMapIterator<int, VertexObject * > it(vao_map);
|
QMapIterator<int, VertexObject *> it(vao_map);
|
||||||
while (it.hasNext())
|
while (it.hasNext())
|
||||||
it.next().value()->setSelectionChanged(yes);
|
it.next().value()->setSelectionChanged(yes);
|
||||||
}
|
}
|
||||||
@@ -291,8 +303,7 @@ void Mesh::transformPoints(const QMatrix4x4 & mat) {
|
|||||||
int vcnt = vertices_.size(), ncnt = normals_.size();
|
int vcnt = vertices_.size(), ncnt = normals_.size();
|
||||||
for (int i = 0; i < vcnt; ++i) {
|
for (int i = 0; i < vcnt; ++i) {
|
||||||
vertices_[i] = (mat * QVector4D(vertices_[i], 1)).toVector3D();
|
vertices_[i] = (mat * QVector4D(vertices_[i], 1)).toVector3D();
|
||||||
if (i < ncnt)
|
if (i < ncnt) normals_[i] = (mat * QVector4D(normals_[i], 0)).toVector3D();
|
||||||
normals_[i] = (mat * QVector4D(normals_[i], 0)).toVector3D();
|
|
||||||
}
|
}
|
||||||
changed = hash_changed = true;
|
changed = hash_changed = true;
|
||||||
}
|
}
|
||||||
@@ -301,7 +312,7 @@ void Mesh::transformPoints(const QMatrix4x4 & mat) {
|
|||||||
void Mesh::flipNormals() {
|
void Mesh::flipNormals() {
|
||||||
if (vertices_.isEmpty()) return;
|
if (vertices_.isEmpty()) return;
|
||||||
for (int i = 0; i < triangles_.size(); ++i)
|
for (int i = 0; i < triangles_.size(); ++i)
|
||||||
piSwap(triangles_[i].p1, triangles_[i].p2);
|
piSwap(triangles_[i].p0, triangles_[i].p1);
|
||||||
for (int i = 0; i < lines_.size(); ++i)
|
for (int i = 0; i < lines_.size(); ++i)
|
||||||
piSwap(lines_[i].p0, lines_[i].p1);
|
piSwap(lines_[i].p0, lines_[i].p1);
|
||||||
int ncnt = normals_.size();
|
int ncnt = normals_.size();
|
||||||
@@ -316,8 +327,8 @@ void Mesh::append(const Mesh * m) {
|
|||||||
if (m->isEmpty()) return;
|
if (m->isEmpty()) return;
|
||||||
if (normals_.isEmpty()) calculateNormals();
|
if (normals_.isEmpty()) calculateNormals();
|
||||||
int vcnt = vertices_.size();
|
int vcnt = vertices_.size();
|
||||||
vertices_ .append(m->vertices_ );
|
vertices_.append(m->vertices_);
|
||||||
normals_ .append(m->normals_ );
|
normals_.append(m->normals_);
|
||||||
texcoords_.append(m->texcoords_);
|
texcoords_.append(m->texcoords_);
|
||||||
QVector<Vector3i> tri = m->triangles_;
|
QVector<Vector3i> tri = m->triangles_;
|
||||||
for (int i = 0; i < tri.size(); ++i)
|
for (int i = 0; i < tri.size(); ++i)
|
||||||
@@ -368,7 +379,7 @@ bool Mesh::loadFromFile(const QString & filename) {
|
|||||||
Box3D Mesh::boundingBox() const {
|
Box3D Mesh::boundingBox() const {
|
||||||
if (vertices_.isEmpty()) return Box3D();
|
if (vertices_.isEmpty()) return Box3D();
|
||||||
int vcnt = vertices_.size();
|
int vcnt = vertices_.size();
|
||||||
//qDebug() << "calculateBinormals" << vcnt << tcnt << vertices_.size() << texcoords_.size() << "...";
|
// qDebug() << "calculateBinormals" << vcnt << tcnt << vertices_.size() << texcoords_.size() << "...";
|
||||||
GLfloat mix, miy, miz, max, may, maz;
|
GLfloat mix, miy, miz, max, may, maz;
|
||||||
QVector3D v0(vertices_[0]);
|
QVector3D v0(vertices_[0]);
|
||||||
mix = max = v0.x();
|
mix = max = v0.x();
|
||||||
@@ -384,9 +395,9 @@ Box3D Mesh::boundingBox() const {
|
|||||||
if (miz > v.z()) miz = v.z();
|
if (miz > v.z()) miz = v.z();
|
||||||
if (maz < v.z()) maz = v.z();
|
if (maz < v.z()) maz = v.z();
|
||||||
}
|
}
|
||||||
bound.x = mix;
|
bound.x = mix;
|
||||||
bound.y = miy;
|
bound.y = miy;
|
||||||
bound.z = miz;
|
bound.z = miz;
|
||||||
bound.length = max - mix;
|
bound.length = max - mix;
|
||||||
bound.width = may - miy;
|
bound.width = may - miy;
|
||||||
bound.height = maz - miz;
|
bound.height = maz - miz;
|
||||||
@@ -394,26 +405,26 @@ Box3D Mesh::boundingBox() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QDataStream & operator <<(QDataStream & s, const Mesh * m) {
|
QDataStream & operator<<(QDataStream & s, const Mesh * m) {
|
||||||
ChunkStream cs;
|
ChunkStream cs;
|
||||||
//qDebug() << "place VBO" << m.vertices_.size() << m.normals_.size() << m.texcoords_.size() << m.colors_.size() << "...";
|
// qDebug() << "place VBO" << m.vertices_.size() << m.normals_.size() << m.texcoords_.size() << m.colors_.size() << "...";
|
||||||
cs.add(1, m->vertices_).add(2, m->normals_).add(3, m->texcoords_)
|
cs.add(1, m->vertices_).add(2, m->normals_).add(3, m->texcoords_).add(6, m->triangles_).add(7, m->lines_).add(10, int(m->geom_type));
|
||||||
.add(6, m->triangles_).add(7, m->lines_).add(10, int(m->geom_type));
|
// qDebug() << "place VBO done" << cs.data().size() << "...";
|
||||||
//qDebug() << "place VBO done" << cs.data().size() << "...";
|
s << cs.data();
|
||||||
s << cs.data(); return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QDataStream & operator >>(QDataStream & s, Mesh *& m) {
|
QDataStream & operator>>(QDataStream & s, Mesh *& m) {
|
||||||
m = new Mesh();
|
m = new Mesh();
|
||||||
ChunkStream cs(s);
|
ChunkStream cs(s);
|
||||||
while (!cs.atEnd()) {
|
while (!cs.atEnd()) {
|
||||||
switch (cs.read()) {
|
switch (cs.read()) {
|
||||||
case 1 : cs.get(m->vertices_ ); break;
|
case 1: cs.get(m->vertices_); break;
|
||||||
case 2 : cs.get(m->normals_ ); break;
|
case 2: cs.get(m->normals_); break;
|
||||||
case 3 : cs.get(m->texcoords_); break;
|
case 3: cs.get(m->texcoords_); break;
|
||||||
case 6 : cs.get(m->triangles_); break;
|
case 6: cs.get(m->triangles_); break;
|
||||||
case 7 : cs.get(m->lines_ ); break;
|
case 7: cs.get(m->lines_); break;
|
||||||
case 10: m->geom_type = cs.getData<int>(); break;
|
case 10: m->geom_type = cs.getData<int>(); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
123
src/core/core/glmesh.h
Normal file
123
src/core/core/glmesh.h
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
QGL Mesh
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLMESH_H
|
||||||
|
#define GLMESH_H
|
||||||
|
|
||||||
|
#include "glvertexobject.h"
|
||||||
|
|
||||||
|
#include <chunkstream.h>
|
||||||
|
|
||||||
|
|
||||||
|
class QGLENGINE_CORE_EXPORT Mesh {
|
||||||
|
friend QDataStream & operator<<(QDataStream & s, const Mesh * m);
|
||||||
|
friend QDataStream & operator>>(QDataStream & s, Mesh *& m);
|
||||||
|
|
||||||
|
public:
|
||||||
|
Mesh(GLenum geom_type_ = GL_TRIANGLES);
|
||||||
|
~Mesh();
|
||||||
|
|
||||||
|
Mesh * clone();
|
||||||
|
|
||||||
|
void init(QOpenGLExtraFunctions * f);
|
||||||
|
void destroy(QOpenGLExtraFunctions * f);
|
||||||
|
bool rebuffer(QOpenGLExtraFunctions * f);
|
||||||
|
void draw(QOpenGLExtraFunctions * f, int count, int type = 0);
|
||||||
|
void reinit();
|
||||||
|
void clear();
|
||||||
|
void loadObject(QOpenGLExtraFunctions * f, const QGLEngineShaders::Object & object, int type = 0);
|
||||||
|
void loadObjects(QOpenGLExtraFunctions * f, const QVector<QGLEngineShaders::Object> & objects, int type = 0);
|
||||||
|
void loadSelections(QOpenGLExtraFunctions * f, const QVector<uchar> & sels, int type = 0);
|
||||||
|
|
||||||
|
int verticesCount() const { return vertices_.size(); }
|
||||||
|
int trianglesCount() const { return triangles_.size(); }
|
||||||
|
int linesCount() const { return lines_.size(); }
|
||||||
|
bool isInit() const { return buffer_geom.isInit(); }
|
||||||
|
bool isEmpty() const { return vertices_.isEmpty(); }
|
||||||
|
uint hash() const;
|
||||||
|
|
||||||
|
bool isObjectsChanged(int type = 0) const;
|
||||||
|
bool isSelectionChanged(int type = 0) const;
|
||||||
|
void setObjectsChanged(int type = 0, bool yes = true);
|
||||||
|
void setSelectionChanged(int type = 0, bool yes = true);
|
||||||
|
void setAllObjectsChanged(bool yes = true);
|
||||||
|
void setAllSelectionChanged(bool yes = true);
|
||||||
|
|
||||||
|
QVector<QVector3D> & vertices() {
|
||||||
|
changed = hash_changed = true;
|
||||||
|
return vertices_;
|
||||||
|
}
|
||||||
|
QVector<QVector3D> & normals() {
|
||||||
|
changed = hash_changed = true;
|
||||||
|
return normals_;
|
||||||
|
}
|
||||||
|
QVector<QVector2D> & texcoords() {
|
||||||
|
changed = hash_changed = true;
|
||||||
|
return texcoords_;
|
||||||
|
}
|
||||||
|
QVector<Vector3i> & indicesTriangles() {
|
||||||
|
changed = hash_changed = true;
|
||||||
|
return triangles_;
|
||||||
|
}
|
||||||
|
QVector<Vector2i> & indicesLines() {
|
||||||
|
changed = hash_changed = true;
|
||||||
|
return lines_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void translatePoints(const QVector3D & dp);
|
||||||
|
void translatePoints(const double & x, const double & y, const double & z) { translatePoints(QVector3D(x, y, z)); }
|
||||||
|
void scalePoints(const QVector3D & dp);
|
||||||
|
void scalePoints(const double & s) { scalePoints(QVector3D(s, s, s)); }
|
||||||
|
void rotatePoints(const double & angle, const QVector3D & a);
|
||||||
|
void rotatePoints(const double & angle, const double & x, const double & y, const double & z) {
|
||||||
|
rotatePoints(angle, QVector3D(x, y, z));
|
||||||
|
}
|
||||||
|
void transformPoints(const QMatrix4x4 & mat);
|
||||||
|
void flipNormals();
|
||||||
|
void append(const Mesh * m);
|
||||||
|
|
||||||
|
bool saveToFile(const QString & filename);
|
||||||
|
bool loadFromFile(const QString & filename);
|
||||||
|
|
||||||
|
Box3D boundingBox() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void calculateNormals();
|
||||||
|
void calculateTangents();
|
||||||
|
VertexObject * vaoByType(int type);
|
||||||
|
|
||||||
|
QVector<QVector3D> vertices_, normals_, tangents_, bitangents_;
|
||||||
|
QVector<QVector2D> texcoords_;
|
||||||
|
QVector<Vector3i> triangles_;
|
||||||
|
QVector<Vector2i> lines_;
|
||||||
|
|
||||||
|
QVector<QGLEngineShaders::Vertex> data_;
|
||||||
|
GLenum geom_type;
|
||||||
|
Buffer buffer_geom, buffer_ind;
|
||||||
|
QMap<int, VertexObject *> vao_map;
|
||||||
|
mutable uint hash_;
|
||||||
|
mutable bool hash_changed;
|
||||||
|
int vert_count;
|
||||||
|
bool changed;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
QGLENGINE_CORE_EXPORT QDataStream & operator<<(QDataStream & s, const Mesh * m);
|
||||||
|
QGLENGINE_CORE_EXPORT QDataStream & operator>>(QDataStream & s, Mesh *& m);
|
||||||
|
|
||||||
|
#endif // GLMESH_H
|
||||||
@@ -1,54 +1,67 @@
|
|||||||
/*
|
/*
|
||||||
QGL Primitives
|
QGL Primitives
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU Lesser General Public License for more details.
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "glprimitives.h"
|
#include "glprimitives.h"
|
||||||
|
|
||||||
#include "glmesh.h"
|
#include "glmesh.h"
|
||||||
|
|
||||||
|
|
||||||
Mesh * Primitive::plane(float width, float length) {
|
Mesh * Primitive::plane(float width, float length, int width_segments, int length_segments) {
|
||||||
Mesh * ret = new Mesh();
|
Mesh * ret = new Mesh();
|
||||||
QVector<QVector3D> & v(ret->vertices ());
|
QVector<QVector3D> & v(ret->vertices());
|
||||||
QVector<QVector3D> & n(ret->normals ());
|
QVector<QVector3D> & n(ret->normals());
|
||||||
QVector<QVector2D> & t(ret->texcoords());
|
QVector<QVector2D> & t(ret->texcoords());
|
||||||
QVector< Vector3i> & i(ret->indicesTriangles ());
|
QVector<Vector3i> & i(ret->indicesTriangles());
|
||||||
float hw = width / 2.f, hl = length / 2.f;
|
float hw = width / 2.f, hl = length / 2.f;
|
||||||
for (int j = 0; j < 4; ++j) n << QVector3D(0., 0., 1.);
|
float w1 = 1.f / width_segments, l1 = 1.f / length_segments;
|
||||||
t << QVector2D(0., 0.) << QVector2D(0., 1.) << QVector2D(1., 1.) << QVector2D(1., 0.);
|
int sind = 0;
|
||||||
v << QVector3D(-hw, -hl, 0.) << QVector3D(-hw, hl, 0.) << QVector3D(hw, hl, 0.) << QVector3D(hw, -hl, 0.);
|
for (int wi = 0; wi < width_segments; ++wi) {
|
||||||
i << Vector3i(0, 2, 1) << Vector3i(0, 3, 2);
|
for (int li = 0; li < length_segments; ++li) {
|
||||||
|
for (int j = 0; j < 4; ++j)
|
||||||
|
n << QVector3D(0., 0., 1.);
|
||||||
|
float ws = (float)wi / width_segments;
|
||||||
|
float ls = (float)li / length_segments;
|
||||||
|
t << QVector2D(ws, ls) << QVector2D(ws, ls + l1) << QVector2D(ws + w1, ls + l1) << QVector2D(ws + w1, ls);
|
||||||
|
v << QVector3D(ws * width - hw, ls * length - hl, 0.) << QVector3D(ws * width - hw, (ls + l1) * length - hl, 0.)
|
||||||
|
<< QVector3D((ws + w1) * width - hw, (ls + l1) * length - hl, 0.) << QVector3D((ws + w1) * width - hw, ls * length - hl, 0.);
|
||||||
|
i << Vector3i(sind + 0, sind + 2, sind + 1) << Vector3i(sind + 0, sind + 3, sind + 2);
|
||||||
|
sind += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Mesh * Primitive::cube(float width, float length, float height) {
|
Mesh * Primitive::cube(float width, float length, float height, int width_segments, int length_segments, int height_segments) {
|
||||||
Mesh * ret = new Mesh();
|
Mesh * ret = new Mesh();
|
||||||
QVector3D scale(width, length, height);
|
QVector3D scale(width, length, height);
|
||||||
QVector<QVector3D> & v(ret->vertices ());
|
QVector<QVector3D> & v(ret->vertices());
|
||||||
QVector<QVector3D> & n(ret->normals ());
|
QVector<QVector3D> & n(ret->normals());
|
||||||
QVector<QVector2D> & t(ret->texcoords());
|
QVector<QVector2D> & t(ret->texcoords());
|
||||||
QVector< Vector3i> & i(ret->indicesTriangles ());
|
QVector<Vector3i> & i(ret->indicesTriangles());
|
||||||
float hs = 0.5f;
|
float hs = 0.5f;
|
||||||
int si = 0;
|
int si = 0;
|
||||||
QMatrix4x4 mat;
|
QMatrix4x4 mat;
|
||||||
|
|
||||||
si = v.size();
|
si = v.size();
|
||||||
for (int j = 0; j < 4; ++j) n << QVector3D(0., -1., 0.);
|
for (int j = 0; j < 4; ++j)
|
||||||
t << QVector2D(0., 0.) << QVector2D(1., 0.) << QVector2D(1., 1.) << QVector2D(0., 1.);
|
n << QVector3D(0., -1., 0.);
|
||||||
|
t << QVector2D(0., 0.) << QVector2D(1., 0.) << QVector2D(1., 1.) << QVector2D(0., 1.);
|
||||||
v << QVector3D(-hs, -hs, -hs) << QVector3D(hs, -hs, -hs) << QVector3D(hs, -hs, hs) << QVector3D(-hs, -hs, hs);
|
v << QVector3D(-hs, -hs, -hs) << QVector3D(hs, -hs, -hs) << QVector3D(hs, -hs, hs) << QVector3D(-hs, -hs, hs);
|
||||||
i << Vector3i(si + 0, si + 1, si + 2) << Vector3i(si + 0, si + 2, si + 3);
|
i << Vector3i(si + 0, si + 1, si + 2) << Vector3i(si + 0, si + 2, si + 3);
|
||||||
|
|
||||||
@@ -60,21 +73,21 @@ Mesh * Primitive::cube(float width, float length, float height) {
|
|||||||
n << cn;
|
n << cn;
|
||||||
v << mat.map(QVector4D(v[j])).toVector3D();
|
v << mat.map(QVector4D(v[j])).toVector3D();
|
||||||
}
|
}
|
||||||
t << QVector2D(0., 0.) << QVector2D(1., 0.) << QVector2D(1., 1.) << QVector2D(0., 1.);
|
t << QVector2D(0., 0.) << QVector2D(1., 0.) << QVector2D(1., 1.) << QVector2D(0., 1.);
|
||||||
i << Vector3i(si + 0, si + 1, si + 2) << Vector3i(si + 0, si + 2, si + 3);
|
i << Vector3i(si + 0, si + 1, si + 2) << Vector3i(si + 0, si + 2, si + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
mat.setToIdentity();
|
mat.setToIdentity();
|
||||||
mat.rotate(90., 1., 0.,0.);
|
mat.rotate(90., 1., 0., 0.);
|
||||||
for (int r = 0; r < 2; ++r) {
|
for (int r = 0; r < 2; ++r) {
|
||||||
si = v.size();
|
si = v.size();
|
||||||
mat.rotate(180., 1., 0.,0.);
|
mat.rotate(180., 1., 0., 0.);
|
||||||
QVector3D cn = mat.map(n[0]);
|
QVector3D cn = mat.map(n[0]);
|
||||||
for (int j = 0; j < 4; ++j) {
|
for (int j = 0; j < 4; ++j) {
|
||||||
n << cn;
|
n << cn;
|
||||||
v << mat.map(QVector4D(v[j])).toVector3D();
|
v << mat.map(QVector4D(v[j])).toVector3D();
|
||||||
}
|
}
|
||||||
t << QVector2D(0., 0.) << QVector2D(1., 0.) << QVector2D(1., 1.) << QVector2D(0., 1.);
|
t << QVector2D(0., 0.) << QVector2D(1., 0.) << QVector2D(1., 1.) << QVector2D(0., 1.);
|
||||||
i << Vector3i(si + 0, si + 1, si + 2) << Vector3i(si + 0, si + 2, si + 3);
|
i << Vector3i(si + 0, si + 1, si + 2) << Vector3i(si + 0, si + 2, si + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,10 +100,10 @@ Mesh * Primitive::cube(float width, float length, float height) {
|
|||||||
|
|
||||||
Mesh * Primitive::ellipsoid(int segments_wl, int segments_h, float radius, float end_angle) {
|
Mesh * Primitive::ellipsoid(int segments_wl, int segments_h, float radius, float end_angle) {
|
||||||
Mesh * ret = new Mesh();
|
Mesh * ret = new Mesh();
|
||||||
QVector<QVector3D> & v(ret->vertices ());
|
QVector<QVector3D> & v(ret->vertices());
|
||||||
QVector<QVector3D> & n(ret->normals ());
|
QVector<QVector3D> & n(ret->normals());
|
||||||
QVector<QVector2D> & t(ret->texcoords());
|
QVector<QVector2D> & t(ret->texcoords());
|
||||||
QVector< Vector3i> & ind(ret->indicesTriangles());
|
QVector<Vector3i> & ind(ret->indicesTriangles());
|
||||||
int hseg = segments_h + 1, wlseg = segments_wl + 1;
|
int hseg = segments_h + 1, wlseg = segments_wl + 1;
|
||||||
double crw, crl, a, ch, twl;
|
double crw, crl, a, ch, twl;
|
||||||
double eang = deg2rad * end_angle;
|
double eang = deg2rad * end_angle;
|
||||||
@@ -99,16 +112,16 @@ Mesh * Primitive::ellipsoid(int segments_wl, int segments_h, float radius, float
|
|||||||
for (int i = 0; i <= hseg; i++) {
|
for (int i = 0; i <= hseg; i++) {
|
||||||
ch = -cos((double)i / hseg * M_PI);
|
ch = -cos((double)i / hseg * M_PI);
|
||||||
cp.setZ(ch * radius);
|
cp.setZ(ch * radius);
|
||||||
twl = sqrt(1. - ch * ch);
|
twl = sqrt(1. - ch * ch);
|
||||||
crw = twl * radius;
|
crw = twl * radius;
|
||||||
crl = twl * radius;
|
crl = twl * radius;
|
||||||
int cvcnt = wlseg * 2;
|
int cvcnt = wlseg * 2;
|
||||||
for (int j = 0; j < cvcnt; j++) {
|
for (int j = 0; j < cvcnt; j++) {
|
||||||
a = (double)j / (cvcnt - 1) * eang;
|
a = (double)j / (cvcnt - 1) * eang;
|
||||||
cp.setX(crl * cos(a));
|
cp.setX(crl * cos(a));
|
||||||
cp.setY(crw * sin(a));
|
cp.setY(crw * sin(a));
|
||||||
v << cp;
|
v << cp;
|
||||||
t << QVector2D((double)j / (cvcnt - 1), ch/2.f + 0.5f);
|
t << QVector2D((double)j / (cvcnt - 1), ch / 2.f + 0.5f);
|
||||||
n << cp.normalized();
|
n << cp.normalized();
|
||||||
int si = v.size() - 1;
|
int si = v.size() - 1;
|
||||||
if (j > 0 && i > 0) {
|
if (j > 0 && i > 0) {
|
||||||
@@ -118,7 +131,7 @@ Mesh * Primitive::ellipsoid(int segments_wl, int segments_h, float radius, float
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (end_angle < 360.) {
|
if (end_angle < 360.) {
|
||||||
Mesh * cap = Primitive::disc(segments_h+1, radius, 180);
|
Mesh * cap = Primitive::disc(segments_h + 1, radius, 180);
|
||||||
cap->rotatePoints(90, 0, 1, 0);
|
cap->rotatePoints(90, 0, 1, 0);
|
||||||
cap->rotatePoints(-90, 0, 0, 1);
|
cap->rotatePoints(-90, 0, 0, 1);
|
||||||
ret->append(cap);
|
ret->append(cap);
|
||||||
@@ -133,10 +146,10 @@ Mesh * Primitive::ellipsoid(int segments_wl, int segments_h, float radius, float
|
|||||||
|
|
||||||
Mesh * Primitive::disc(int segments, float radius, float end_angle) {
|
Mesh * Primitive::disc(int segments, float radius, float end_angle) {
|
||||||
Mesh * ret = new Mesh();
|
Mesh * ret = new Mesh();
|
||||||
QVector<QVector3D> & v(ret->vertices ());
|
QVector<QVector3D> & v(ret->vertices());
|
||||||
QVector<QVector3D> & n(ret->normals ());
|
QVector<QVector3D> & n(ret->normals());
|
||||||
QVector<QVector2D> & t(ret->texcoords());
|
QVector<QVector2D> & t(ret->texcoords());
|
||||||
QVector< Vector3i> & ind(ret->indicesTriangles());
|
QVector<Vector3i> & ind(ret->indicesTriangles());
|
||||||
|
|
||||||
segments = qMax(segments + 1, 4);
|
segments = qMax(segments + 1, 4);
|
||||||
QVector3D cp;
|
QVector3D cp;
|
||||||
@@ -173,10 +186,10 @@ QVector3D coneNormal(double r, double height, double ang) {
|
|||||||
|
|
||||||
Mesh * Primitive::cone(int segments, float radius, float height) {
|
Mesh * Primitive::cone(int segments, float radius, float height) {
|
||||||
Mesh * ret = new Mesh();
|
Mesh * ret = new Mesh();
|
||||||
QVector<QVector3D> & v(ret->vertices ());
|
QVector<QVector3D> & v(ret->vertices());
|
||||||
QVector<QVector3D> & n(ret->normals ());
|
QVector<QVector3D> & n(ret->normals());
|
||||||
QVector<QVector2D> & t(ret->texcoords());
|
QVector<QVector2D> & t(ret->texcoords());
|
||||||
QVector< Vector3i> & ind(ret->indicesTriangles());
|
QVector<Vector3i> & ind(ret->indicesTriangles());
|
||||||
|
|
||||||
int seg = qMax(segments + 1, 4);
|
int seg = qMax(segments + 1, 4);
|
||||||
QVector3D cp;
|
QVector3D cp;
|
||||||
@@ -194,8 +207,7 @@ Mesh * Primitive::cone(int segments, float radius, float height) {
|
|||||||
t << QVector2D((double)i / (seg - 1), 0.f);
|
t << QVector2D((double)i / (seg - 1), 0.f);
|
||||||
n << coneNormal(radius, height, a);
|
n << coneNormal(radius, height, a);
|
||||||
int si = v.size() - 1;
|
int si = v.size() - 1;
|
||||||
if (i > 0)
|
if (i > 0) ind << Vector3i(si - 1, si - 2, si);
|
||||||
ind << Vector3i(si - 1, si - 2, si);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh * cap = Primitive::disc(segments, radius);
|
Mesh * cap = Primitive::disc(segments, radius);
|
||||||
@@ -209,10 +221,10 @@ Mesh * Primitive::cone(int segments, float radius, float height) {
|
|||||||
|
|
||||||
Mesh * Primitive::cylinder(int segments, float radius, float height, float end_angle) {
|
Mesh * Primitive::cylinder(int segments, float radius, float height, float end_angle) {
|
||||||
Mesh * ret = new Mesh();
|
Mesh * ret = new Mesh();
|
||||||
QVector<QVector3D> & v(ret->vertices ());
|
QVector<QVector3D> & v(ret->vertices());
|
||||||
QVector<QVector3D> & n(ret->normals ());
|
QVector<QVector3D> & n(ret->normals());
|
||||||
QVector<QVector2D> & t(ret->texcoords());
|
QVector<QVector2D> & t(ret->texcoords());
|
||||||
QVector< Vector3i> & ind(ret->indicesTriangles());
|
QVector<Vector3i> & ind(ret->indicesTriangles());
|
||||||
|
|
||||||
int seg = qMax(segments + 1, 4);
|
int seg = qMax(segments + 1, 4);
|
||||||
QVector3D cp, norm;
|
QVector3D cp, norm;
|
||||||
@@ -229,7 +241,8 @@ Mesh * Primitive::cylinder(int segments, float radius, float height, float end_a
|
|||||||
v << cp;
|
v << cp;
|
||||||
t << QVector2D((double)i / (seg - 1), 0.f);
|
t << QVector2D((double)i / (seg - 1), 0.f);
|
||||||
t << QVector2D((double)i / (seg - 1), 1.f);
|
t << QVector2D((double)i / (seg - 1), 1.f);
|
||||||
n << norm; n << norm;
|
n << norm;
|
||||||
|
n << norm;
|
||||||
int si = v.size() - 1;
|
int si = v.size() - 1;
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
ind << Vector3i(si - 2, si - 1, si);
|
ind << Vector3i(si - 2, si - 1, si);
|
||||||
@@ -248,7 +261,7 @@ Mesh * Primitive::cylinder(int segments, float radius, float height, float end_a
|
|||||||
if (end_angle < 360.) {
|
if (end_angle < 360.) {
|
||||||
Mesh * cap = Primitive::plane(radius, height);
|
Mesh * cap = Primitive::plane(radius, height);
|
||||||
cap->rotatePoints(90, 1, 0, 0);
|
cap->rotatePoints(90, 1, 0, 0);
|
||||||
cap->translatePoints(radius/2, 0, height/2);
|
cap->translatePoints(radius / 2, 0, height / 2);
|
||||||
ret->append(cap);
|
ret->append(cap);
|
||||||
cap->flipNormals();
|
cap->flipNormals();
|
||||||
cap->rotatePoints(end_angle, 0, 0, 1);
|
cap->rotatePoints(end_angle, 0, 0, 1);
|
||||||
@@ -263,8 +276,8 @@ Mesh * Primitive::cylinder(int segments, float radius, float height, float end_a
|
|||||||
Mesh * Primitive::arrow(int segments, float thick, float angle) {
|
Mesh * Primitive::arrow(int segments, float thick, float angle) {
|
||||||
double cone_r = 1.5 * thick;
|
double cone_r = 1.5 * thick;
|
||||||
double cone_h = 2. * cone_r / tan(angle * deg2rad);
|
double cone_h = 2. * cone_r / tan(angle * deg2rad);
|
||||||
Mesh * ret = new Mesh();
|
Mesh * ret = new Mesh();
|
||||||
Mesh * m = Primitive::cylinder(segments, thick / 2., 1. - cone_h);
|
Mesh * m = Primitive::cylinder(segments, thick / 2., 1. - cone_h);
|
||||||
ret->append(m);
|
ret->append(m);
|
||||||
delete m;
|
delete m;
|
||||||
m = Primitive::cone(segments, cone_r, cone_h);
|
m = Primitive::cone(segments, cone_r, cone_h);
|
||||||
@@ -277,10 +290,10 @@ Mesh * Primitive::arrow(int segments, float thick, float angle) {
|
|||||||
|
|
||||||
Mesh * Primitive::torus(int segments_main, int segments_second, float radius_main, float radius_second, float end_angle) {
|
Mesh * Primitive::torus(int segments_main, int segments_second, float radius_main, float radius_second, float end_angle) {
|
||||||
Mesh * ret = new Mesh();
|
Mesh * ret = new Mesh();
|
||||||
QVector<QVector3D> & v(ret->vertices ());
|
QVector<QVector3D> & v(ret->vertices());
|
||||||
QVector<QVector3D> & n(ret->normals ());
|
QVector<QVector3D> & n(ret->normals());
|
||||||
QVector<QVector2D> & t(ret->texcoords());
|
QVector<QVector2D> & t(ret->texcoords());
|
||||||
QVector< Vector3i> & ind(ret->indicesTriangles());
|
QVector<Vector3i> & ind(ret->indicesTriangles());
|
||||||
|
|
||||||
QVector<QVector3D> cv, cn;
|
QVector<QVector3D> cv, cn;
|
||||||
QVector<QVector2D> ct;
|
QVector<QVector2D> ct;
|
||||||
@@ -315,7 +328,7 @@ Mesh * Primitive::torus(int segments_main, int segments_second, float radius_mai
|
|||||||
pcnt = v.size();
|
pcnt = v.size();
|
||||||
}
|
}
|
||||||
if (end_angle < 360.) {
|
if (end_angle < 360.) {
|
||||||
Mesh * cap = Primitive::disc(segments_second-1, radius_second);
|
Mesh * cap = Primitive::disc(segments_second - 1, radius_second);
|
||||||
cap->rotatePoints(90, 1, 0, 0);
|
cap->rotatePoints(90, 1, 0, 0);
|
||||||
cap->translatePoints(radius_main, 0, 0);
|
cap->translatePoints(radius_main, 0, 0);
|
||||||
ret->append(cap);
|
ret->append(cap);
|
||||||
@@ -328,22 +341,20 @@ Mesh * Primitive::torus(int segments_main, int segments_second, float radius_mai
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Mesh * Primitive::cubeFrame(float width, float length, float height) {
|
Mesh * Primitive::cubeFrame(float width, float length, float height) {
|
||||||
Mesh * ret = new Mesh(GL_LINES);
|
Mesh * ret = new Mesh(GL_LINES);
|
||||||
QVector3D scale(width, length, height);
|
QVector3D scale(width, length, height);
|
||||||
QVector<QVector3D> & v(ret->vertices ());
|
QVector<QVector3D> & v(ret->vertices());
|
||||||
QVector<QVector3D> & n(ret->normals ());
|
QVector<QVector3D> & n(ret->normals());
|
||||||
QVector<QVector2D> & t(ret->texcoords());
|
QVector<QVector2D> & t(ret->texcoords());
|
||||||
QVector< Vector2i> & i(ret->indicesLines());
|
QVector<Vector2i> & i(ret->indicesLines());
|
||||||
float hs = 0.5f;
|
float hs = 0.5f;
|
||||||
v << QVector3D(-hs, -hs, -hs) << QVector3D(-hs, hs, -hs) << QVector3D( hs, hs, -hs) << QVector3D( hs, -hs, -hs);
|
v << QVector3D(-hs, -hs, -hs) << QVector3D(-hs, hs, -hs) << QVector3D(hs, hs, -hs) << QVector3D(hs, -hs, -hs);
|
||||||
v << QVector3D(-hs, -hs, hs) << QVector3D(-hs, hs, hs) << QVector3D( hs, hs, hs) << QVector3D( hs, -hs, hs);
|
v << QVector3D(-hs, -hs, hs) << QVector3D(-hs, hs, hs) << QVector3D(hs, hs, hs) << QVector3D(hs, -hs, hs);
|
||||||
for (int j = 0; j < 8; ++j) {
|
for (int j = 0; j < 8; ++j) {
|
||||||
v[j] *= scale;
|
v[j] *= scale;
|
||||||
t << QVector2D(0, 0);
|
t << QVector2D(0, 0);
|
||||||
n << QVector3D(0,0,1);
|
n << QVector3D(0, 0, 1);
|
||||||
}
|
}
|
||||||
for (int j = 0; j < 4; ++j) {
|
for (int j = 0; j < 4; ++j) {
|
||||||
i << Vector2i(j, (j + 1) % 4);
|
i << Vector2i(j, (j + 1) % 4);
|
||||||
@@ -356,10 +367,10 @@ Mesh * Primitive::cubeFrame(float width, float length, float height) {
|
|||||||
|
|
||||||
Mesh * Primitive::ellipsoidFrame(int segments_wl, int segments_h, float radius) {
|
Mesh * Primitive::ellipsoidFrame(int segments_wl, int segments_h, float radius) {
|
||||||
Mesh * ret = new Mesh(GL_LINES);
|
Mesh * ret = new Mesh(GL_LINES);
|
||||||
QVector<QVector3D> & v(ret->vertices ());
|
QVector<QVector3D> & v(ret->vertices());
|
||||||
QVector<QVector3D> & n(ret->normals ());
|
QVector<QVector3D> & n(ret->normals());
|
||||||
QVector<QVector2D> & t(ret->texcoords());
|
QVector<QVector2D> & t(ret->texcoords());
|
||||||
QVector< Vector2i> & ind(ret->indicesLines());
|
QVector<Vector2i> & ind(ret->indicesLines());
|
||||||
int hseg = segments_h + 1, wlseg = segments_wl + 1;
|
int hseg = segments_h + 1, wlseg = segments_wl + 1;
|
||||||
double crw, crl, a, ch, twl;
|
double crw, crl, a, ch, twl;
|
||||||
|
|
||||||
@@ -367,16 +378,16 @@ Mesh * Primitive::ellipsoidFrame(int segments_wl, int segments_h, float radius)
|
|||||||
for (int i = 0; i <= hseg; i++) {
|
for (int i = 0; i <= hseg; i++) {
|
||||||
ch = -cos((double)i / hseg * M_PI);
|
ch = -cos((double)i / hseg * M_PI);
|
||||||
cp.setZ(ch * radius);
|
cp.setZ(ch * radius);
|
||||||
twl = sqrt(1. - ch * ch);
|
twl = sqrt(1. - ch * ch);
|
||||||
crw = twl * radius;
|
crw = twl * radius;
|
||||||
crl = twl * radius;
|
crl = twl * radius;
|
||||||
int cvcnt = wlseg * 2;
|
int cvcnt = wlseg * 2;
|
||||||
for (int j = 0; j < cvcnt; j++) {
|
for (int j = 0; j < cvcnt; j++) {
|
||||||
a = (double)j / (cvcnt - 1) * M_2PI;
|
a = (double)j / (cvcnt - 1) * M_2PI;
|
||||||
cp.setX(crl * cos(a));
|
cp.setX(crl * cos(a));
|
||||||
cp.setY(crw * sin(a));
|
cp.setY(crw * sin(a));
|
||||||
v << cp;
|
v << cp;
|
||||||
t << QVector2D((double)j / (cvcnt - 1), ch/2.f + 0.5f);
|
t << QVector2D((double)j / (cvcnt - 1), ch / 2.f + 0.5f);
|
||||||
n << cp.normalized();
|
n << cp.normalized();
|
||||||
int si = v.size() - 1;
|
int si = v.size() - 1;
|
||||||
if (j > 0 && i > 0) {
|
if (j > 0 && i > 0) {
|
||||||
@@ -391,10 +402,10 @@ Mesh * Primitive::ellipsoidFrame(int segments_wl, int segments_h, float radius)
|
|||||||
|
|
||||||
Mesh * Primitive::coneFrame(int segments, float radius, float height) {
|
Mesh * Primitive::coneFrame(int segments, float radius, float height) {
|
||||||
Mesh * ret = new Mesh(GL_LINES);
|
Mesh * ret = new Mesh(GL_LINES);
|
||||||
QVector<QVector3D> & v(ret->vertices ());
|
QVector<QVector3D> & v(ret->vertices());
|
||||||
QVector<QVector3D> & n(ret->normals ());
|
QVector<QVector3D> & n(ret->normals());
|
||||||
QVector<QVector2D> & t(ret->texcoords());
|
QVector<QVector2D> & t(ret->texcoords());
|
||||||
QVector< Vector2i> & ind(ret->indicesLines());
|
QVector<Vector2i> & ind(ret->indicesLines());
|
||||||
|
|
||||||
int seg = qMax(segments + 1, 4);
|
int seg = qMax(segments + 1, 4);
|
||||||
QVector3D cp;
|
QVector3D cp;
|
||||||
@@ -424,13 +435,13 @@ Mesh * Primitive::coneFrame(int segments, float radius, float height) {
|
|||||||
|
|
||||||
Mesh * Primitive::lineFrame(QVector3D p0, QVector3D p1) {
|
Mesh * Primitive::lineFrame(QVector3D p0, QVector3D p1) {
|
||||||
Mesh * ret = new Mesh(GL_LINES);
|
Mesh * ret = new Mesh(GL_LINES);
|
||||||
QVector<QVector3D> & v(ret->vertices ());
|
QVector<QVector3D> & v(ret->vertices());
|
||||||
QVector<QVector3D> & n(ret->normals ());
|
QVector<QVector3D> & n(ret->normals());
|
||||||
QVector<QVector2D> & t(ret->texcoords());
|
QVector<QVector2D> & t(ret->texcoords());
|
||||||
QVector< Vector2i> & ind(ret->indicesLines());
|
QVector<Vector2i> & ind(ret->indicesLines());
|
||||||
v << p0 << p1;
|
v << p0 << p1;
|
||||||
n << QVector3D(0,0,1) << QVector3D(0,0,1);
|
n << QVector3D(0, 0, 1) << QVector3D(0, 0, 1);
|
||||||
t << QVector2D(0,0) << QVector2D(1,0);
|
t << QVector2D(0, 0) << QVector2D(1, 0);
|
||||||
ind << Vector2i(0, 1);
|
ind << Vector2i(0, 1);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
57
src/core/core/glprimitives.h
Normal file
57
src/core/core/glprimitives.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
QGL Primitives
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLPRIMITIVE_CUBE_H
|
||||||
|
#define GLPRIMITIVE_CUBE_H
|
||||||
|
|
||||||
|
#include "gltypes.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Primitive {
|
||||||
|
|
||||||
|
|
||||||
|
QGLENGINE_CORE_EXPORT Mesh * plane(float width = 1., float length = 1., int width_segments = 1, int length_segments = 1);
|
||||||
|
|
||||||
|
QGLENGINE_CORE_EXPORT Mesh *
|
||||||
|
cube(float width = 1., float length = 1., float height = 1., int width_segments = 1, int length_segments = 1, int height_segments = 1);
|
||||||
|
|
||||||
|
QGLENGINE_CORE_EXPORT Mesh * ellipsoid(int segments_wl, int segments_h, float radius = 1., float end_angle = 360.);
|
||||||
|
|
||||||
|
QGLENGINE_CORE_EXPORT Mesh * disc(int segments, float radius = 1., float end_angle = 360.);
|
||||||
|
|
||||||
|
QGLENGINE_CORE_EXPORT Mesh * cone(int segments, float radius = 1., float height = 1.);
|
||||||
|
|
||||||
|
QGLENGINE_CORE_EXPORT Mesh * cylinder(int segments, float radius = 1., float height = 1., float end_angle = 360.);
|
||||||
|
|
||||||
|
QGLENGINE_CORE_EXPORT Mesh * arrow(int segments = 16, float thick = 0.04, float angle = 30.); // length = 1
|
||||||
|
|
||||||
|
QGLENGINE_CORE_EXPORT Mesh *
|
||||||
|
torus(int segments_main = 30, int segments_second = 16, float radius_main = 2.5, float radius_second = 0.5, float end_angle = 360.);
|
||||||
|
|
||||||
|
|
||||||
|
QGLENGINE_CORE_EXPORT Mesh * lineFrame(QVector3D p0, QVector3D p1);
|
||||||
|
|
||||||
|
QGLENGINE_CORE_EXPORT Mesh * cubeFrame(float width = 1., float length = 1., float height = 1.);
|
||||||
|
|
||||||
|
QGLENGINE_CORE_EXPORT Mesh * ellipsoidFrame(int segments_wl, int segments_h, float radius = 1.);
|
||||||
|
|
||||||
|
QGLENGINE_CORE_EXPORT Mesh * coneFrame(int segments, float radius = 1., float height = 1.);
|
||||||
|
|
||||||
|
} // namespace Primitive
|
||||||
|
|
||||||
|
#endif // GLPRIMITIVE_CUBE_H
|
||||||
@@ -1,54 +1,63 @@
|
|||||||
/*
|
/*
|
||||||
QGLEngineShaders
|
QGLEngineShaders
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU Lesser General Public License for more details.
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "glshaders.h"
|
||||||
|
|
||||||
|
#include "glshaders_headers.h"
|
||||||
#include "gltypes.h"
|
#include "gltypes.h"
|
||||||
#include "qglview.h"
|
#include "qglview.h"
|
||||||
#include "glshaders.h"
|
|
||||||
#include "glshaders_headers.h"
|
|
||||||
|
|
||||||
using namespace QGLEngineShaders;
|
using namespace QGLEngineShaders;
|
||||||
|
|
||||||
|
|
||||||
bool addShader(QOpenGLShaderProgram * prog, QOpenGLShader::ShaderType type, QString & content, const QString & file, bool add_qgl, const QString & defs) {
|
bool addShader(QOpenGLShaderProgram * prog,
|
||||||
|
QOpenGLShader::ShaderType type,
|
||||||
|
QString & content,
|
||||||
|
const QString & file,
|
||||||
|
bool add_qgl,
|
||||||
|
const QString & defs) {
|
||||||
if (type == 0 || content.isEmpty()) {
|
if (type == 0 || content.isEmpty()) {
|
||||||
content.clear();
|
content.clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//qDebug() << "[QGLEngine] Shader" << file << "found" << (QOpenGLShader::ShaderTypeBit)(int)type << "section ...";
|
// qDebug() << "[QGLEngine] Shader" << file << "found" << (QOpenGLShader::ShaderTypeBit)(int)type << "section ...";
|
||||||
if (add_qgl) {
|
if (add_qgl) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case QOpenGLShader::Fragment:
|
case QOpenGLShader::Fragment:
|
||||||
|
content.prepend(qgl_material_head);
|
||||||
content.prepend(qgl_fragment_head);
|
content.prepend(qgl_fragment_head);
|
||||||
content.prepend(qgl_uniform);
|
content.prepend(qgl_uniform_light);
|
||||||
|
content.prepend(qgl_uniform_material);
|
||||||
content.prepend(qgl_structs);
|
content.prepend(qgl_structs);
|
||||||
break;
|
break;
|
||||||
case QOpenGLShader::Vertex :
|
case QOpenGLShader::Vertex:
|
||||||
content.prepend(qgl_vertex_head );
|
content.prepend(qgl_material_head);
|
||||||
break;
|
content.prepend(qgl_vertex_head);
|
||||||
case QOpenGLShader::Geometry:
|
content.prepend(qgl_uniform_material);
|
||||||
content.prepend(qgl_geometry_head);
|
content.prepend(qgl_structs);
|
||||||
break;
|
break;
|
||||||
|
case QOpenGLShader::Geometry: content.prepend(qgl_geometry_head); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
content.prepend(defs);
|
content.prepend(defs);
|
||||||
content.prepend(qgl_common_head);
|
content.prepend(qgl_common_head);
|
||||||
bool ret = prog->addShaderFromSourceCode(type, content.toLatin1());
|
bool ret = prog->addShaderFromSourceCode(type, content.toLatin1());
|
||||||
if (!ret) qDebug() << "[QGLEngine] Shader" << file << "Compile error:\n" << prog->log();
|
if (!ret) qDebug() << "[QGLEngine] Shader" << file << "Compile error:\n" << prog->log().toLocal8Bit().constData();
|
||||||
content.clear();
|
content.clear();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -57,15 +66,18 @@ bool addShader(QOpenGLShaderProgram * prog, QOpenGLShader::ShaderType type, QStr
|
|||||||
QString prepareDefines(const QStringList & defines) {
|
QString prepareDefines(const QStringList & defines) {
|
||||||
if (defines.isEmpty()) return QString();
|
if (defines.isEmpty()) return QString();
|
||||||
QString ret;
|
QString ret;
|
||||||
foreach (QString s, defines)
|
foreach(QString s, defines)
|
||||||
ret.append("#define " + s + "\n");
|
ret.append("#define " + s + "\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool QGLEngineShaders::loadShadersMulti(QOpenGLShaderProgram *& prog, const QString & file, bool add_qgl, const QStringList & defines) {
|
bool QGLEngineShaders::loadShadersMulti(QOpenGLShaderProgram *& prog,
|
||||||
if (!prog)
|
const QString & file,
|
||||||
prog = new QOpenGLShaderProgram();
|
bool add_qgl,
|
||||||
|
const QStringList & defines,
|
||||||
|
const QString & custom_header) {
|
||||||
|
if (!prog) prog = new QOpenGLShaderProgram();
|
||||||
prog->removeAllShaders();
|
prog->removeAllShaders();
|
||||||
QFile f(file);
|
QFile f(file);
|
||||||
if (!f.open(QIODevice::ReadOnly)) {
|
if (!f.open(QIODevice::ReadOnly)) {
|
||||||
@@ -73,11 +85,11 @@ bool QGLEngineShaders::loadShadersMulti(QOpenGLShaderProgram *& prog, const QStr
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
QTextStream ts(&f);
|
QTextStream ts(&f);
|
||||||
QString cur_shader, line, pl, defs = prepareDefines(defines);
|
QString cur_shader, line, pl, defs = prepareDefines(defines) + "\n" + custom_header;
|
||||||
QOpenGLShader::ShaderType type = QOpenGLShader::ShaderType();
|
QOpenGLShader::ShaderType type = QOpenGLShader::ShaderType();
|
||||||
while (!ts.atEnd()) {
|
while (!ts.atEnd()) {
|
||||||
line = ts.readLine();
|
line = ts.readLine();
|
||||||
pl = line.trimmed().remove(' ').remove('\t').mid(2).toLower();
|
pl = line.trimmed().remove(' ').remove('\t').mid(2).toLower();
|
||||||
pl.chop(2);
|
pl.chop(2);
|
||||||
if (pl == "vertex" || pl == "vert") {
|
if (pl == "vertex" || pl == "vert") {
|
||||||
if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false;
|
if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false;
|
||||||
@@ -109,7 +121,7 @@ bool QGLEngineShaders::loadShadersMulti(QOpenGLShaderProgram *& prog, const QStr
|
|||||||
}
|
}
|
||||||
if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false;
|
if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false;
|
||||||
if (!prog->link()) {
|
if (!prog->link()) {
|
||||||
qDebug() << "[QGLEngine] Shader" << file << "Link error:\n" << prog->log();
|
qDebug() << "[QGLEngine] Shader" << file << "Link error:\n" << prog->log().toLocal8Bit().constData();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
qDebug() << "[QGLEngine] Shader" << file << "ok";
|
qDebug() << "[QGLEngine] Shader" << file << "ok";
|
||||||
@@ -117,15 +129,18 @@ bool QGLEngineShaders::loadShadersMulti(QOpenGLShaderProgram *& prog, const QStr
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool QGLEngineShaders::loadShaders(QOpenGLShaderProgram *& prog, const QStringList & files, bool add_qgl, const QStringList & defines) {
|
bool QGLEngineShaders::loadShaders(QOpenGLShaderProgram *& prog,
|
||||||
if (!prog)
|
const QStringList & files,
|
||||||
prog = new QOpenGLShaderProgram();
|
bool add_qgl,
|
||||||
|
const QStringList & defines,
|
||||||
|
const QString & custom_header) {
|
||||||
|
if (!prog) prog = new QOpenGLShaderProgram();
|
||||||
prog->removeAllShaders();
|
prog->removeAllShaders();
|
||||||
QString cur_shader, defs = prepareDefines(defines);
|
QString cur_shader, defs = prepareDefines(defines) + "\n" + custom_header;
|
||||||
foreach (QString f, files) {
|
foreach(QString f, files) {
|
||||||
QFileInfo fi(f);
|
QFileInfo fi(f);
|
||||||
QOpenGLShader::ShaderType type = QOpenGLShader::ShaderType();
|
QOpenGLShader::ShaderType type = QOpenGLShader::ShaderType();
|
||||||
if (fi.suffix().toLower() == "vert") type = QOpenGLShader::Vertex ;
|
if (fi.suffix().toLower() == "vert") type = QOpenGLShader::Vertex;
|
||||||
if (fi.suffix().toLower() == "frag") type = QOpenGLShader::Fragment;
|
if (fi.suffix().toLower() == "frag") type = QOpenGLShader::Fragment;
|
||||||
if (fi.suffix().toLower() == "geom") type = QOpenGLShader::Geometry;
|
if (fi.suffix().toLower() == "geom") type = QOpenGLShader::Geometry;
|
||||||
if (type == 0) continue;
|
if (type == 0) continue;
|
||||||
@@ -138,7 +153,7 @@ bool QGLEngineShaders::loadShaders(QOpenGLShaderProgram *& prog, const QStringLi
|
|||||||
if (!addShader(prog, type, cur_shader, f, add_qgl, defs)) return false;
|
if (!addShader(prog, type, cur_shader, f, add_qgl, defs)) return false;
|
||||||
}
|
}
|
||||||
if (!prog->link()) {
|
if (!prog->link()) {
|
||||||
qDebug() << "[QGLEngine] Shader" << files << "Link error:\n" << prog->log();
|
qDebug() << "[QGLEngine] Shader" << files << "Link error:\n" << prog->log().toLocal8Bit().constData();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
qDebug() << "[QGLEngine] Shader" << files << "ok";
|
qDebug() << "[QGLEngine] Shader" << files << "ok";
|
||||||
39
src/core/core/glshaders.h
Normal file
39
src/core/core/glshaders.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
QGLEngineShaders
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLSHADERS_H
|
||||||
|
#define GLSHADERS_H
|
||||||
|
|
||||||
|
#include "gltypes.h"
|
||||||
|
|
||||||
|
namespace QGLEngineShaders {
|
||||||
|
|
||||||
|
QGLENGINE_CORE_EXPORT bool loadShadersMulti(QOpenGLShaderProgram *& prog,
|
||||||
|
const QString & file,
|
||||||
|
bool add_qgl = true,
|
||||||
|
const QStringList & defines = QStringList(),
|
||||||
|
const QString & custom_header = QString());
|
||||||
|
QGLENGINE_CORE_EXPORT bool loadShaders(QOpenGLShaderProgram *& prog,
|
||||||
|
const QStringList & files,
|
||||||
|
bool add_qgl = true,
|
||||||
|
const QStringList & defines = QStringList(),
|
||||||
|
const QString & custom_header = QString());
|
||||||
|
|
||||||
|
} // namespace QGLEngineShaders
|
||||||
|
|
||||||
|
#endif // GLSHADERS_H
|
||||||
129
src/core/core/glshaders_headers.h
Normal file
129
src/core/core/glshaders_headers.h
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
QGLEngineShaders
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLSHADERS_HEADERS_H
|
||||||
|
#define GLSHADERS_HEADERS_H
|
||||||
|
|
||||||
|
namespace QGLEngineShaders {
|
||||||
|
|
||||||
|
const int max_materials = 128;
|
||||||
|
const int max_lights = 256;
|
||||||
|
|
||||||
|
const char qgl_common_head[] = "#version 400 core\n"
|
||||||
|
"";
|
||||||
|
|
||||||
|
const char qgl_vertex_head[] = "layout(location = 1 ) in vec3 qgl_Vertex ;\n"
|
||||||
|
"layout(location = 2 ) in vec3 qgl_Normal ;\n"
|
||||||
|
"layout(location = 3 ) in vec3 qgl_Tangent ;\n"
|
||||||
|
"layout(location = 4 ) in vec3 qgl_Bitangent ;\n"
|
||||||
|
"layout(location = 5 ) in vec2 qgl_Texture ;\n"
|
||||||
|
"layout(location = 6 ) in uvec4 qgl_ObjectIntegers;\n"
|
||||||
|
"layout(location = 7 ) in uint qgl_ObjectSelected;\n"
|
||||||
|
"layout(location = 8 ) in vec4 qgl_ObjectColor ;\n"
|
||||||
|
"layout(location = 9 ) in mat4 qgl_ModelMatrix ;\n"
|
||||||
|
"layout(location = 13) in mat2x3 qgl_TextureMatrix ;\n"
|
||||||
|
"out vec2 qgl_FragTexture;\n"
|
||||||
|
"flat out uint qgl_MaterialIndex;\n"
|
||||||
|
"uniform mat4 qgl_ViewMatrix;\n"
|
||||||
|
"uniform mat4 qgl_ViewProjMatrix;\n"
|
||||||
|
"mat3 qgl_getNormalMatrix() {return inverse(mat3(qgl_ViewMatrix * qgl_ModelMatrix));}\n"
|
||||||
|
"mat3 qgl_getTangentMatrix() {return mat3(qgl_ViewMatrix * qgl_ModelMatrix);}\n"
|
||||||
|
"vec2 qgl_getFragTexture() {return (vec3(qgl_Texture, 1.f) * qgl_TextureMatrix).xy;}\n"
|
||||||
|
"vec4 qgl_ftransform() {return qgl_ViewProjMatrix * (qgl_ModelMatrix * vec4(qgl_Vertex, 1.f));}\n"
|
||||||
|
"#define qgl_Material qgl_ObjectIntegers[0]\n"
|
||||||
|
"#define qgl_ObjectID qgl_ObjectIntegers[1]\n"
|
||||||
|
"#define qgl_ObjectFlags qgl_ObjectIntegers[2]\n"
|
||||||
|
"";
|
||||||
|
|
||||||
|
const char qgl_material_head[] =
|
||||||
|
"vec4 qgl_materialTexture(uint type, vec2 coord, vec4 tex_shift) {\n"
|
||||||
|
" coord *= qgl_material[qgl_MaterialIndex].map[type].scale;\n"
|
||||||
|
" vec4 t = texture(qgl_texture_array[qgl_material[qgl_MaterialIndex].map[type].array_index],\n"
|
||||||
|
" vec3(coord, qgl_material[qgl_MaterialIndex].map[type].map_index));\n"
|
||||||
|
" t += tex_shift;\n"
|
||||||
|
" t.rgb = t.rgb * qgl_material[qgl_MaterialIndex].map[type].amount + qgl_material[qgl_MaterialIndex].map[type].offset;\n"
|
||||||
|
" return t;\n"
|
||||||
|
"}\n"
|
||||||
|
"";
|
||||||
|
|
||||||
|
const char qgl_fragment_head[] = "in vec2 qgl_FragTexture;\n"
|
||||||
|
"flat in uint qgl_MaterialIndex;\n"
|
||||||
|
"out vec4 qgl_FragData[gl_MaxDrawBuffers];\n"
|
||||||
|
"uniform vec2 qgl_ViewSize;\n"
|
||||||
|
"#define qgl_FragColor qgl_FragData[0]\n"
|
||||||
|
"";
|
||||||
|
|
||||||
|
const char qgl_geometry_head[] = "";
|
||||||
|
|
||||||
|
const char qgl_structs[] = "#define QGL_MAPS_COUNT 6\n"
|
||||||
|
"#define QGL_MAP_DIFFUSE 0\n"
|
||||||
|
"#define QGL_MAP_NORMAL 1\n"
|
||||||
|
"#define QGL_MAP_METALNESS 2\n"
|
||||||
|
"#define QGL_MAP_ROUGHNESS 3\n"
|
||||||
|
"#define QGL_MAP_EMISSION 4\n"
|
||||||
|
"#define QGL_MAP_RELIEF 5\n"
|
||||||
|
"#define QGL_TEXTURE_ARRAY_EMPTY 0\n"
|
||||||
|
"#define QGL_TEXTURE_ARRAY_MAPS 1\n"
|
||||||
|
"struct QGLMap {\n"
|
||||||
|
" float offset;\n"
|
||||||
|
" float amount;\n"
|
||||||
|
" vec2 scale;\n"
|
||||||
|
" uint array_index;\n"
|
||||||
|
" uint map_index;\n"
|
||||||
|
"};\n"
|
||||||
|
"struct QGLMaterial {\n"
|
||||||
|
" vec4 color_diffuse;\n"
|
||||||
|
" vec4 color_emission;\n"
|
||||||
|
" float transparency;\n"
|
||||||
|
" float reflectivity;\n"
|
||||||
|
" float iof;\n"
|
||||||
|
" float dispersion;\n"
|
||||||
|
" QGLMap map[QGL_MAPS_COUNT];\n"
|
||||||
|
"};\n"
|
||||||
|
"struct QGLLightParameter {\n"
|
||||||
|
" vec4 color;\n"
|
||||||
|
" vec4 decay_intensity;\n"
|
||||||
|
" vec4 angles;\n"
|
||||||
|
" float size;\n"
|
||||||
|
" float flags;\n"
|
||||||
|
" QGLMap map;\n"
|
||||||
|
"};\n"
|
||||||
|
"struct QGLLightPosition {\n"
|
||||||
|
" vec4 position;\n"
|
||||||
|
" vec4 direction;\n"
|
||||||
|
" mat4 shadow_matrix;\n"
|
||||||
|
"};\n"
|
||||||
|
"";
|
||||||
|
|
||||||
|
const char qgl_uniform_material[] = "layout (std140) uniform QGLMaterialData {\n"
|
||||||
|
" QGLMaterial qgl_material[128];\n"
|
||||||
|
"};\n"
|
||||||
|
"uniform sampler2DArray qgl_texture_array[2];\n"
|
||||||
|
"";
|
||||||
|
|
||||||
|
const char qgl_uniform_light[] = "layout (std140) uniform QGLLightParameterData {\n"
|
||||||
|
" QGLLightParameter qgl_light_parameter[256];\n"
|
||||||
|
"};\n"
|
||||||
|
"layout (std140) uniform QGLLightPositionData {\n"
|
||||||
|
" QGLLightPosition qgl_light_position[256];\n"
|
||||||
|
"};\n"
|
||||||
|
"";
|
||||||
|
|
||||||
|
} // namespace QGLEngineShaders
|
||||||
|
|
||||||
|
#endif // GLSHADERS_HEADERS_H
|
||||||
108
src/core/core/glshaders_types.cpp
Normal file
108
src/core/core/glshaders_types.cpp
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
QGLEngineShaders
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "glshaders_types.h"
|
||||||
|
|
||||||
|
|
||||||
|
QGLEngineShaders::QGLMap::QGLMap() {
|
||||||
|
offset = 0.;
|
||||||
|
amount = 1.;
|
||||||
|
scale = QVector2D(1., 1.);
|
||||||
|
array_index = map_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QGLEngineShaders::QGLMaterial::QGLMaterial() {
|
||||||
|
color_diffuse = QVector4D(1., 1., 1., 0.);
|
||||||
|
color_emission = QVector4D(0., 0., 0., 0.);
|
||||||
|
transparency = 0.;
|
||||||
|
reflectivity = 0.;
|
||||||
|
iof = 0.;
|
||||||
|
dispersion = 0.;
|
||||||
|
map[mtNormal].map_index = emrBlue;
|
||||||
|
map[mtRelief].map_index = emrBlack;
|
||||||
|
map[mtRoughness].amount = 0.75;
|
||||||
|
map[mtMetalness].amount = 0.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QGLEngineShaders::prepareDrawGeom(QOpenGLExtraFunctions * f) {
|
||||||
|
// qDebug() << "prepareDrawGeom";
|
||||||
|
|
||||||
|
f->glEnableVertexAttribArray(pos_loc);
|
||||||
|
f->glEnableVertexAttribArray(normal_loc);
|
||||||
|
f->glEnableVertexAttribArray(tangent_loc);
|
||||||
|
f->glEnableVertexAttribArray(bitangent_loc);
|
||||||
|
f->glEnableVertexAttribArray(tex_loc);
|
||||||
|
|
||||||
|
int size = sizeof(Vertex);
|
||||||
|
f->glVertexAttribPointer(pos_loc, 3, GL_FLOAT, GL_FALSE, size, (const void *)pos_offset);
|
||||||
|
f->glVertexAttribPointer(normal_loc, 3, GL_FLOAT, GL_FALSE, size, (const void *)normal_offset);
|
||||||
|
f->glVertexAttribPointer(tangent_loc, 3, GL_FLOAT, GL_FALSE, size, (const void *)tangent_offset);
|
||||||
|
f->glVertexAttribPointer(bitangent_loc, 3, GL_FLOAT, GL_FALSE, size, (const void *)bitangent_offset);
|
||||||
|
f->glVertexAttribPointer(tex_loc, 2, GL_FLOAT, GL_FALSE, size, (const void *)tex_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QGLEngineShaders::prepareDrawObj(QOpenGLExtraFunctions * f) {
|
||||||
|
// qDebug() << "prepareDrawObj";
|
||||||
|
|
||||||
|
f->glEnableVertexAttribArray(integers_loc);
|
||||||
|
f->glEnableVertexAttribArray(color_loc);
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
f->glEnableVertexAttribArray(modelmatrix_loc + i);
|
||||||
|
for (int i = 0; i < 2; ++i)
|
||||||
|
f->glEnableVertexAttribArray(texturematrix_loc + i);
|
||||||
|
|
||||||
|
GLsizei size = sizeof(Object);
|
||||||
|
f->glVertexAttribIPointer(integers_loc, 4, GL_UNSIGNED_INT, size, (const void *)integers_offset);
|
||||||
|
f->glVertexAttribPointer(color_loc, 4, GL_FLOAT, GL_FALSE, size, (const void *)color_offset);
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
f->glVertexAttribPointer(modelmatrix_loc + i,
|
||||||
|
4,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
size,
|
||||||
|
(const void *)(modelmatrix_offset + sizeof(QVector4D) * i));
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
f->glVertexAttribPointer(texturematrix_loc + i,
|
||||||
|
3,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
size,
|
||||||
|
(const void *)(texturematrix_offset + sizeof(QVector3D) * i));
|
||||||
|
}
|
||||||
|
|
||||||
|
f->glVertexAttribDivisor(integers_loc, 1);
|
||||||
|
f->glVertexAttribDivisor(color_loc, 1);
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
f->glVertexAttribDivisor(modelmatrix_loc + i, 1);
|
||||||
|
for (int i = 0; i < 2; ++i)
|
||||||
|
f->glVertexAttribDivisor(texturematrix_loc + i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QGLEngineShaders::prepareDrawSel(QOpenGLExtraFunctions * f) {
|
||||||
|
// qDebug() << "prepareDrawObj";
|
||||||
|
|
||||||
|
f->glEnableVertexAttribArray(is_selected_loc);
|
||||||
|
GLsizei size = 1;
|
||||||
|
f->glVertexAttribIPointer(is_selected_loc, 1, GL_UNSIGNED_BYTE, size, (const void *)is_selected_offset);
|
||||||
|
f->glVertexAttribDivisor(is_selected_loc, 1);
|
||||||
|
}
|
||||||
170
src/core/core/glshaders_types.h
Normal file
170
src/core/core/glshaders_types.h
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
QGLEngineShaders
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLSHADERS_TYPES_H
|
||||||
|
#define GLSHADERS_TYPES_H
|
||||||
|
|
||||||
|
#include "gltypes.h"
|
||||||
|
|
||||||
|
namespace QGLEngineShaders {
|
||||||
|
|
||||||
|
|
||||||
|
/// VBO
|
||||||
|
|
||||||
|
// geometry
|
||||||
|
const GLsizei pos_offset = 0;
|
||||||
|
const GLsizei normal_offset = sizeof(QVector3D) + pos_offset;
|
||||||
|
const GLsizei tangent_offset = sizeof(QVector3D) + normal_offset;
|
||||||
|
const GLsizei bitangent_offset = sizeof(QVector3D) + tangent_offset;
|
||||||
|
const GLsizei tex_offset = sizeof(QVector3D) + bitangent_offset;
|
||||||
|
|
||||||
|
// object
|
||||||
|
const GLsizei integers_offset = 0;
|
||||||
|
const GLsizei color_offset = sizeof(GLuint) * 4 + integers_offset;
|
||||||
|
const GLsizei modelmatrix_offset = sizeof(QVector4D) + color_offset;
|
||||||
|
const GLsizei texturematrix_offset = sizeof(QVector4D) * 4 + modelmatrix_offset;
|
||||||
|
|
||||||
|
const GLsizei is_selected_offset = 0;
|
||||||
|
|
||||||
|
const GLuint pos_loc = 1; // qgl_Vertex
|
||||||
|
const GLuint normal_loc = 2; // qgl_Normal
|
||||||
|
const GLuint tangent_loc = 3; // qgl_Tangent
|
||||||
|
const GLuint bitangent_loc = 4; // qgl_Bitangent
|
||||||
|
const GLuint tex_loc = 5; // qgl_Texture
|
||||||
|
|
||||||
|
const GLuint integers_loc = 6; // qgl_ObjectIntegers
|
||||||
|
const GLuint color_loc = 8; // qgl_ObjectColor
|
||||||
|
const GLuint modelmatrix_loc = 9; // qgl_ModelViewProjectionMatrix
|
||||||
|
const GLuint texturematrix_loc = 13; // qgl_TextureMatrix
|
||||||
|
|
||||||
|
const GLuint is_selected_loc = 7; // qgl_ObjectSelected
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct Vertex {
|
||||||
|
QVector3D pos;
|
||||||
|
QVector3D normal;
|
||||||
|
QVector3D tangent;
|
||||||
|
QVector3D bitangent;
|
||||||
|
QVector2D tex;
|
||||||
|
};
|
||||||
|
struct Object {
|
||||||
|
Object() {
|
||||||
|
material = object_id = flags = 0;
|
||||||
|
color = QVector4D(1, 1, 1, 1);
|
||||||
|
QMatrix4x4().copyDataTo(modelmatrix);
|
||||||
|
QMatrix2x3().transposed().copyDataTo(texturematrix);
|
||||||
|
}
|
||||||
|
GLuint material;
|
||||||
|
GLuint object_id;
|
||||||
|
union {
|
||||||
|
GLuint flags;
|
||||||
|
struct {
|
||||||
|
GLuint f_accept_light : 1;
|
||||||
|
GLuint f_accept_fog : 1;
|
||||||
|
GLuint f_accept_cast_shadow: 1;
|
||||||
|
GLuint f_accept_rec_shadow : 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
GLuint _reserve;
|
||||||
|
QVector4D color;
|
||||||
|
GLfloat modelmatrix[16];
|
||||||
|
GLfloat texturematrix[6];
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
|
||||||
|
/// UBO
|
||||||
|
|
||||||
|
enum BindingPoints {
|
||||||
|
bpMaterials,
|
||||||
|
bpLightParameters,
|
||||||
|
bpLightPositions,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum MapType {
|
||||||
|
mtDiffuse = 0,
|
||||||
|
mtNormal = 1,
|
||||||
|
mtMetalness = 2,
|
||||||
|
mtRoughness = 3,
|
||||||
|
mtEmission = 4,
|
||||||
|
mtRelief = 5,
|
||||||
|
};
|
||||||
|
enum TextureRole {
|
||||||
|
trCoeffBRDF = 10,
|
||||||
|
trEnvironment = 11,
|
||||||
|
};
|
||||||
|
enum TextureArrayRole {
|
||||||
|
tarEmpty = 12,
|
||||||
|
tarMaps = 13,
|
||||||
|
tarShadowsCone = 16,
|
||||||
|
tarShadowsOmni = 17,
|
||||||
|
tarDepthsCone = 18,
|
||||||
|
tarDepthsOmni = 19,
|
||||||
|
};
|
||||||
|
enum EmptyMapRole {
|
||||||
|
emrWhite,
|
||||||
|
emrBlue,
|
||||||
|
emrBlack,
|
||||||
|
emrCount,
|
||||||
|
};
|
||||||
|
#define QGL_MAPS_COUNT 6
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct QGLMap {
|
||||||
|
QGLMap();
|
||||||
|
GLfloat offset;
|
||||||
|
GLfloat amount;
|
||||||
|
QVector2D scale;
|
||||||
|
GLuint array_index;
|
||||||
|
GLuint map_index;
|
||||||
|
GLfloat __res_2[2];
|
||||||
|
};
|
||||||
|
struct QGLMaterial {
|
||||||
|
QGLMaterial();
|
||||||
|
QVector4D color_diffuse;
|
||||||
|
QVector4D color_emission;
|
||||||
|
GLfloat transparency;
|
||||||
|
GLfloat reflectivity;
|
||||||
|
GLfloat iof;
|
||||||
|
GLfloat dispersion;
|
||||||
|
QGLMap map[QGL_MAPS_COUNT];
|
||||||
|
};
|
||||||
|
struct QGLLightParameter {
|
||||||
|
QVector4D color;
|
||||||
|
QVector4D decay_intensity; // [^0, ^1, ^2, intensity]
|
||||||
|
QVector4D angles; // [start, cos(start), end, cos(end)]
|
||||||
|
GLfloat size = 0.1f;
|
||||||
|
GLfloat flags = 0;
|
||||||
|
GLfloat _align[2];
|
||||||
|
QGLMap map;
|
||||||
|
};
|
||||||
|
struct QGLLightPosition {
|
||||||
|
QGLLightPosition() { QMatrix4x4().copyDataTo(shadowmatrix); }
|
||||||
|
QVector4D position;
|
||||||
|
QVector4D direction;
|
||||||
|
GLfloat shadowmatrix[16];
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
void prepareDrawGeom(QOpenGLExtraFunctions * f);
|
||||||
|
void prepareDrawObj(QOpenGLExtraFunctions * f);
|
||||||
|
void prepareDrawSel(QOpenGLExtraFunctions * f);
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace QGLEngineShaders
|
||||||
|
|
||||||
|
#endif // GLSHADERS_TYPES_H
|
||||||
@@ -1,36 +1,37 @@
|
|||||||
/*
|
/*
|
||||||
QGL Texture2DArray
|
QGL Texture2DArray
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU Lesser General Public License for more details.
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define GL_GLEXT_PROTOTYPES
|
#define GL_GLEXT_PROTOTYPES
|
||||||
#include <QOpenGLExtraFunctions>
|
|
||||||
#include "gltexturearray.h"
|
#include "gltexturearray.h"
|
||||||
|
|
||||||
|
#include <QOpenGLExtraFunctions>
|
||||||
|
|
||||||
Texture2DArray::Texture2DArray(bool filter) {
|
|
||||||
target_ = GL_TEXTURE_2D_ARRAY;
|
Texture2DArray::Texture2DArray(GLenum format, bool filter) {
|
||||||
texture_ = 0;
|
target_ = GL_TEXTURE_2D_ARRAY;
|
||||||
layers_ = 0;
|
format_ = format;
|
||||||
|
texture_ = 0;
|
||||||
|
layers_ = 0;
|
||||||
filtering_ = filter;
|
filtering_ = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Texture2DArray::~Texture2DArray() {
|
Texture2DArray::~Texture2DArray() {}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Texture2DArray::init(QOpenGLExtraFunctions * f) {
|
void Texture2DArray::init(QOpenGLExtraFunctions * f) {
|
||||||
@@ -48,6 +49,12 @@ void Texture2DArray::destroy(QOpenGLExtraFunctions * f) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Texture2DArray::reinit() {
|
||||||
|
texture_ = 0;
|
||||||
|
layers_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Texture2DArray::bind(QOpenGLExtraFunctions * f, int channel) {
|
void Texture2DArray::bind(QOpenGLExtraFunctions * f, int channel) {
|
||||||
f->glActiveTexture(GL_TEXTURE0 + channel);
|
f->glActiveTexture(GL_TEXTURE0 + channel);
|
||||||
f->glBindTexture(target_, texture_);
|
f->glBindTexture(target_, texture_);
|
||||||
@@ -62,7 +69,7 @@ void Texture2DArray::release(QOpenGLExtraFunctions * f) {
|
|||||||
bool Texture2DArray::resize(QOpenGLExtraFunctions * f, QSize new_size, int layers_count) {
|
bool Texture2DArray::resize(QOpenGLExtraFunctions * f, QSize new_size, int layers_count) {
|
||||||
if (new_size.isNull() || layers_count <= 0) return false;
|
if (new_size.isNull() || layers_count <= 0) return false;
|
||||||
if ((size_ == new_size) && (layers_ >= layers_count)) return false;
|
if ((size_ == new_size) && (layers_ >= layers_count)) return false;
|
||||||
size_ = new_size;
|
size_ = new_size;
|
||||||
layers_ = layers_count;
|
layers_ = layers_count;
|
||||||
f->glBindTexture(target_, texture_);
|
f->glBindTexture(target_, texture_);
|
||||||
f->glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
f->glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
@@ -75,17 +82,26 @@ bool Texture2DArray::resize(QOpenGLExtraFunctions * f, QSize new_size, int layer
|
|||||||
f->glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
f->glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
f->glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
f->glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
}
|
}
|
||||||
f->glTexImage3D(target_, 0, GL_RGBA8, size_.width(), size_.height(), layers_, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
GLenum bformat = format_;
|
||||||
|
GLenum btype = GL_UNSIGNED_BYTE;
|
||||||
|
if (format_ == GL_R16F || format_ == GL_R32F) {
|
||||||
|
bformat = GL_RED;
|
||||||
|
btype = GL_FLOAT;
|
||||||
|
}
|
||||||
|
if (format_ == GL_DEPTH_COMPONENT || format_ == GL_DEPTH_COMPONENT16 || format_ == GL_DEPTH_COMPONENT24 ||
|
||||||
|
format_ == GL_DEPTH_COMPONENT32) {
|
||||||
|
bformat = GL_DEPTH_COMPONENT;
|
||||||
|
}
|
||||||
|
f->glTexImage3D(target_, 0, format_, size_.width(), size_.height(), layers_, 0, bformat, btype, nullptr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Texture2DArray::load(QOpenGLExtraFunctions * f, const QImage & image, int layer) {
|
void Texture2DArray::load(QOpenGLExtraFunctions * f, const QImage & image, int layer) {
|
||||||
if (image.isNull() || size_.isNull() || layer < 0 || layer >= layers_) return;
|
if (image.isNull() || size_.isNull() || layer < 0 || layer >= layers_) return;
|
||||||
QImage im = image.mirrored(false, true)
|
QImage im =
|
||||||
.scaled(size_, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)
|
image.mirrored(false, true).scaled(size_, Qt::IgnoreAspectRatio, Qt::SmoothTransformation).convertToFormat(QImage::Format_RGBA8888);
|
||||||
.convertToFormat(QImage::Format_RGBA8888);
|
// qDebug() << "Texture2DArray::load image" << image.size() << "to layer" << layer;
|
||||||
//qDebug() << "Texture2DArray::load image" << image.size() << "to layer" << layer;
|
|
||||||
f->glTexSubImage3D(target_, 0, 0, 0, layer, size_.width(), size_.height(), 1, GL_RGBA, GL_UNSIGNED_BYTE, im.constBits());
|
f->glTexSubImage3D(target_, 0, 0, 0, layer, size_.width(), size_.height(), 1, GL_RGBA, GL_UNSIGNED_BYTE, im.constBits());
|
||||||
}
|
}
|
||||||
|
|
||||||
55
src/core/core/gltexturearray.h
Normal file
55
src/core/core/gltexturearray.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
QGL Texture2DArray
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLTEXTUREARRAY_H
|
||||||
|
#define GLTEXTUREARRAY_H
|
||||||
|
|
||||||
|
#include "gltypes.h"
|
||||||
|
|
||||||
|
|
||||||
|
class QGLENGINE_CORE_EXPORT Texture2DArray {
|
||||||
|
public:
|
||||||
|
Texture2DArray(GLenum format, bool filter);
|
||||||
|
~Texture2DArray();
|
||||||
|
|
||||||
|
void init(QOpenGLExtraFunctions * f);
|
||||||
|
void destroy(QOpenGLExtraFunctions * f);
|
||||||
|
void reinit();
|
||||||
|
|
||||||
|
void bind(QOpenGLExtraFunctions * f, int channel = 0);
|
||||||
|
void release(QOpenGLExtraFunctions * f);
|
||||||
|
|
||||||
|
// returns true if size changed
|
||||||
|
bool resize(QOpenGLExtraFunctions * f, QSize new_size, int layers_count);
|
||||||
|
void load(QOpenGLExtraFunctions * f, const QImage & image, int layer);
|
||||||
|
void mipmaps(QOpenGLExtraFunctions * f);
|
||||||
|
|
||||||
|
GLuint ID() const { return texture_; }
|
||||||
|
bool isInit() const { return texture_ != 0; }
|
||||||
|
int layersCount() const { return layers_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLenum target_, format_;
|
||||||
|
GLuint texture_;
|
||||||
|
QSize size_;
|
||||||
|
int layers_;
|
||||||
|
bool filtering_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // GLTEXTUREARRAY_H
|
||||||
@@ -1,36 +1,50 @@
|
|||||||
/*
|
/*
|
||||||
QGL Transform
|
QGL Transform
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU Lesser General Public License for more details.
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "gltransform.h"
|
#include "gltransform.h"
|
||||||
|
|
||||||
#include "gltypes.h"
|
#include "gltypes.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
|
||||||
inline void composeQMatrix4x4(const QVector3D & position, const QVector3D & orientation, const QVector3D & scale, QMatrix4x4 &m) {
|
inline void composeQMatrix4x4(const QVector3D & position, const QVector3D & orientation, const QVector3D & scale, QMatrix4x4 & m) {
|
||||||
const QMatrix3x3 rot3x3(Transform::toRotationMatrix(orientation));
|
const QMatrix3x3 rot3x3(Transform::toRotationMatrix(orientation));
|
||||||
|
|
||||||
// set up final matrix with scale, rotation and translation
|
// set up final matrix with scale, rotation and translation
|
||||||
m(0, 0) = scale.x() * rot3x3(0, 0); m(0, 1) = scale.y() * rot3x3(0, 1); m(0, 2) = scale.z() * rot3x3(0, 2); m(0, 3) = position.x();
|
m(0, 0) = scale.x() * rot3x3(0, 0);
|
||||||
m(1, 0) = scale.x() * rot3x3(1, 0); m(1, 1) = scale.y() * rot3x3(1, 1); m(1, 2) = scale.z() * rot3x3(1, 2); m(1, 3) = position.y();
|
m(0, 1) = scale.y() * rot3x3(0, 1);
|
||||||
m(2, 0) = scale.x() * rot3x3(2, 0); m(2, 1) = scale.y() * rot3x3(2, 1); m(2, 2) = scale.z() * rot3x3(2, 2); m(2, 3) = position.z();
|
m(0, 2) = scale.z() * rot3x3(0, 2);
|
||||||
|
m(0, 3) = position.x();
|
||||||
|
m(1, 0) = scale.x() * rot3x3(1, 0);
|
||||||
|
m(1, 1) = scale.y() * rot3x3(1, 1);
|
||||||
|
m(1, 2) = scale.z() * rot3x3(1, 2);
|
||||||
|
m(1, 3) = position.y();
|
||||||
|
m(2, 0) = scale.x() * rot3x3(2, 0);
|
||||||
|
m(2, 1) = scale.y() * rot3x3(2, 1);
|
||||||
|
m(2, 2) = scale.z() * rot3x3(2, 2);
|
||||||
|
m(2, 3) = position.z();
|
||||||
// no projection term
|
// no projection term
|
||||||
m(3, 0) = 0.0f; m(3, 1) = 0.0f; m(3, 2) = 0.0f; m(3, 3) = 1.0f;
|
m(3, 0) = 0.0f;
|
||||||
|
m(3, 1) = 0.0f;
|
||||||
|
m(3, 2) = 0.0f;
|
||||||
|
m(3, 3) = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void decomposeQMatrix3x3(const QMatrix3x3 & m, QMatrix3x3 & Q, QVector3D & D, QVector3D & U) {
|
inline void decomposeQMatrix3x3(const QMatrix3x3 & m, QMatrix3x3 & Q, QVector3D & D, QVector3D & U) {
|
||||||
@@ -62,24 +76,24 @@ inline void decomposeQMatrix3x3(const QMatrix3x3 & m, QMatrix3x3 & Q, QVector3D
|
|||||||
|
|
||||||
// build orthogonal matrix Q
|
// build orthogonal matrix Q
|
||||||
float invLen = 1.0f / std::sqrt(m(0, 0) * m(0, 0) + m(1, 0) * m(1, 0) + m(2, 0) * m(2, 0));
|
float invLen = 1.0f / std::sqrt(m(0, 0) * m(0, 0) + m(1, 0) * m(1, 0) + m(2, 0) * m(2, 0));
|
||||||
Q(0, 0) = m(0, 0) * invLen;
|
Q(0, 0) = m(0, 0) * invLen;
|
||||||
Q(1, 0) = m(1, 0) * invLen;
|
Q(1, 0) = m(1, 0) * invLen;
|
||||||
Q(2, 0) = m(2, 0) * invLen;
|
Q(2, 0) = m(2, 0) * invLen;
|
||||||
|
|
||||||
float dot = Q(0, 0) * m(0, 1) + Q(1, 0) * m(1, 1) + Q(2, 0) * m(2, 1);
|
float dot = Q(0, 0) * m(0, 1) + Q(1, 0) * m(1, 1) + Q(2, 0) * m(2, 1);
|
||||||
Q(0, 1) = m(0, 1) - dot * Q(0, 0);
|
Q(0, 1) = m(0, 1) - dot * Q(0, 0);
|
||||||
Q(1, 1) = m(1, 1) - dot * Q(1, 0);
|
Q(1, 1) = m(1, 1) - dot * Q(1, 0);
|
||||||
Q(2, 1) = m(2, 1) - dot * Q(2, 0);
|
Q(2, 1) = m(2, 1) - dot * Q(2, 0);
|
||||||
invLen = 1.0f / std::sqrt(Q(0, 1) * Q(0, 1) + Q(1, 1) * Q(1, 1) + Q(2, 1) * Q(2, 1));
|
invLen = 1.0f / std::sqrt(Q(0, 1) * Q(0, 1) + Q(1, 1) * Q(1, 1) + Q(2, 1) * Q(2, 1));
|
||||||
Q(0, 1) *= invLen;
|
Q(0, 1) *= invLen;
|
||||||
Q(1, 1) *= invLen;
|
Q(1, 1) *= invLen;
|
||||||
Q(2, 1) *= invLen;
|
Q(2, 1) *= invLen;
|
||||||
|
|
||||||
dot = Q(0, 0) * m(0, 2) + Q(1, 0) * m(1, 2) + Q(2, 0) * m(2, 2);
|
dot = Q(0, 0) * m(0, 2) + Q(1, 0) * m(1, 2) + Q(2, 0) * m(2, 2);
|
||||||
Q(0, 2) = m(0, 2) - dot * Q(0, 0);
|
Q(0, 2) = m(0, 2) - dot * Q(0, 0);
|
||||||
Q(1, 2) = m(1, 2) - dot * Q(1, 0);
|
Q(1, 2) = m(1, 2) - dot * Q(1, 0);
|
||||||
Q(2, 2) = m(2, 2) - dot * Q(2, 0);
|
Q(2, 2) = m(2, 2) - dot * Q(2, 0);
|
||||||
dot = Q(0, 1) * m(0, 2) + Q(1, 1) * m(1, 2) + Q(2, 1) * m(2, 2);
|
dot = Q(0, 1) * m(0, 2) + Q(1, 1) * m(1, 2) + Q(2, 1) * m(2, 2);
|
||||||
Q(0, 2) -= dot * Q(0, 1);
|
Q(0, 2) -= dot * Q(0, 1);
|
||||||
Q(1, 2) -= dot * Q(1, 1);
|
Q(1, 2) -= dot * Q(1, 1);
|
||||||
Q(2, 2) -= dot * Q(2, 1);
|
Q(2, 2) -= dot * Q(2, 1);
|
||||||
@@ -89,11 +103,9 @@ inline void decomposeQMatrix3x3(const QMatrix3x3 & m, QMatrix3x3 & Q, QVector3D
|
|||||||
Q(2, 2) *= invLen;
|
Q(2, 2) *= invLen;
|
||||||
|
|
||||||
// guarantee that orthogonal matrix has determinant 1 (no reflections)
|
// guarantee that orthogonal matrix has determinant 1 (no reflections)
|
||||||
const float det = Q(0, 0) * Q(1, 1) * Q(2, 2) + Q(0, 1) * Q(1, 2) * Q(2, 0) +
|
const float det = Q(0, 0) * Q(1, 1) * Q(2, 2) + Q(0, 1) * Q(1, 2) * Q(2, 0) + Q(0, 2) * Q(1, 0) * Q(2, 1) -
|
||||||
Q(0, 2) * Q(1, 0) * Q(2, 1) - Q(0, 2) * Q(1, 1) * Q(2, 0) -
|
Q(0, 2) * Q(1, 1) * Q(2, 0) - Q(0, 1) * Q(1, 0) * Q(2, 2) - Q(0, 0) * Q(1, 2) * Q(2, 1);
|
||||||
Q(0, 1) * Q(1, 0) * Q(2, 2) - Q(0, 0) * Q(1, 2) * Q(2, 1);
|
if (det < 0.0f) Q *= -1.0f;
|
||||||
if (det < 0.0f)
|
|
||||||
Q *= -1.0f;
|
|
||||||
|
|
||||||
// build "right" matrix R
|
// build "right" matrix R
|
||||||
QMatrix3x3 R(Qt::Uninitialized);
|
QMatrix3x3 R(Qt::Uninitialized);
|
||||||
@@ -105,30 +117,26 @@ inline void decomposeQMatrix3x3(const QMatrix3x3 & m, QMatrix3x3 & Q, QVector3D
|
|||||||
R(2, 2) = Q(0, 2) * m(0, 2) + Q(1, 2) * m(1, 2) + Q(2, 2) * m(2, 2);
|
R(2, 2) = Q(0, 2) * m(0, 2) + Q(1, 2) * m(1, 2) + Q(2, 2) * m(2, 2);
|
||||||
|
|
||||||
// the scaling component
|
// the scaling component
|
||||||
D[0] = R(0, 0);
|
D[0] = R(0, 0);
|
||||||
D[1] = R(1, 1);
|
D[1] = R(1, 1);
|
||||||
D[2] = R(2, 2);
|
D[2] = R(2, 2);
|
||||||
|
|
||||||
// the shear component
|
// the shear component
|
||||||
U[0] = R(0, 1) / D[0];
|
U[0] = R(0, 1) / D[0];
|
||||||
U[1] = R(0, 2) / D[0];
|
U[1] = R(0, 2) / D[0];
|
||||||
U[2] = R(1, 2) / D[1];
|
U[2] = R(1, 2) / D[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool hasScale(const QMatrix4x4 &m) {
|
inline bool hasScale(const QMatrix4x4 & m) {
|
||||||
// If the columns are orthonormal and form a right-handed system, then there is no scale
|
// If the columns are orthonormal and form a right-handed system, then there is no scale
|
||||||
float t(m.determinant());
|
float t(m.determinant());
|
||||||
if (!qFuzzyIsNull(t - 1.0f))
|
if (!qFuzzyIsNull(t - 1.0f)) return true;
|
||||||
return true;
|
|
||||||
t = m(0, 0) * m(0, 0) + m(1, 0) * m(1, 0) + m(2, 0) * m(2, 0);
|
t = m(0, 0) * m(0, 0) + m(1, 0) * m(1, 0) + m(2, 0) * m(2, 0);
|
||||||
if (!qFuzzyIsNull(t - 1.0f))
|
if (!qFuzzyIsNull(t - 1.0f)) return true;
|
||||||
return true;
|
|
||||||
t = m(0, 1) * m(0, 1) + m(1, 1) * m(1, 1) + m(2, 1) * m(2, 1);
|
t = m(0, 1) * m(0, 1) + m(1, 1) * m(1, 1) + m(2, 1) * m(2, 1);
|
||||||
if (!qFuzzyIsNull(t - 1.0f))
|
if (!qFuzzyIsNull(t - 1.0f)) return true;
|
||||||
return true;
|
|
||||||
t = m(0, 2) * m(0, 2) + m(1, 2) * m(1, 2) + m(2, 2) * m(2, 2);
|
t = m(0, 2) * m(0, 2) + m(1, 2) * m(1, 2) + m(2, 2) * m(2, 2);
|
||||||
if (!qFuzzyIsNull(t - 1.0f))
|
if (!qFuzzyIsNull(t - 1.0f)) return true;
|
||||||
return true;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,64 +150,57 @@ inline void decomposeQMatrix4x4(const QMatrix4x4 & m, QVector3D & position, QVec
|
|||||||
decomposeQMatrix3x3(m3x3, rot3x3, scale, position);
|
decomposeQMatrix3x3(m3x3, rot3x3, scale, position);
|
||||||
} else {
|
} else {
|
||||||
// we know there is no scaling part; no need for QDU decomposition
|
// we know there is no scaling part; no need for QDU decomposition
|
||||||
scale = QVector3D(1.0f, 1.0f, 1.0f);
|
scale = QVector3D(1.0f, 1.0f, 1.0f);
|
||||||
rot3x3 = m3x3;
|
rot3x3 = m3x3;
|
||||||
}
|
}
|
||||||
orientation = Transform::fromRotationMatrix(rot3x3);
|
orientation = Transform::fromRotationMatrix(rot3x3);
|
||||||
position = QVector3D(m(0, 3), m(1, 3), m(2, 3));
|
position = QVector3D(m(0, 3), m(1, 3), m(2, 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Transform::Transform(): m_scale(1.0f, 1.0f, 1.0f), m_translation(), m_eulerRotationAngles(), m_matrixDirty(false) {}
|
||||||
|
|
||||||
|
|
||||||
Transform::Transform(): m_scale(1.0f, 1.0f, 1.0f),
|
Transform & Transform::operator=(const Transform & t) {
|
||||||
m_translation(), m_eulerRotationAngles(), m_matrixDirty(false) {
|
m_scale = t.m_scale;
|
||||||
}
|
m_translation = t.m_translation;
|
||||||
|
|
||||||
|
|
||||||
Transform & Transform::operator =(const Transform & t) {
|
|
||||||
m_scale = t.m_scale;
|
|
||||||
m_translation = t.m_translation;
|
|
||||||
m_eulerRotationAngles = t.m_eulerRotationAngles;
|
m_eulerRotationAngles = t.m_eulerRotationAngles;
|
||||||
m_matrixDirty = true;
|
m_matrixDirty = true;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Transform::setMatrix(const QMatrix4x4 & m) {
|
void Transform::setMatrix(const QMatrix4x4 & m) {
|
||||||
if (m != matrix()) {
|
if (m != matrix()) {
|
||||||
m_matrix = m;
|
m_matrix = m;
|
||||||
m_matrixDirty = false;
|
m_matrixDirty = false;
|
||||||
QVector3D s;
|
QVector3D s;
|
||||||
QVector3D t;
|
QVector3D t;
|
||||||
QVector3D r;
|
QVector3D r;
|
||||||
decomposeQMatrix4x4(m, t, r, s);
|
decomposeQMatrix4x4(m, t, r, s);
|
||||||
m_scale = s;
|
m_scale = s;
|
||||||
m_translation = t;
|
m_translation = t;
|
||||||
m_eulerRotationAngles = r;
|
m_eulerRotationAngles = r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Transform::setRotationX(float r) {
|
void Transform::setRotationX(float r) {
|
||||||
if (m_eulerRotationAngles.x() == r)
|
if (m_eulerRotationAngles.x() == r) return;
|
||||||
return;
|
|
||||||
m_eulerRotationAngles.setX(r);
|
m_eulerRotationAngles.setX(r);
|
||||||
m_matrixDirty = true;
|
m_matrixDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Transform::setRotationY(float r) {
|
void Transform::setRotationY(float r) {
|
||||||
if (m_eulerRotationAngles.y() == r)
|
if (m_eulerRotationAngles.y() == r) return;
|
||||||
return;
|
|
||||||
m_eulerRotationAngles.setY(r);
|
m_eulerRotationAngles.setY(r);
|
||||||
m_matrixDirty = true;
|
m_matrixDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Transform::setRotationZ(float r) {
|
void Transform::setRotationZ(float r) {
|
||||||
if (m_eulerRotationAngles.z() == r)
|
if (m_eulerRotationAngles.z() == r) return;
|
||||||
return;
|
|
||||||
m_eulerRotationAngles.setZ(r);
|
m_eulerRotationAngles.setZ(r);
|
||||||
m_matrixDirty = true;
|
m_matrixDirty = true;
|
||||||
}
|
}
|
||||||
@@ -230,7 +231,7 @@ QMatrix4x4 Transform::matrixRotateScale() const {
|
|||||||
|
|
||||||
|
|
||||||
QVector3D Transform::direction() const {
|
QVector3D Transform::direction() const {
|
||||||
return matrixRotate().mapVector(QVector3D(0,0,-1)).normalized();
|
return matrixRotate().mapVector(QVector3D(0, 0, -1)).normalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -238,7 +239,7 @@ void Transform::buildMatrix() const {
|
|||||||
if (m_matrixDirty) {
|
if (m_matrixDirty) {
|
||||||
composeQMatrix4x4(m_translation, m_eulerRotationAngles, m_scale, m_matrix);
|
composeQMatrix4x4(m_translation, m_eulerRotationAngles, m_scale, m_matrix);
|
||||||
composeQMatrix4x4(QVector3D(), m_eulerRotationAngles, m_scale, m_matrixWT);
|
composeQMatrix4x4(QVector3D(), m_eulerRotationAngles, m_scale, m_matrixWT);
|
||||||
composeQMatrix4x4(QVector3D(), m_eulerRotationAngles, QVector3D(1,1,1), m_matrixR);
|
composeQMatrix4x4(QVector3D(), m_eulerRotationAngles, QVector3D(1, 1, 1), m_matrixR);
|
||||||
composeQMatrix4x4(QVector3D(), QVector3D(), m_scale, m_matrixS);
|
composeQMatrix4x4(QVector3D(), QVector3D(), m_scale, m_matrixS);
|
||||||
m_matrixDirty = false;
|
m_matrixDirty = false;
|
||||||
}
|
}
|
||||||
@@ -262,7 +263,7 @@ float Transform::rotationZ() const {
|
|||||||
|
|
||||||
void Transform::setScale(const QVector3D & s) {
|
void Transform::setScale(const QVector3D & s) {
|
||||||
if (s != m_scale) {
|
if (s != m_scale) {
|
||||||
m_scale = s;
|
m_scale = s;
|
||||||
m_matrixDirty = true;
|
m_matrixDirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -305,7 +306,7 @@ float Transform::scale() const {
|
|||||||
void Transform::setRotation(const QVector3D & r) {
|
void Transform::setRotation(const QVector3D & r) {
|
||||||
if (r != m_eulerRotationAngles) {
|
if (r != m_eulerRotationAngles) {
|
||||||
m_eulerRotationAngles = r;
|
m_eulerRotationAngles = r;
|
||||||
m_matrixDirty = true;
|
m_matrixDirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,17 +363,19 @@ QQuaternion Transform::fromAxisAndAngle(float x, float y, float z, float angle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QQuaternion Transform::fromAxesAndAngles(const QVector3D & axis1, float angle1,
|
QQuaternion Transform::fromAxesAndAngles(const QVector3D & axis1, float angle1, const QVector3D & axis2, float angle2) {
|
||||||
const QVector3D & axis2, float angle2) {
|
|
||||||
const QQuaternion q1 = QQuaternion::fromAxisAndAngle(axis1, angle1);
|
const QQuaternion q1 = QQuaternion::fromAxisAndAngle(axis1, angle1);
|
||||||
const QQuaternion q2 = QQuaternion::fromAxisAndAngle(axis2, angle2);
|
const QQuaternion q2 = QQuaternion::fromAxisAndAngle(axis2, angle2);
|
||||||
return q2 * q1;
|
return q2 * q1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QQuaternion Transform::fromAxesAndAngles(const QVector3D & axis1, float angle1,
|
QQuaternion Transform::fromAxesAndAngles(const QVector3D & axis1,
|
||||||
const QVector3D & axis2, float angle2,
|
float angle1,
|
||||||
const QVector3D & axis3, float angle3) {
|
const QVector3D & axis2,
|
||||||
|
float angle2,
|
||||||
|
const QVector3D & axis3,
|
||||||
|
float angle3) {
|
||||||
const QQuaternion q1 = QQuaternion::fromAxisAndAngle(axis1, angle1);
|
const QQuaternion q1 = QQuaternion::fromAxisAndAngle(axis1, angle1);
|
||||||
const QQuaternion q2 = QQuaternion::fromAxisAndAngle(axis2, angle2);
|
const QQuaternion q2 = QQuaternion::fromAxisAndAngle(axis2, angle2);
|
||||||
const QQuaternion q3 = QQuaternion::fromAxisAndAngle(axis3, angle3);
|
const QQuaternion q3 = QQuaternion::fromAxisAndAngle(axis3, angle3);
|
||||||
@@ -398,16 +401,16 @@ QVector3D Transform::fromDirection(QVector3D d, float pitch) {
|
|||||||
|
|
||||||
|
|
||||||
QVector3D Transform::fromRotationMatrix(const QMatrix3x3 & m) {
|
QVector3D Transform::fromRotationMatrix(const QMatrix3x3 & m) {
|
||||||
float sy = sqrt(m(0,0) * m(0,0) + m(1,0) * m(1,0));
|
float sy = sqrt(m(0, 0) * m(0, 0) + m(1, 0) * m(1, 0));
|
||||||
bool singular = sy < 1.E-6; // If
|
bool singular = sy < 1.E-6; // If
|
||||||
float x, y, z;
|
float x, y, z;
|
||||||
if (!singular) {
|
if (!singular) {
|
||||||
x = atan2( m(2,1), m(2,2));
|
x = atan2(m(2, 1), m(2, 2));
|
||||||
y = atan2(-m(2,0), sy);
|
y = atan2(-m(2, 0), sy);
|
||||||
z = atan2( m(1,0), m(0,0));
|
z = atan2(m(1, 0), m(0, 0));
|
||||||
} else {
|
} else {
|
||||||
x = atan2(-m(1,2), m(1,1));
|
x = atan2(-m(1, 2), m(1, 1));
|
||||||
y = atan2(-m(2,0), sy);
|
y = atan2(-m(2, 0), sy);
|
||||||
z = 0.;
|
z = 0.;
|
||||||
}
|
}
|
||||||
return QVector3D(x, y, z) * rad2deg;
|
return QVector3D(x, y, z) * rad2deg;
|
||||||
@@ -419,7 +422,7 @@ QMatrix3x3 Transform::toRotationMatrix(const QVector3D & r) {
|
|||||||
if (r.z() != 0.f) m.rotate(r.z(), 0., 0., 1.);
|
if (r.z() != 0.f) m.rotate(r.z(), 0., 0., 1.);
|
||||||
if (r.y() != 0.f) m.rotate(r.y(), 0., 1., 0.);
|
if (r.y() != 0.f) m.rotate(r.y(), 0., 1., 0.);
|
||||||
if (r.x() != 0.f) m.rotate(r.x(), 1., 0., 0.);
|
if (r.x() != 0.f) m.rotate(r.x(), 1., 0., 0.);
|
||||||
return m.toGenericMatrix<3,3>();
|
return m.toGenericMatrix<3, 3>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -433,8 +436,20 @@ QMatrix4x4 Transform::rotateAround(const QVector3D & point, float angle, const Q
|
|||||||
|
|
||||||
|
|
||||||
QMatrix4x4 Transform::rotateFromAxes(const QVector3D & xAxis, const QVector3D & yAxis, const QVector3D & zAxis) {
|
QMatrix4x4 Transform::rotateFromAxes(const QVector3D & xAxis, const QVector3D & yAxis, const QVector3D & zAxis) {
|
||||||
return QMatrix4x4(xAxis.x(), yAxis.x(), zAxis.x(), 0.0f,
|
return QMatrix4x4(xAxis.x(),
|
||||||
xAxis.y(), yAxis.y(), zAxis.y(), 0.0f,
|
yAxis.x(),
|
||||||
xAxis.z(), yAxis.z(), zAxis.z(), 0.0f,
|
zAxis.x(),
|
||||||
0.0f, 0.0f, 0.0f, 1.0f);
|
0.0f,
|
||||||
|
xAxis.y(),
|
||||||
|
yAxis.y(),
|
||||||
|
zAxis.y(),
|
||||||
|
0.0f,
|
||||||
|
xAxis.z(),
|
||||||
|
yAxis.z(),
|
||||||
|
zAxis.z(),
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
1.0f);
|
||||||
}
|
}
|
||||||
@@ -1,35 +1,38 @@
|
|||||||
/*
|
/*
|
||||||
QGL Transform
|
QGL Transform
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU Lesser General Public License for more details.
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef GLTRANSFORM_H
|
#ifndef GLTRANSFORM_H
|
||||||
#define GLTRANSFORM_H
|
#define GLTRANSFORM_H
|
||||||
|
|
||||||
|
#include "qglengine_core_export.h"
|
||||||
|
|
||||||
#include <QMatrix4x4>
|
#include <QMatrix4x4>
|
||||||
#include <QQuaternion>
|
#include <QQuaternion>
|
||||||
#include <QVector3D>
|
#include <QVector3D>
|
||||||
#include <chunkstream.h>
|
#include <chunkstream.h>
|
||||||
|
|
||||||
|
|
||||||
class Transform {
|
class QGLENGINE_CORE_EXPORT Transform {
|
||||||
friend QDataStream & operator >>(QDataStream & s, Transform & v);
|
friend QDataStream & operator>>(QDataStream & s, Transform & v);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Transform();
|
Transform();
|
||||||
Transform & operator =(const Transform & t);
|
Transform & operator=(const Transform & t);
|
||||||
|
|
||||||
float scale() const;
|
float scale() const;
|
||||||
QVector3D scale3D() const;
|
QVector3D scale3D() const;
|
||||||
@@ -45,7 +48,7 @@ public:
|
|||||||
float rotationY() const;
|
float rotationY() const;
|
||||||
float rotationZ() const;
|
float rotationZ() const;
|
||||||
|
|
||||||
void setScale(float s) {setScale(QVector3D(s, s, s));}
|
void setScale(float s) { setScale(QVector3D(s, s, s)); }
|
||||||
void setScale(const QVector3D & s);
|
void setScale(const QVector3D & s);
|
||||||
void setScaleX(float s);
|
void setScaleX(float s);
|
||||||
void setScaleY(float s);
|
void setScaleY(float s);
|
||||||
@@ -62,17 +65,15 @@ public:
|
|||||||
void setTranslationZ(float t);
|
void setTranslationZ(float t);
|
||||||
|
|
||||||
void setMatrix(const QMatrix4x4 & matrix);
|
void setMatrix(const QMatrix4x4 & matrix);
|
||||||
void setDirty(bool yes = true) {m_matrixDirty = yes;}
|
void setDirty(bool yes = true) { m_matrixDirty = yes; }
|
||||||
|
|
||||||
|
|
||||||
static QQuaternion fromAxisAndAngle(const QVector3D & axis, float angle);
|
static QQuaternion fromAxisAndAngle(const QVector3D & axis, float angle);
|
||||||
static QQuaternion fromAxisAndAngle(float x, float y, float z, float angle);
|
static QQuaternion fromAxisAndAngle(float x, float y, float z, float angle);
|
||||||
|
|
||||||
static QQuaternion fromAxesAndAngles(const QVector3D & axis1, float angle1,
|
static QQuaternion fromAxesAndAngles(const QVector3D & axis1, float angle1, const QVector3D & axis2, float angle2);
|
||||||
const QVector3D & axis2, float angle2);
|
static QQuaternion
|
||||||
static QQuaternion fromAxesAndAngles(const QVector3D & axis1, float angle1,
|
fromAxesAndAngles(const QVector3D & axis1, float angle1, const QVector3D & axis2, float angle2, const QVector3D & axis3, float angle3);
|
||||||
const QVector3D & axis2, float angle2,
|
|
||||||
const QVector3D & axis3, float angle3);
|
|
||||||
static QQuaternion fromAxes(const QVector3D & xAxis, const QVector3D & yAxis, const QVector3D & zAxis);
|
static QQuaternion fromAxes(const QVector3D & xAxis, const QVector3D & yAxis, const QVector3D & zAxis);
|
||||||
|
|
||||||
static QVector3D fromDirection(QVector3D d, float pitch = 0.f);
|
static QVector3D fromDirection(QVector3D d, float pitch = 0.f);
|
||||||
@@ -91,14 +92,14 @@ protected:
|
|||||||
|
|
||||||
mutable QMatrix4x4 m_matrix, m_matrixWT, m_matrixR, m_matrixS;
|
mutable QMatrix4x4 m_matrix, m_matrixWT, m_matrixR, m_matrixS;
|
||||||
mutable bool m_matrixDirty;
|
mutable bool m_matrixDirty;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
inline QDataStream & operator <<(QDataStream & s, const Transform & v) {
|
inline QDataStream & operator<<(QDataStream & s, const Transform & v) {
|
||||||
s << v.matrix(); return s;
|
s << v.matrix();
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
inline QDataStream & operator >>(QDataStream & s, Transform & v) {
|
inline QDataStream & operator>>(QDataStream & s, Transform & v) {
|
||||||
QMatrix4x4 m;
|
QMatrix4x4 m;
|
||||||
s >> m;
|
s >> m;
|
||||||
v.setMatrix(m);
|
v.setMatrix(m);
|
||||||
@@ -1,26 +1,27 @@
|
|||||||
/*
|
/*
|
||||||
QGLView Types
|
QGLView Types
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU Lesser General Public License for more details.
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "glcamera.h"
|
#include "glcamera.h"
|
||||||
#include "qglview.h"
|
|
||||||
#include "gltexture_manager.h"
|
#include "gltexture_manager.h"
|
||||||
|
#include "qglview.h"
|
||||||
|
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include <QRandomGenerator>
|
||||||
|
|
||||||
|
|
||||||
QString readCharsUntilNull(QDataStream & s) {
|
QString readCharsUntilNull(QDataStream & s) {
|
||||||
@@ -37,15 +38,14 @@ QString readCharsUntilNull(QDataStream & s) {
|
|||||||
|
|
||||||
QString findFile(const QString & file, const QStringList & pathes) {
|
QString findFile(const QString & file, const QStringList & pathes) {
|
||||||
QFileInfo fi(QString(file).replace("\\", "/"));
|
QFileInfo fi(QString(file).replace("\\", "/"));
|
||||||
//qDebug() << "search" << file << "in" << pathes;
|
// qDebug() << "search" << file << "in" << pathes;
|
||||||
if (fi.exists()) return fi.absoluteFilePath();
|
if (fi.exists()) return fi.absoluteFilePath();
|
||||||
QString fn = fi.fileName();
|
QString fn = fi.fileName();
|
||||||
if (fn.contains("/")) fn = fn.mid(fn.lastIndexOf("/"));
|
if (fn.contains("/")) fn = fn.mid(fn.lastIndexOf("/"));
|
||||||
foreach (QString p, pathes) {
|
foreach(QString p, pathes) {
|
||||||
QFileInfoList fil = QDir(p).entryInfoList(QStringList(fn), QDir::Files | QDir::NoDotAndDotDot);
|
QFileInfoList fil = QDir(p).entryInfoList(QStringList(fn), QDir::Files | QDir::NoDotAndDotDot);
|
||||||
//qDebug() << "findFile" << fn << "in" << p << "->" << fil.size();
|
// qDebug() << "findFile" << fn << "in" << p << "->" << fil.size();
|
||||||
if (!fil.isEmpty())
|
if (!fil.isEmpty()) return fil[0].absoluteFilePath();
|
||||||
return fil[0].absoluteFilePath();
|
|
||||||
}
|
}
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
@@ -55,21 +55,28 @@ void glDrawQuad(QOpenGLShaderProgram * prog, QVector4D * corner_dirs, GLfloat x,
|
|||||||
glSetPolygonMode(GL_FILL);
|
glSetPolygonMode(GL_FILL);
|
||||||
glDisable(GL_LIGHTING);
|
glDisable(GL_LIGHTING);
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
int loc = prog ? prog->attributeLocation("qgl_Color") : -1,
|
// glColor4f(1, 1, 1, 1);
|
||||||
locv = prog ? prog->attributeLocation("qgl_Vertex") : -1,
|
int loc = prog ? prog->attributeLocation("qgl_Color") : -1, locv = prog ? prog->attributeLocation("qgl_Vertex") : -1,
|
||||||
loct = prog ? prog->attributeLocation("qgl_Texture") : -1,
|
loct = prog ? prog->attributeLocation("qgl_Texture") : -1, locc = prog ? prog->attributeLocation("view_corner") : -1;
|
||||||
locc = prog ? prog->attributeLocation("view_corner") : -1;
|
|
||||||
QOpenGLFunctions * glFuncs = QOpenGLContext::currentContext()->functions();
|
QOpenGLFunctions * glFuncs = QOpenGLContext::currentContext()->functions();
|
||||||
if (prog) {
|
if (prog) {
|
||||||
static const GLfloat cols [] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f};
|
static const GLfloat cols[] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f};
|
||||||
static const GLfloat verts[] = {x, y, x+w, y, x, y+h, x+w, y+h};
|
static const GLfloat verts[] = {x, y, x + w, y, x, y + h, x + w, y + h};
|
||||||
static const GLfloat texs [] = {0.f, 0.f, 1.f, 0.f, 0.f, 1.f, 1.f, 1.f};
|
static const GLfloat texs[] = {0.f, 0.f, 1.f, 0.f, 0.f, 1.f, 1.f, 1.f};
|
||||||
GLfloat vcs[] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f};
|
GLfloat vcs[] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f};
|
||||||
if (corner_dirs) {
|
if (corner_dirs) {
|
||||||
vcs[0] = corner_dirs[0].x(); vcs[1] = corner_dirs[0].y(); vcs[2] = corner_dirs[0].z();
|
vcs[0] = corner_dirs[0].x();
|
||||||
vcs[3] = corner_dirs[1].x(); vcs[4] = corner_dirs[1].y(); vcs[5] = corner_dirs[1].z();
|
vcs[1] = corner_dirs[0].y();
|
||||||
vcs[6] = corner_dirs[2].x(); vcs[7] = corner_dirs[2].y(); vcs[8] = corner_dirs[2].z();
|
vcs[2] = corner_dirs[0].z();
|
||||||
vcs[9] = corner_dirs[3].x(); vcs[10] = corner_dirs[3].y(); vcs[11] = corner_dirs[3].z();
|
vcs[3] = corner_dirs[1].x();
|
||||||
|
vcs[4] = corner_dirs[1].y();
|
||||||
|
vcs[5] = corner_dirs[1].z();
|
||||||
|
vcs[6] = corner_dirs[2].x();
|
||||||
|
vcs[7] = corner_dirs[2].y();
|
||||||
|
vcs[8] = corner_dirs[2].z();
|
||||||
|
vcs[9] = corner_dirs[3].x();
|
||||||
|
vcs[10] = corner_dirs[3].y();
|
||||||
|
vcs[11] = corner_dirs[3].z();
|
||||||
}
|
}
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
glDisableClientState(GL_NORMAL_ARRAY);
|
glDisableClientState(GL_NORMAL_ARRAY);
|
||||||
@@ -92,10 +99,14 @@ void glDrawQuad(QOpenGLShaderProgram * prog, QVector4D * corner_dirs, GLfloat x,
|
|||||||
} else {
|
} else {
|
||||||
glBegin(GL_TRIANGLE_STRIP);
|
glBegin(GL_TRIANGLE_STRIP);
|
||||||
glColor4f(1.f, 1.f, 1.f, 1.f);
|
glColor4f(1.f, 1.f, 1.f, 1.f);
|
||||||
glTexCoord2f(0.f, 0.f); glVertex2f(x, y);
|
glTexCoord2f(0.f, 0.f);
|
||||||
glTexCoord2f(1.f, 0.f); glVertex2f(x+w, y);
|
glVertex2f(x, y);
|
||||||
glTexCoord2f(0.f, 1.f); glVertex2f(x, y+h);
|
glTexCoord2f(1.f, 0.f);
|
||||||
glTexCoord2f(1.f, 1.f); glVertex2f(x+w, y+h);
|
glVertex2f(x + w, y);
|
||||||
|
glTexCoord2f(0.f, 1.f);
|
||||||
|
glVertex2f(x, y + h);
|
||||||
|
glTexCoord2f(1.f, 1.f);
|
||||||
|
glVertex2f(x + w, y + h);
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,15 +151,13 @@ void createGLTexture(QOpenGLExtraFunctions * f, GLuint & tex, int width, int hei
|
|||||||
f->glTexImage2D(target, 0, format, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, nullptr);
|
f->glTexImage2D(target, 0, format, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, nullptr);
|
||||||
else {
|
else {
|
||||||
int type = GL_UNSIGNED_BYTE;
|
int type = GL_UNSIGNED_BYTE;
|
||||||
int fmt = GL_RGBA;
|
int fmt = GL_RGBA;
|
||||||
if (format == GL_RGB32F || format == GL_RGB16F || format == GL_RGBA32F || format == GL_RGBA16F)
|
if (format == GL_RGB32F || format == GL_RGB16F || format == GL_RGBA32F || format == GL_RGBA16F) type = GL_FLOAT;
|
||||||
type = GL_FLOAT;
|
if (format == GL_RGB32F || format == GL_RGB16F || format == GL_RGB8 || format == GL_RGB) fmt = GL_RGB;
|
||||||
if (format == GL_RGB32F || format == GL_RGB16F || format == GL_RGB8 || format == GL_RGB)
|
|
||||||
fmt = GL_RGB;
|
|
||||||
f->glTexImage2D(target, 0, format, width, height, 0, fmt, type, nullptr);
|
f->glTexImage2D(target, 0, format, width, height, 0, fmt, type, nullptr);
|
||||||
//qDebug() << "glTexImage2D" << width << height << QString::number(t, 16);
|
// qDebug() << "glTexImage2D" << width << height << QString::number(t, 16);
|
||||||
}
|
}
|
||||||
//qDebug() << QString::number(glGetError(), 16);
|
// qDebug() << QString::number(glGetError(), 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -174,7 +183,7 @@ void createGLTexture(QOpenGLExtraFunctions * f, GLuint & tex, const QImage & ima
|
|||||||
if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D || target == GL_TEXTURE_3D) {
|
if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D || target == GL_TEXTURE_3D) {
|
||||||
f->glGenerateMipmap(target);
|
f->glGenerateMipmap(target);
|
||||||
}
|
}
|
||||||
//qDebug() << target << format << tex << im.width() << im.height() << im.bits() << QString::number(glGetError(), 16);
|
// qDebug() << target << format << tex << im.width() << im.height() << im.bits() << QString::number(glGetError(), 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -216,14 +225,15 @@ QImage rotateQImageRight(const QImage & im) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
QColor colorFromString(const QString & str) {
|
QColor colorFromString(const QString & str) {
|
||||||
QString s = str.trimmed();
|
QString s = str.trimmed();
|
||||||
int i = s.indexOf("\t");
|
int i = s.indexOf("\t");
|
||||||
float r, g, b;
|
float r, g, b;
|
||||||
r = s.left(i).toFloat(); s = s.right(s.length() - i - 1); i = s.indexOf("\t");
|
r = s.left(i).toFloat();
|
||||||
g = s.left(i).toFloat(); s = s.right(s.length() - i - 1);
|
s = s.right(s.length() - i - 1);
|
||||||
|
i = s.indexOf("\t");
|
||||||
|
g = s.left(i).toFloat();
|
||||||
|
s = s.right(s.length() - i - 1);
|
||||||
b = s.toFloat();
|
b = s.toFloat();
|
||||||
return QColor(r * 255.f, g * 255.f, b * 255.f);
|
return QColor(r * 255.f, g * 255.f, b * 255.f);
|
||||||
}
|
}
|
||||||
@@ -232,9 +242,12 @@ QColor colorFromString(const QString & str) {
|
|||||||
QVector3D orthToVector(const QVector3D & v, const float & scale) {
|
QVector3D orthToVector(const QVector3D & v, const float & scale) {
|
||||||
if (v.isNull()) return QVector3D();
|
if (v.isNull()) return QVector3D();
|
||||||
QVector3D rv, fn, sn;
|
QVector3D rv, fn, sn;
|
||||||
if (v.x() != 0.f) rv.setZ(1.);
|
if (v.x() != 0.f)
|
||||||
else if (v.y() != 0.f) rv.setX(1.);
|
rv.setZ(1.);
|
||||||
else rv.setY(1.);
|
else if (v.y() != 0.f)
|
||||||
|
rv.setX(1.);
|
||||||
|
else
|
||||||
|
rv.setY(1.);
|
||||||
fn = QVector3D::crossProduct(v, rv).normalized();
|
fn = QVector3D::crossProduct(v, rv).normalized();
|
||||||
sn = QVector3D::crossProduct(v, fn).normalized();
|
sn = QVector3D::crossProduct(v, fn).normalized();
|
||||||
return fn * urand(scale) + sn * urand(scale);
|
return fn * urand(scale) + sn * urand(scale);
|
||||||
@@ -268,18 +281,22 @@ void lengthenVector(QVector3D & v, const float & l) {
|
|||||||
|
|
||||||
Vector2i::Vector2i(const QString & str) {
|
Vector2i::Vector2i(const QString & str) {
|
||||||
QString s = str.trimmed();
|
QString s = str.trimmed();
|
||||||
int i = s.indexOf("\t");
|
int i = s.indexOf("\t");
|
||||||
p0 = s.left(i).toInt(); s = s.right(s.length() - i - 1);
|
p0 = s.left(i).toInt();
|
||||||
p1 = s.toInt();
|
s = s.right(s.length() - i - 1);
|
||||||
|
p1 = s.toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Vector3i::Vector3i(const QString & str) {
|
Vector3i::Vector3i(const QString & str) {
|
||||||
QString s = str.trimmed();
|
QString s = str.trimmed();
|
||||||
int i = s.indexOf("\t");
|
int i = s.indexOf("\t");
|
||||||
p0 = s.left(i).toInt(); s = s.right(s.length() - i - 1); i = s.indexOf("\t");
|
p0 = s.left(i).toInt();
|
||||||
p1 = s.left(i).toInt(); s = s.right(s.length() - i - 1);
|
s = s.right(s.length() - i - 1);
|
||||||
p2 = s.toInt();
|
i = s.indexOf("\t");
|
||||||
|
p1 = s.left(i).toInt();
|
||||||
|
s = s.right(s.length() - i - 1);
|
||||||
|
p2 = s.toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -305,8 +322,6 @@ void glClearFramebuffer(const QColor & color, bool depth) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Box3D::Box3D(const QVector<QVector3D> & points) {
|
Box3D::Box3D(const QVector<QVector3D> & points) {
|
||||||
x = y = z = width = length = height = angle_z = angle_xy = angle_roll = 0.f;
|
x = y = z = width = length = height = angle_z = angle_xy = angle_roll = 0.f;
|
||||||
if (points.isEmpty()) return;
|
if (points.isEmpty()) return;
|
||||||
@@ -315,13 +330,16 @@ Box3D::Box3D(const QVector<QVector3D> & points) {
|
|||||||
iy = ay = points[0].y();
|
iy = ay = points[0].y();
|
||||||
iz = az = points[0].z();
|
iz = az = points[0].z();
|
||||||
for (int i = 1; i < points.size(); ++i) {
|
for (int i = 1; i < points.size(); ++i) {
|
||||||
ix = qMin<float>(ix, points[i].x()); ax = qMax<float>(ax, points[i].x());
|
ix = qMin<float>(ix, points[i].x());
|
||||||
iy = qMin<float>(iy, points[i].y()); ay = qMax<float>(ay, points[i].y());
|
ax = qMax<float>(ax, points[i].x());
|
||||||
iz = qMin<float>(iz, points[i].z()); az = qMax<float>(az, points[i].z());
|
iy = qMin<float>(iy, points[i].y());
|
||||||
|
ay = qMax<float>(ay, points[i].y());
|
||||||
|
iz = qMin<float>(iz, points[i].z());
|
||||||
|
az = qMax<float>(az, points[i].z());
|
||||||
}
|
}
|
||||||
x = ix;
|
x = ix;
|
||||||
y = iy;
|
y = iy;
|
||||||
z = iz;
|
z = iz;
|
||||||
length = ax - ix;
|
length = ax - ix;
|
||||||
width = ay - iy;
|
width = ay - iy;
|
||||||
height = az - iz;
|
height = az - iz;
|
||||||
@@ -331,32 +349,60 @@ Box3D::Box3D(const QVector<QVector3D> & points) {
|
|||||||
QVector<QVector3D> Box3D::corners() const {
|
QVector<QVector3D> Box3D::corners() const {
|
||||||
QVector<QVector3D> ret;
|
QVector<QVector3D> ret;
|
||||||
ret << QVector3D(x, y, z) << QVector3D(x, y + width, z) << QVector3D(x, y, z + height) << QVector3D(x, y + width, z + height)
|
ret << QVector3D(x, y, z) << QVector3D(x, y + width, z) << QVector3D(x, y, z + height) << QVector3D(x, y + width, z + height)
|
||||||
<< QVector3D(x + length, y, z) << QVector3D(x + length, y + width, z)
|
<< QVector3D(x + length, y, z) << QVector3D(x + length, y + width, z) << QVector3D(x + length, y, z + height)
|
||||||
<< QVector3D(x + length, y, z + height) << QVector3D(x + length, y + width, z + height);
|
<< QVector3D(x + length, y + width, z + height);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Box3D & Box3D::operator |=(const Box3D & o) {
|
Box3D & Box3D::operator|=(const Box3D & o) {
|
||||||
if (o.isEmpty()) return *this;
|
if (o.isEmpty()) return *this;
|
||||||
if (isEmpty()) *this = o;
|
if (isEmpty())
|
||||||
|
*this = o;
|
||||||
else {
|
else {
|
||||||
GLfloat mx = x + length, my = y + width, mz = z + height;
|
GLfloat mx = x + length, my = y + width, mz = z + height;
|
||||||
GLfloat omx = o.x + o.length, omy = o.y + o.width, omz = o.z + o.height;
|
GLfloat omx = o.x + o.length, omy = o.y + o.width, omz = o.z + o.height;
|
||||||
x = qMin(x, o.x); y = qMin(y, o.y); z = qMin(z, o.z);
|
x = qMin(x, o.x);
|
||||||
mx = qMax(mx, omx); my = qMax(my, omy); mz = qMax(mz, omz);
|
y = qMin(y, o.y);
|
||||||
length = mx - x; width = my - y; height = mz - z;
|
z = qMin(z, o.z);
|
||||||
|
mx = qMax(mx, omx);
|
||||||
|
my = qMax(my, omy);
|
||||||
|
mz = qMax(mz, omz);
|
||||||
|
length = mx - x;
|
||||||
|
width = my - y;
|
||||||
|
height = mz - z;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QVector3D vectorFromString(const QString & str) {
|
QVector3D vectorFromString(const QString & str) {
|
||||||
QTextStream s(const_cast<QString*>(&str), QIODevice::ReadOnly);
|
QTextStream s(const_cast<QString *>(&str), QIODevice::ReadOnly);
|
||||||
QVector3D ret;
|
QVector3D ret;
|
||||||
float f(0.f);
|
float f(0.f);
|
||||||
s >> f; ret.setX(f);
|
s >> f;
|
||||||
s >> f; ret.setY(f);
|
ret.setX(f);
|
||||||
s >> f; ret.setZ(f);
|
s >> f;
|
||||||
|
ret.setY(f);
|
||||||
|
s >> f;
|
||||||
|
ret.setZ(f);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QImage generateNoise(QSize sz) {
|
||||||
|
QImage im(sz, QImage::Format_ARGB32);
|
||||||
|
QRandomGenerator rg[2] = {1, 2};
|
||||||
|
uint pcnt = im.sizeInBytes() / sizeof(QRgb);
|
||||||
|
QRgb * data = (QRgb *)im.bits();
|
||||||
|
for (uint i = 0; i < pcnt; ++i) {
|
||||||
|
double r = rg[0].generateDouble();
|
||||||
|
double a = rg[0].generateDouble() * M_2PI;
|
||||||
|
double x = r * cos(a) / 2. + 0.5, y = r * sin(a) / 2. + 0.5;
|
||||||
|
data[i] = qRgba(qRound(x * 256),
|
||||||
|
qRound(y * 256),
|
||||||
|
(rg[1].generate() % sz.width()) % 256,
|
||||||
|
(rg[1].generate() % sz.height()) % 256); // argb GLSL
|
||||||
|
}
|
||||||
|
return im;
|
||||||
|
}
|
||||||
500
src/core/core/gltypes.h
Normal file
500
src/core/core/gltypes.h
Normal file
@@ -0,0 +1,500 @@
|
|||||||
|
/*
|
||||||
|
QGLView Types
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLTYPES_H
|
||||||
|
#define GLTYPES_H
|
||||||
|
|
||||||
|
#if WIN32 || WIN64 || _WIN32 || _WIN64 || __WIN32__ || __WIN64__
|
||||||
|
# define WINDOWS
|
||||||
|
#endif
|
||||||
|
#if __QNX__ || __QNXNTO__
|
||||||
|
# define QNX
|
||||||
|
#endif
|
||||||
|
#ifdef __APPLE__
|
||||||
|
# define MAC
|
||||||
|
#endif
|
||||||
|
#ifndef WINDOWS
|
||||||
|
# ifndef QNX
|
||||||
|
# ifndef MAC
|
||||||
|
# define LINUX
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#if __GNUC__
|
||||||
|
# define CC_GCC
|
||||||
|
#elif _MSC_VER
|
||||||
|
# define CC_VC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
// #ifndef WINDOWS
|
||||||
|
// # ifdef MAC
|
||||||
|
// # include <OpenGL/gl.h>
|
||||||
|
// # include <OpenGL/glu.h>
|
||||||
|
// # include <GLUT/glut.h>
|
||||||
|
// # else
|
||||||
|
// # include <GL/gl.h>
|
||||||
|
// # include <GL/glext.h>
|
||||||
|
// # include <GL/glu.h>
|
||||||
|
// # endif
|
||||||
|
// #endif
|
||||||
|
#include <QColor>
|
||||||
|
#include <QDataStream>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QImage>
|
||||||
|
#include <QMatrix4x4>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QOpenGLExtraFunctions>
|
||||||
|
#include <QOpenGLShader>
|
||||||
|
#include <QOpenGLShaderProgram>
|
||||||
|
#include <QVector2D>
|
||||||
|
#include <QVector3D>
|
||||||
|
#include <cmath>
|
||||||
|
#include <float.h>
|
||||||
|
#include <qopenglext.h>
|
||||||
|
#ifndef QNX
|
||||||
|
# include <cmath>
|
||||||
|
# include <complex>
|
||||||
|
#else
|
||||||
|
# include <complex.h>
|
||||||
|
# include <math.h>
|
||||||
|
#endif
|
||||||
|
#include "pimathbase.h"
|
||||||
|
#include "qglengine_core_export.h"
|
||||||
|
#include "qglengine_version.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
// #ifdef WINDOWS
|
||||||
|
// # define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
|
||||||
|
// # define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
#ifndef M_PI
|
||||||
|
# define M_PI 3.14159265358979323846
|
||||||
|
#endif
|
||||||
|
#ifndef M_2PI
|
||||||
|
# define M_2PI 6.28318530717958647692
|
||||||
|
#endif
|
||||||
|
#ifndef M_PI_3
|
||||||
|
# define M_PI_3 1.04719755119659774615
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_RGBA16F
|
||||||
|
# define GL_RGBA16F GL_RGBA16F_ARB
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using std::complex;
|
||||||
|
|
||||||
|
#ifndef PIP_VERSION
|
||||||
|
typedef long long llong;
|
||||||
|
typedef unsigned char uchar;
|
||||||
|
typedef unsigned short int ushort;
|
||||||
|
typedef unsigned int uint;
|
||||||
|
typedef unsigned long ulong;
|
||||||
|
typedef unsigned long long ullong;
|
||||||
|
typedef long double ldouble;
|
||||||
|
|
||||||
|
const float deg2rad = atanf(1.f) / 45.f;
|
||||||
|
const float rad2deg = 45.f / atanf(1.f);
|
||||||
|
|
||||||
|
# ifdef WINDOWS
|
||||||
|
inline int random() {
|
||||||
|
return rand();
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define random randomi
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CC_VC
|
||||||
|
inline float round(const float & v) {
|
||||||
|
return floor(v + 0.5);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
inline float randomu() {
|
||||||
|
return float(random()) / RAND_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const QSizeF operator*(const QSizeF & f, const QSizeF & s) {
|
||||||
|
return QSizeF(f.width() * s.width(), f.height() * s.height());
|
||||||
|
}
|
||||||
|
#ifndef PIP_VERSION
|
||||||
|
template<typename T>
|
||||||
|
inline void piSwap(T & f, T & s) {
|
||||||
|
T t(f);
|
||||||
|
f = s;
|
||||||
|
s = t;
|
||||||
|
}
|
||||||
|
template<typename Type>
|
||||||
|
inline Type piMin(const Type & f, const Type & s) {
|
||||||
|
return (f > s) ? s : f;
|
||||||
|
}
|
||||||
|
template<typename Type>
|
||||||
|
inline Type piMin(const Type & f, const Type & s, const Type & t) {
|
||||||
|
return (f < s && f < t) ? f : ((s < t) ? s : t);
|
||||||
|
}
|
||||||
|
template<typename Type>
|
||||||
|
inline Type piMax(const Type & f, const Type & s) {
|
||||||
|
return (f < s) ? s : f;
|
||||||
|
}
|
||||||
|
template<typename Type>
|
||||||
|
inline Type piMax(const Type & f, const Type & s, const Type & t) {
|
||||||
|
return (f > s && f > t) ? f : ((s > t) ? s : t);
|
||||||
|
}
|
||||||
|
template<typename Type>
|
||||||
|
inline Type piClamp(const Type & v, const Type & min, const Type & max) {
|
||||||
|
return (v > max ? max : (v < min ? min : v));
|
||||||
|
}
|
||||||
|
inline ushort letobe_s(ushort v) {
|
||||||
|
return (v << 8) | (v >> 8);
|
||||||
|
}
|
||||||
|
inline uint letobe_i(const uint & v) {
|
||||||
|
return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// return [-1, 1]
|
||||||
|
inline float urand(const float & scale = 1.) {
|
||||||
|
return ((float)rand() / RAND_MAX - .5f) * (scale + scale);
|
||||||
|
}
|
||||||
|
// return [0, 1]
|
||||||
|
inline float uprand(const float & scale = 1.) {
|
||||||
|
return ((float)rand() / RAND_MAX) * scale;
|
||||||
|
}
|
||||||
|
QGLENGINE_CORE_EXPORT QString readCharsUntilNull(QDataStream & s);
|
||||||
|
QGLENGINE_CORE_EXPORT QString findFile(const QString & file, const QStringList & pathes);
|
||||||
|
inline QColor operator*(const QColor & c, float v) {
|
||||||
|
return QColor(piClamp<int>(c.red() * v, 0, 255),
|
||||||
|
piClamp<int>(c.green() * v, 0, 255),
|
||||||
|
piClamp<int>(c.blue() * v, 0, 255),
|
||||||
|
piClamp<int>(c.alpha() * v, 0, 255));
|
||||||
|
}
|
||||||
|
inline QColor operator/(const QColor & c, float v) {
|
||||||
|
return QColor(piClamp<int>(c.red() / v, 0, 255),
|
||||||
|
piClamp<int>(c.green() / v, 0, 255),
|
||||||
|
piClamp<int>(c.blue() / v, 0, 255),
|
||||||
|
piClamp<int>(c.alpha() / v, 0, 255));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void qglColor(const QColor & c) {
|
||||||
|
glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());
|
||||||
|
}
|
||||||
|
inline void glClearError() {
|
||||||
|
int c = 100;
|
||||||
|
while (glGetError() != GL_NO_ERROR && --c > 0)
|
||||||
|
glGetError();
|
||||||
|
}
|
||||||
|
inline void glSetCapEnabled(GLenum cap, bool on = true) {
|
||||||
|
if (on)
|
||||||
|
glEnable(cap);
|
||||||
|
else
|
||||||
|
glDisable(cap);
|
||||||
|
}
|
||||||
|
inline void glSetPolygonMode(GLenum mode) {
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, mode);
|
||||||
|
}
|
||||||
|
inline void deleteGLTexture(QOpenGLExtraFunctions * f, GLuint & tex) {
|
||||||
|
if (tex != 0) f->glDeleteTextures(1, &tex);
|
||||||
|
tex = 0;
|
||||||
|
}
|
||||||
|
QGLENGINE_CORE_EXPORT void glEnableDepth();
|
||||||
|
QGLENGINE_CORE_EXPORT void glDisableDepth();
|
||||||
|
QGLENGINE_CORE_EXPORT void glClearFramebuffer(const QColor & color = Qt::black, bool depth = true);
|
||||||
|
QGLENGINE_CORE_EXPORT void glDrawQuad(QOpenGLShaderProgram * prog = nullptr,
|
||||||
|
QVector4D * corner_dirs = nullptr,
|
||||||
|
GLfloat x = -1.f,
|
||||||
|
GLfloat y = -1.f,
|
||||||
|
GLfloat w = 2.f,
|
||||||
|
GLfloat h = 2.f);
|
||||||
|
QGLENGINE_CORE_EXPORT void createGLTexture(QOpenGLExtraFunctions * f,
|
||||||
|
GLuint & tex,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
const GLenum & format = GL_RGBA,
|
||||||
|
const GLenum & target = GL_TEXTURE_2D);
|
||||||
|
QGLENGINE_CORE_EXPORT void createGLTexture(QOpenGLExtraFunctions * f,
|
||||||
|
GLuint & tex,
|
||||||
|
const QImage & image,
|
||||||
|
const GLenum & format = GL_RGBA,
|
||||||
|
const GLenum & target = GL_TEXTURE_2D);
|
||||||
|
QGLENGINE_CORE_EXPORT QMatrix4x4 glMatrixPerspective(float angle, float aspect, float near_);
|
||||||
|
QGLENGINE_CORE_EXPORT QImage rotateQImageLeft(const QImage & im);
|
||||||
|
QGLENGINE_CORE_EXPORT QImage rotateQImageRight(const QImage & im);
|
||||||
|
inline QImage rotateQImage180(const QImage & im) {
|
||||||
|
return im.mirrored(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
class QGLView;
|
||||||
|
class MouseController;
|
||||||
|
class ObjectBase;
|
||||||
|
class AimedObject;
|
||||||
|
class Light;
|
||||||
|
class Camera;
|
||||||
|
class Texture;
|
||||||
|
class CubeTexture;
|
||||||
|
class Map;
|
||||||
|
class Material;
|
||||||
|
class TextureManager;
|
||||||
|
class Texture2DArray;
|
||||||
|
class Framebuffer;
|
||||||
|
class FramebufferMipmap;
|
||||||
|
class FramebufferEffectBase;
|
||||||
|
class VertexObject;
|
||||||
|
class Mesh;
|
||||||
|
class Scene;
|
||||||
|
class RendererBase;
|
||||||
|
class Renderer;
|
||||||
|
class RendererMaterial;
|
||||||
|
class RendererService;
|
||||||
|
class RendererSelection;
|
||||||
|
|
||||||
|
enum RenderPass {
|
||||||
|
rpSolid,
|
||||||
|
rpTransparent,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef QList<ObjectBase *> ObjectBaseList;
|
||||||
|
|
||||||
|
struct QGLENGINE_CORE_EXPORT Box3D {
|
||||||
|
GLfloat x;
|
||||||
|
GLfloat y;
|
||||||
|
GLfloat z;
|
||||||
|
GLfloat width;
|
||||||
|
GLfloat length;
|
||||||
|
GLfloat height;
|
||||||
|
GLfloat angle_z;
|
||||||
|
GLfloat angle_xy;
|
||||||
|
GLfloat angle_roll;
|
||||||
|
Box3D() { x = y = z = width = length = height = angle_z = angle_xy = angle_roll = 0.f; }
|
||||||
|
Box3D(const QVector3D & center, GLfloat hwid, GLfloat hlen, GLfloat hhei) {
|
||||||
|
x = center.x() - hwid;
|
||||||
|
y = center.y() - hlen;
|
||||||
|
z = center.z() - hhei;
|
||||||
|
width = 2 * hwid;
|
||||||
|
length = 2 * hlen;
|
||||||
|
height = 2 * hhei;
|
||||||
|
angle_z = angle_xy = angle_roll = 0.f;
|
||||||
|
}
|
||||||
|
Box3D(const QVector<QVector3D> & points);
|
||||||
|
bool isEmpty() const { return (qAbs(width) < 1E-6f) && (qAbs(length) < 1E-6f) && (qAbs(height) < 1E-6f); }
|
||||||
|
QVector3D randomPoint() const { return QVector3D(uprand(length) + x, uprand(width) + y, uprand(height) + z); }
|
||||||
|
QVector3D pos() const { return QVector3D(x, y, z); }
|
||||||
|
QVector3D size() const { return QVector3D(length, width, height); }
|
||||||
|
QVector3D center() const { return QVector3D(length / 2.f + x, width / 2.f + y, height / 2.f + z); }
|
||||||
|
QVector3D angles() const { return QVector3D(angle_xy, angle_roll, angle_z); }
|
||||||
|
QVector<QVector3D> corners() const;
|
||||||
|
void setPos(const QVector3D & p) {
|
||||||
|
x = p.x();
|
||||||
|
y = p.y();
|
||||||
|
z = p.z();
|
||||||
|
}
|
||||||
|
void setAngles(const QVector3D & a) {
|
||||||
|
angle_xy = a.x();
|
||||||
|
angle_roll = a.y();
|
||||||
|
angle_z = a.z();
|
||||||
|
}
|
||||||
|
void setSize(const QVector3D & s) {
|
||||||
|
length = s.x();
|
||||||
|
width = s.y();
|
||||||
|
height = s.z();
|
||||||
|
}
|
||||||
|
Box3D & moveTo(const QVector3D & v) {
|
||||||
|
x = v.x();
|
||||||
|
y = v.y();
|
||||||
|
z = v.z();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Box3D & move(const QVector3D & v) {
|
||||||
|
x += v.x();
|
||||||
|
y += v.y();
|
||||||
|
z += v.z();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Box3D movedTo(const QVector3D & v) const {
|
||||||
|
Box3D t(*this);
|
||||||
|
t.x = v.x();
|
||||||
|
t.y = v.y();
|
||||||
|
t.z = v.z();
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
Box3D moved(const QVector3D & v) const {
|
||||||
|
Box3D t(*this);
|
||||||
|
t.x += v.x();
|
||||||
|
t.y += v.y();
|
||||||
|
t.z += v.z();
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
Box3D & operator|=(const Box3D & o);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QDebug operator<<(QDebug d, const Box3D & v) {
|
||||||
|
d << "Box3D {start (" << v.x << "," << v.y << "," << v.z << "), size (" << v.length << "," << v.width << "," << v.height << ")}";
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct QGLENGINE_CORE_EXPORT Vector2i {
|
||||||
|
Vector2i(int p0_ = 0, int p1_ = 0) {
|
||||||
|
p0 = p0_;
|
||||||
|
p1 = p1_;
|
||||||
|
}
|
||||||
|
Vector2i(const QString & str);
|
||||||
|
Vector2i movedX(const int & o) { return Vector2i(p0 + o, p1); }
|
||||||
|
Vector2i movedY(const int & o) { return Vector2i(p0, p1 + o); }
|
||||||
|
Vector2i moved(const int & x, const int & y) { return Vector2i(p0 + x, p1 + y); }
|
||||||
|
GLint p0;
|
||||||
|
GLint p1;
|
||||||
|
bool operator==(const Vector2i & o) const { return p0 == o.p0 && p1 == o.p1; }
|
||||||
|
bool operator!=(const Vector2i & o) const { return p0 != o.p0 || p1 != o.p1; }
|
||||||
|
void operator+=(int v) {
|
||||||
|
p0 += v;
|
||||||
|
p1 += v;
|
||||||
|
}
|
||||||
|
QVector2D toQVector2D() const { return QVector2D(p0, p1); }
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
inline Vector2i operator+(const Vector2i & f, const Vector2i & s) {
|
||||||
|
return Vector2i(f.p0 + s.p0, f.p1 + s.p1);
|
||||||
|
}
|
||||||
|
inline Vector2i operator-(const Vector2i & f, const Vector2i & s) {
|
||||||
|
return Vector2i(f.p0 - s.p0, f.p1 - s.p1);
|
||||||
|
}
|
||||||
|
inline Vector2i operator/(const Vector2i & f, const int & s) {
|
||||||
|
return Vector2i(f.p0 / s, f.p1 / s);
|
||||||
|
}
|
||||||
|
inline uint qHash(const Vector2i & v) {
|
||||||
|
return v.p0 ^ ((v.p1 << 8) | (v.p1 >> 24));
|
||||||
|
}
|
||||||
|
inline QDebug operator<<(QDebug d, const Vector2i & v) {
|
||||||
|
d.nospace() << "{" << v.p0 << ", " << v.p1 << "}";
|
||||||
|
return d.space();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QDataStream & operator<<(QDataStream & s, const Vector2i & v) {
|
||||||
|
s << v.p0 << v.p1;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
inline QDataStream & operator>>(QDataStream & s, Vector2i & v) {
|
||||||
|
s >> v.p0 >> v.p1;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct QGLENGINE_CORE_EXPORT Vector3i {
|
||||||
|
Vector3i(int p0_ = 0, int p1_ = 0, int p2_ = 0) {
|
||||||
|
p0 = p0_;
|
||||||
|
p1 = p1_;
|
||||||
|
p2 = p2_;
|
||||||
|
}
|
||||||
|
Vector3i(const QString & str);
|
||||||
|
Vector3i movedX(const int & o) { return Vector3i(p0 + o, p1, p2); }
|
||||||
|
Vector3i movedY(const int & o) { return Vector3i(p0, p1 + o, p2); }
|
||||||
|
Vector3i movedZ(const int & o) { return Vector3i(p0, p1, p2 + o); }
|
||||||
|
Vector3i moved(const int & x, const int & y, const int & z) { return Vector3i(p0 + x, p1 + y, p2 + z); }
|
||||||
|
GLint p0;
|
||||||
|
GLint p1;
|
||||||
|
GLint p2;
|
||||||
|
bool operator==(const Vector3i & o) const { return p0 == o.p0 && p1 == o.p1 && p2 == o.p2; }
|
||||||
|
bool operator!=(const Vector3i & o) const { return p0 != o.p0 || p1 != o.p1 || p2 != o.p2; }
|
||||||
|
void operator+=(int v) {
|
||||||
|
p0 += v;
|
||||||
|
p1 += v;
|
||||||
|
p2 += v;
|
||||||
|
}
|
||||||
|
QVector3D toQVector3D() const { return QVector3D(p0, p1, p2); }
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
inline Vector3i operator+(const Vector3i & f, const Vector3i & s) {
|
||||||
|
return Vector3i(f.p0 + s.p0, f.p1 + s.p1, f.p2 + s.p2);
|
||||||
|
}
|
||||||
|
inline Vector3i operator-(const Vector3i & f, const Vector3i & s) {
|
||||||
|
return Vector3i(f.p0 - s.p0, f.p1 - s.p1, f.p2 - s.p2);
|
||||||
|
}
|
||||||
|
inline Vector3i operator/(const Vector3i & f, const int & s) {
|
||||||
|
return Vector3i(f.p0 / s, f.p1 / s, f.p2 / s);
|
||||||
|
}
|
||||||
|
inline uint qHash(const Vector3i & v) {
|
||||||
|
return v.p0 ^ ((v.p1 << 8) | (v.p1 >> 24)) ^ ((v.p2 << 16) | (v.p2 >> 16));
|
||||||
|
}
|
||||||
|
inline QDebug operator<<(QDebug d, const Vector3i & v) {
|
||||||
|
d.nospace() << "{" << v.p0 << ", " << v.p1 << ", " << v.p2 << "}";
|
||||||
|
return d.space();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QDataStream & operator<<(QDataStream & s, const Vector3i & v) {
|
||||||
|
s << v.p0 << v.p1 << v.p2;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
inline QDataStream & operator>>(QDataStream & s, Vector3i & v) {
|
||||||
|
s >> v.p0 >> v.p1 >> v.p2;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QGLENGINE_CORE_EXPORT QVector3D vectorFromString(const QString & str);
|
||||||
|
QGLENGINE_CORE_EXPORT QColor colorFromString(const QString & str);
|
||||||
|
inline QVector4D QColor2QVector(const QColor & c) {
|
||||||
|
return QVector4D(c.redF(), c.greenF(), c.blueF(), c.alphaF());
|
||||||
|
}
|
||||||
|
inline float cosABV(const QVector3D & v0, const QVector3D & v1) {
|
||||||
|
float l = v0.length() * v1.length();
|
||||||
|
if (l == 0.f) return 0.;
|
||||||
|
return (QVector3D::dotProduct(v0, v1)) / l;
|
||||||
|
}
|
||||||
|
inline void normalizeAngleRad(float & a) {
|
||||||
|
while (a < 0.)
|
||||||
|
a += M_2PI;
|
||||||
|
while (a >= M_2PI)
|
||||||
|
a -= M_2PI;
|
||||||
|
}
|
||||||
|
inline void normalizeAngleDeg360(float & a) {
|
||||||
|
while (a < 0.)
|
||||||
|
a += 360.;
|
||||||
|
while (a >= 360.)
|
||||||
|
a -= 360.;
|
||||||
|
}
|
||||||
|
inline QVector3D projection(const QVector3D & v, const QVector3D & to) {
|
||||||
|
return to.normalized() * v.length() * cosABV(v, to);
|
||||||
|
}
|
||||||
|
QGLENGINE_CORE_EXPORT QVector3D orthToVector(const QVector3D & v, const float & scale = 1.);
|
||||||
|
QGLENGINE_CORE_EXPORT QVector3D rotateVector(const QVector3D & v, const QVector3D & a);
|
||||||
|
QGLENGINE_CORE_EXPORT void setVectorLength(QVector3D & v, const float & l);
|
||||||
|
QGLENGINE_CORE_EXPORT void lengthenVector(QVector3D & v, const float & l);
|
||||||
|
inline float squareLength(const QVector3D & from, const QVector3D & to) {
|
||||||
|
return (to.x() - from.x()) * (to.x() - from.x()) + (to.y() - from.y()) * (to.y() - from.y()) +
|
||||||
|
(to.z() - from.z()) * (to.z() - from.z());
|
||||||
|
}
|
||||||
|
inline QVector3D directionFromAngles(const QVector3D & a) {
|
||||||
|
return rotateVector(QVector3D(1., 0., 0.), a);
|
||||||
|
}
|
||||||
|
inline float frac(const float & x, const float & b) {
|
||||||
|
return x - int(x / b) * b;
|
||||||
|
}
|
||||||
|
QImage generateNoise(QSize sz);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // GLTYPES_H
|
||||||
@@ -1,39 +1,37 @@
|
|||||||
/*
|
/*
|
||||||
QGL VertexObject
|
QGL VertexObject
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU Lesser General Public License for more details.
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define GL_GLEXT_PROTOTYPES
|
#define GL_GLEXT_PROTOTYPES
|
||||||
#include <QOpenGLExtraFunctions>
|
|
||||||
#include "glvertexobject.h"
|
#include "glvertexobject.h"
|
||||||
|
|
||||||
|
#include <QOpenGLExtraFunctions>
|
||||||
|
|
||||||
using namespace QGLEngineShaders;
|
using namespace QGLEngineShaders;
|
||||||
|
|
||||||
|
|
||||||
VertexObject::VertexObject():
|
VertexObject::VertexObject(): buffer_obj(GL_ARRAY_BUFFER, GL_STREAM_DRAW), buffer_sel(GL_ARRAY_BUFFER, GL_STREAM_DRAW) {
|
||||||
buffer_obj (GL_ARRAY_BUFFER, GL_STREAM_DRAW),
|
vao_ = 0;
|
||||||
buffer_sel (GL_ARRAY_BUFFER, GL_STREAM_DRAW) {
|
buffers_binded = false;
|
||||||
vao_ = 0;
|
|
||||||
buffers_binded = false;
|
|
||||||
objects_changed = selected_changed = true;
|
objects_changed = selected_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VertexObject::~VertexObject() {
|
VertexObject::~VertexObject() {}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void VertexObject::init(QOpenGLExtraFunctions * f) {
|
void VertexObject::init(QOpenGLExtraFunctions * f) {
|
||||||
@@ -55,8 +53,17 @@ void VertexObject::destroy(QOpenGLExtraFunctions * f) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VertexObject::reinit() {
|
||||||
|
vao_ = 0;
|
||||||
|
buffer_obj.reinit();
|
||||||
|
buffer_sel.reinit();
|
||||||
|
buffers_binded = false;
|
||||||
|
objects_changed = selected_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void VertexObject::bind(QOpenGLExtraFunctions * f) {
|
void VertexObject::bind(QOpenGLExtraFunctions * f) {
|
||||||
//qDebug() << "bind" << target_ << buffer_;
|
// qDebug() << "bind" << target_ << buffer_;
|
||||||
f->glBindVertexArray(vao_);
|
f->glBindVertexArray(vao_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,6 +111,7 @@ void VertexObject::loadSelections(QOpenGLExtraFunctions * f, const QVector<uchar
|
|||||||
|
|
||||||
|
|
||||||
void VertexObject::draw(QOpenGLExtraFunctions * f, GLenum geom_type, int vert_cout, int obj_count) {
|
void VertexObject::draw(QOpenGLExtraFunctions * f, GLenum geom_type, int vert_cout, int obj_count) {
|
||||||
|
if (obj_count <= 0) return;
|
||||||
bind(f);
|
bind(f);
|
||||||
f->glDrawElementsInstanced(geom_type, vert_cout, GL_UNSIGNED_INT, 0, obj_count);
|
f->glDrawElementsInstanced(geom_type, vert_cout, GL_UNSIGNED_INT, 0, obj_count);
|
||||||
release(f);
|
release(f);
|
||||||
62
src/core/core/glvertexobject.h
Normal file
62
src/core/core/glvertexobject.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
QGL VertexObject
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLVERTEXOBJECT_H
|
||||||
|
#define GLVERTEXOBJECT_H
|
||||||
|
|
||||||
|
#include "glbuffer.h"
|
||||||
|
#include "glshaders_types.h"
|
||||||
|
|
||||||
|
|
||||||
|
class QGLENGINE_CORE_EXPORT VertexObject {
|
||||||
|
public:
|
||||||
|
VertexObject();
|
||||||
|
~VertexObject();
|
||||||
|
|
||||||
|
void init(QOpenGLExtraFunctions * f);
|
||||||
|
void destroy(QOpenGLExtraFunctions * f);
|
||||||
|
void reinit();
|
||||||
|
|
||||||
|
void bind(QOpenGLExtraFunctions * f);
|
||||||
|
void release(QOpenGLExtraFunctions * f);
|
||||||
|
|
||||||
|
void bindBuffers(QOpenGLExtraFunctions * f, Buffer & geom, Buffer & elem, bool force = false);
|
||||||
|
void loadObject(QOpenGLExtraFunctions * f, const QGLEngineShaders::Object & object);
|
||||||
|
void loadObjects(QOpenGLExtraFunctions * f, const QVector<QGLEngineShaders::Object> & objects);
|
||||||
|
void loadSelections(QOpenGLExtraFunctions * f, const QVector<uchar> & sels);
|
||||||
|
|
||||||
|
void draw(QOpenGLExtraFunctions * f, GLenum geom_type, int vert_cout, int obj_count);
|
||||||
|
|
||||||
|
GLuint ID() const { return vao_; }
|
||||||
|
bool isInit() const { return vao_ != 0; }
|
||||||
|
|
||||||
|
bool isObjectsChanged() const { return objects_changed; }
|
||||||
|
bool isSelectionChanged() const { return selected_changed; }
|
||||||
|
void setObjectsChanged(bool yes = true) { objects_changed = yes; }
|
||||||
|
void setSelectionChanged(bool yes = true) { selected_changed = yes; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void loadBuffer(QOpenGLExtraFunctions * f, Buffer & buf, const void * data, int size);
|
||||||
|
|
||||||
|
GLuint vao_;
|
||||||
|
Buffer buffer_obj, buffer_sel;
|
||||||
|
bool buffers_binded, objects_changed, selected_changed;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // GLVERTEXOBJECT_H
|
||||||
122
src/core/core/hdr.cpp
Normal file
122
src/core/core/hdr.cpp
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
QGL HDR
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hdr_p.h"
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <qmath.h>
|
||||||
|
|
||||||
|
#define RGBE_DATA_RED 2
|
||||||
|
#define RGBE_DATA_GREEN 1
|
||||||
|
#define RGBE_DATA_BLUE 0
|
||||||
|
/* number of floats per pixel */
|
||||||
|
#define RGBE_DATA_SIZE 3
|
||||||
|
|
||||||
|
|
||||||
|
void rgbe2float(float * red, float * green, float * blue, uchar rgbe[4]) {
|
||||||
|
float f;
|
||||||
|
if (rgbe[3]) {
|
||||||
|
f = static_cast<float>(ldexp(1.0, rgbe[3] - (int)(128 + 8)));
|
||||||
|
*red = rgbe[0] * f;
|
||||||
|
*green = rgbe[1] * f;
|
||||||
|
*blue = rgbe[2] * f;
|
||||||
|
} else
|
||||||
|
*red = *green = *blue = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* simple read routine. will not correctly handle run length encoding */
|
||||||
|
bool RGBE_ReadPixels(QDataStream * fp, float * data, int numpixels) {
|
||||||
|
uchar rgbe[4];
|
||||||
|
while (numpixels-- > 0) {
|
||||||
|
if (fp->readRawData((char *)rgbe, sizeof(rgbe)) < 1) return false;
|
||||||
|
rgbe2float(&data[RGBE_DATA_RED], &data[RGBE_DATA_GREEN], &data[RGBE_DATA_BLUE], rgbe);
|
||||||
|
data += RGBE_DATA_SIZE;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool RGBE_ReadPixels_RLE(QDataStream * fp, float * data, int scanline_width, int num_scanlines) {
|
||||||
|
uchar rgbe[4], *ptr, *ptr_end;
|
||||||
|
int i, count;
|
||||||
|
uchar buf[2];
|
||||||
|
QByteArray scanline_buffer;
|
||||||
|
|
||||||
|
if ((scanline_width < 8) || (scanline_width > 0x7fff)) /* run length encoding is not allowed so read flat*/
|
||||||
|
return RGBE_ReadPixels(fp, data, scanline_width * num_scanlines);
|
||||||
|
scanline_buffer.resize(4 * scanline_width);
|
||||||
|
/* read in each successive scanline */
|
||||||
|
while (num_scanlines > 0) {
|
||||||
|
if (fp->readRawData((char *)rgbe, sizeof(rgbe)) < 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((rgbe[0] != 2) || (rgbe[1] != 2) || (rgbe[2] & 0x80)) {
|
||||||
|
/* this file is not run length encoded */
|
||||||
|
rgbe2float(&data[RGBE_DATA_RED], &data[RGBE_DATA_GREEN], &data[RGBE_DATA_BLUE], rgbe);
|
||||||
|
data += RGBE_DATA_SIZE;
|
||||||
|
return RGBE_ReadPixels(fp, data, scanline_width * num_scanlines - 1);
|
||||||
|
}
|
||||||
|
if ((((int)rgbe[2]) << 8 | rgbe[3]) != scanline_width) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ptr = (uchar *)scanline_buffer.data();
|
||||||
|
/* read each of the four channels for the scanline into the buffer */
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
ptr_end = (uchar *)scanline_buffer.data() + ((i + 1) * scanline_width);
|
||||||
|
while (ptr < ptr_end) {
|
||||||
|
if (fp->readRawData((char *)buf, sizeof(buf[0]) * 2) < 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (buf[0] > 128) {
|
||||||
|
/* a run of the same value */
|
||||||
|
count = buf[0] - 128;
|
||||||
|
if ((count == 0) || (count > ptr_end - ptr)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
while (count-- > 0)
|
||||||
|
*ptr++ = buf[1];
|
||||||
|
} else {
|
||||||
|
/* a non-run */
|
||||||
|
count = buf[0];
|
||||||
|
if ((count == 0) || (count > ptr_end - ptr)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*ptr++ = buf[1];
|
||||||
|
if (--count > 0) {
|
||||||
|
if (fp->readRawData((char *)ptr, sizeof(*ptr) * count) < 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ptr += count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* now convert data from buffer into floats */
|
||||||
|
for (i = 0; i < scanline_width; i++) {
|
||||||
|
rgbe[0] = scanline_buffer[i];
|
||||||
|
rgbe[1] = scanline_buffer[i + scanline_width];
|
||||||
|
rgbe[2] = scanline_buffer[i + 2 * scanline_width];
|
||||||
|
rgbe[3] = scanline_buffer[i + 3 * scanline_width];
|
||||||
|
rgbe2float(&data[RGBE_DATA_RED], &data[RGBE_DATA_GREEN], &data[RGBE_DATA_BLUE], rgbe);
|
||||||
|
data += RGBE_DATA_SIZE;
|
||||||
|
}
|
||||||
|
num_scanlines--;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
26
src/core/core/hdr_p.h
Normal file
26
src/core/core/hdr_p.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
QGL HDR
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HDR_P_H
|
||||||
|
#define HDR_P_H
|
||||||
|
|
||||||
|
#include <QDataStream>
|
||||||
|
|
||||||
|
bool RGBE_ReadPixels_RLE(QDataStream * fp, float * data, int scanline_width, int num_scanlines);
|
||||||
|
|
||||||
|
#endif // HDR_P_H
|
||||||
41
src/core/core/measurer.cpp
Normal file
41
src/core/core/measurer.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
Time mesurer
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "measurer.h"
|
||||||
|
|
||||||
|
#include <QOpenGLFunctions>
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
|
||||||
|
Measurer::Measurer(QString * output): out(output) {}
|
||||||
|
|
||||||
|
|
||||||
|
Measurer::~Measurer() {}
|
||||||
|
|
||||||
|
|
||||||
|
void Measurer::begin(const QString & name) {
|
||||||
|
n = name;
|
||||||
|
et.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Measurer::end() {
|
||||||
|
glFinish();
|
||||||
|
auto ms = et.elapsed_m();
|
||||||
|
QTextStream ts(out);
|
||||||
|
ts << n << ": " << QString::number(ms, 'f', 2) << " ms\n";
|
||||||
|
}
|
||||||
44
src/core/core/measurer.h
Normal file
44
src/core/core/measurer.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
Time mesurer
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef measurer_H
|
||||||
|
#define measurer_H
|
||||||
|
|
||||||
|
#include "qglengine_core_export.h"
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <pitime.h>
|
||||||
|
|
||||||
|
|
||||||
|
class QGLENGINE_CORE_EXPORT Measurer {
|
||||||
|
friend class ObjectBase;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Measurer(QString * output);
|
||||||
|
~Measurer();
|
||||||
|
|
||||||
|
void begin(const QString & name);
|
||||||
|
void end();
|
||||||
|
|
||||||
|
private:
|
||||||
|
PITimeMeasurer et;
|
||||||
|
QString n, *out;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
30
src/core/core/parameteredobject.cpp
Normal file
30
src/core/core/parameteredobject.cpp
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
QGL Framebuffer effect basic
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "parameteredobject.h"
|
||||||
|
|
||||||
|
|
||||||
|
PIValueTree ParameteredObject::parameters() const {
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ParameteredObject::setParameters(const PIValueTree & p) {
|
||||||
|
params.applyValues(p);
|
||||||
|
parametersChanged();
|
||||||
|
}
|
||||||
41
src/core/core/parameteredobject.h
Normal file
41
src/core/core/parameteredobject.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
QGL Framebuffer effect basic
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef parameteredobject_H
|
||||||
|
#define parameteredobject_H
|
||||||
|
|
||||||
|
#include "qglengine_core_export.h"
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <pivaluetree.h>
|
||||||
|
|
||||||
|
|
||||||
|
class QGLENGINE_CORE_EXPORT ParameteredObject {
|
||||||
|
public:
|
||||||
|
virtual ~ParameteredObject() {}
|
||||||
|
|
||||||
|
PIValueTree parameters() const;
|
||||||
|
void setParameters(const PIValueTree & p);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void parametersChanged() {}
|
||||||
|
|
||||||
|
PIValueTree params;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,41 +1,52 @@
|
|||||||
/*
|
/*
|
||||||
QGL Loader Assimp
|
QGL Loader Assimp
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU Lesser General Public License for more details.
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "loader_assimp.h"
|
#include "loader_assimp.h"
|
||||||
#include "glscene.h"
|
|
||||||
#include "glmesh.h"
|
|
||||||
#include "glmaterial.h"
|
#include "glmaterial.h"
|
||||||
|
#include "glmesh.h"
|
||||||
#include "globject.h"
|
#include "globject.h"
|
||||||
|
#include "glscene.h"
|
||||||
|
|
||||||
#include <assimp/Importer.hpp>
|
#include <assimp/Importer.hpp>
|
||||||
|
#include <assimp/material.h>
|
||||||
|
#include <assimp/mesh.h>
|
||||||
#include <assimp/postprocess.h>
|
#include <assimp/postprocess.h>
|
||||||
#include <assimp/scene.h>
|
#include <assimp/scene.h>
|
||||||
#include <assimp/mesh.h>
|
|
||||||
#include <assimp/material.h>
|
|
||||||
|
|
||||||
QString fromAiString (const aiString & s) {return QString::fromLocal8Bit(s.C_Str());}
|
QString fromAiString(const aiString & s) {
|
||||||
QColor fromAiColor (const aiColor4D & c) {return QColor::fromRgbF(piClamp(c.r, 0.f, 1.f), piClamp(c.g, 0.f, 1.f), piClamp(c.b, 0.f, 1.f));}
|
return QString::fromLocal8Bit(s.C_Str());
|
||||||
QVector3D fromAiVector3D(const aiVector3D & v) {return QVector3D(v.x, v.y, v.z);}
|
}
|
||||||
Vector3i fromAiFace (const aiFace & v) {return Vector3i(v.mIndices[0], v.mIndices[1], v.mIndices[2]);}
|
QColor fromAiColor(const aiColor4D & c) {
|
||||||
QMatrix4x4 fromAiMatrix4D(const aiMatrix4x4 & v) {return QMatrix4x4(v.a1, v.a2, v.a3, v.a4,
|
return QColor::fromRgbF(piClamp(c.r, 0.f, 1.f), piClamp(c.g, 0.f, 1.f), piClamp(c.b, 0.f, 1.f));
|
||||||
v.b1, v.b2, v.b3, v.b4,
|
}
|
||||||
v.c1, v.c2, v.c3, v.c4,
|
QVector3D fromAiVector3D(const aiVector3D & v) {
|
||||||
v.d1, v.d2, v.d3, v.d4);}
|
return QVector3D(v.x, v.y, v.z);
|
||||||
bool isAiMeshTriangles(const aiMesh * m) {return (m->mPrimitiveTypes & aiPrimitiveType_TRIANGLE) == aiPrimitiveType_TRIANGLE;}
|
}
|
||||||
|
Vector3i fromAiFace(const aiFace & v) {
|
||||||
|
return Vector3i(v.mIndices[0], v.mIndices[1], v.mIndices[2]);
|
||||||
|
}
|
||||||
|
QMatrix4x4 fromAiMatrix4D(const aiMatrix4x4 & v) {
|
||||||
|
return QMatrix4x4(v.a1, v.a2, v.a3, v.a4, v.b1, v.b2, v.b3, v.b4, v.c1, v.c2, v.c3, v.c4, v.d1, v.d2, v.d3, v.d4);
|
||||||
|
}
|
||||||
|
bool isAiMeshTriangles(const aiMesh * m) {
|
||||||
|
return (m->mPrimitiveTypes & aiPrimitiveType_TRIANGLE) == aiPrimitiveType_TRIANGLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Mesh * assimpMesh(const aiMesh * m) {
|
Mesh * assimpMesh(const aiMesh * m) {
|
||||||
@@ -44,9 +55,11 @@ Mesh * assimpMesh(const aiMesh * m) {
|
|||||||
Mesh * ret = new Mesh();
|
Mesh * ret = new Mesh();
|
||||||
int vcnt = m->mNumVertices, tcnt = m->mNumFaces;
|
int vcnt = m->mNumVertices, tcnt = m->mNumFaces;
|
||||||
|
|
||||||
QVector<QVector3D> & v(ret->vertices()); v.resize(vcnt);
|
QVector<QVector3D> & v(ret->vertices());
|
||||||
QVector<QVector2D> & t(ret->texcoords()); t.resize(vcnt);
|
v.resize(vcnt);
|
||||||
QVector< Vector3i> & ind(ret->indicesTriangles());
|
QVector<QVector2D> & t(ret->texcoords());
|
||||||
|
t.resize(vcnt);
|
||||||
|
QVector<Vector3i> & ind(ret->indicesTriangles());
|
||||||
|
|
||||||
for (int i = 0; i < vcnt; ++i)
|
for (int i = 0; i < vcnt; ++i)
|
||||||
v[i] = fromAiVector3D(m->mVertices[i]);
|
v[i] = fromAiVector3D(m->mVertices[i]);
|
||||||
@@ -72,12 +85,12 @@ Mesh * assimpMesh(const aiMesh * m) {
|
|||||||
ind.resize(tcnt);
|
ind.resize(tcnt);
|
||||||
int si = 0;
|
int si = 0;
|
||||||
for (int i = 0; i < tcnt; ++i) {
|
for (int i = 0; i < tcnt; ++i) {
|
||||||
si = i+i+i;
|
si = i + i + i;
|
||||||
ind[i] = Vector3i(si, si+1, si+2);
|
ind[i] = Vector3i(si, si + 1, si + 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//qDebug() << "add mesh" << v.size() << ret->normals().size() << ret->texcoords().size() << ret->indices().size();
|
// qDebug() << "add mesh" << v.size() << ret->normals().size() << ret->texcoords().size() << ret->indices().size();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -86,7 +99,7 @@ Mesh * assimpMesh(const aiMesh * m) {
|
|||||||
QColor aiMatColor(const aiMaterial * m, const char * key, uint s0, uint s1, const QColor & def = Qt::white) {
|
QColor aiMatColor(const aiMaterial * m, const char * key, uint s0, uint s1, const QColor & def = Qt::white) {
|
||||||
aiColor4D col;
|
aiColor4D col;
|
||||||
aiReturn r = m->Get(key, s0, s1, col);
|
aiReturn r = m->Get(key, s0, s1, col);
|
||||||
//qDebug() << key << r << col.r << col.g << col.b;
|
// qDebug() << key << r << col.r << col.g << col.b;
|
||||||
if (r != aiReturn_SUCCESS) return def;
|
if (r != aiReturn_SUCCESS) return def;
|
||||||
return fromAiColor(col);
|
return fromAiColor(col);
|
||||||
}
|
}
|
||||||
@@ -98,36 +111,36 @@ float aiMatFloat(const aiMaterial * m, const char * key, uint s0, uint s1, float
|
|||||||
}
|
}
|
||||||
QString aiMatString(const aiMaterial * m, const char * key, uint s0, uint s1) {
|
QString aiMatString(const aiMaterial * m, const char * key, uint s0, uint s1) {
|
||||||
aiString p;
|
aiString p;
|
||||||
aiReturn r = const_cast<aiMaterial*>(m)->Get(key, s0, s1, p);
|
aiReturn r = const_cast<aiMaterial *>(m)->Get(key, s0, s1, p);
|
||||||
//qDebug() << "GetTexture" << key << s0 << r << fromAiString(p);
|
// qDebug() << "GetTexture" << key << s0 << r << fromAiString(p);
|
||||||
if (r != aiReturn_SUCCESS) return QString();
|
if (r != aiReturn_SUCCESS) return QString();
|
||||||
return fromAiString(p);
|
return fromAiString(p);
|
||||||
}
|
}
|
||||||
Material * assimpMaterial(const aiMaterial * m) {
|
Material * assimpMaterial(const aiMaterial * m) {
|
||||||
if (!m) return 0;
|
if (!m) return 0;
|
||||||
Material * ret = new Material();
|
Material * ret = new Material();
|
||||||
///WARNING: no function GetName() in aiMaterial in stable release
|
/// WARNING: no function GetName() in aiMaterial in stable release
|
||||||
//ret->name = fromAiString(const_cast<aiMaterial*>(m)->GetName());
|
// ret->name = fromAiString(const_cast<aiMaterial*>(m)->GetName());
|
||||||
aiString name;
|
aiString name;
|
||||||
const_cast<aiMaterial*>(m)->Get(AI_MATKEY_NAME,name);
|
const_cast<aiMaterial *>(m)->Get(AI_MATKEY_NAME, name);
|
||||||
ret->name = fromAiString(name);
|
ret->name = fromAiString(name);
|
||||||
//qDebug() << "mat" << ret->name;
|
// qDebug() << "mat" << ret->name;
|
||||||
//for (int i = 0; i < m->mNumProperties; ++i) {
|
// for (int i = 0; i < m->mNumProperties; ++i) {
|
||||||
// qDebug()<< fromAiString(m->mProperties[i]->mKey);// << "=" << aiMatFloat(m, m->mProperties[i]->mKey.C_Str(), 0, 0);
|
// qDebug()<< fromAiString(m->mProperties[i]->mKey);// << "=" << aiMatFloat(m, m->mProperties[i]->mKey.C_Str(), 0, 0);
|
||||||
//}
|
// }
|
||||||
ret->color_diffuse = aiMatColor(m, AI_MATKEY_COLOR_DIFFUSE);
|
ret->color_diffuse = aiMatColor(m, AI_MATKEY_COLOR_DIFFUSE);
|
||||||
ret->color_emission = aiMatColor(m, AI_MATKEY_COLOR_EMISSIVE);
|
ret->color_emission = aiMatColor(m, AI_MATKEY_COLOR_EMISSIVE);
|
||||||
float shine = aiMatFloat(m, AI_MATKEY_SHININESS, -1.f);
|
float shine = aiMatFloat(m, AI_MATKEY_SHININESS, -1.f);
|
||||||
if (shine >= 0) {
|
if (shine >= 0) {
|
||||||
ret->map_roughness.color_amount = 0.8f - (shine / 100.f * 0.6f);
|
ret->map_roughness.color_amount = 0.8f - (shine / 100.f * 0.6f);
|
||||||
//qDebug() << "shine" << shine;
|
// qDebug() << "shine" << shine;
|
||||||
}
|
}
|
||||||
ret->map_diffuse .bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_DIFFUSE(0));
|
ret->map_diffuse.bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_DIFFUSE(0));
|
||||||
ret->map_normal .bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_NORMALS(0));
|
ret->map_normal.bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_NORMALS(0));
|
||||||
//ret->map_metalness.bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_SPECULAR(0));
|
// ret->map_metalness.bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_SPECULAR(0));
|
||||||
ret->map_roughness.bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_SHININESS(0));
|
ret->map_roughness.bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_SHININESS(0));
|
||||||
ret->map_emission .bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_EMISSIVE(0));
|
ret->map_emission.bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_EMISSIVE(0));
|
||||||
ret->transparency = 1.f - aiMatFloat(m, AI_MATKEY_OPACITY, 1.f);
|
ret->transparency = 1.f - aiMatFloat(m, AI_MATKEY_OPACITY, 1.f);
|
||||||
ret->detectMaps();
|
ret->detectMaps();
|
||||||
ret->setTypes();
|
ret->setTypes();
|
||||||
return ret;
|
return ret;
|
||||||
@@ -136,19 +149,17 @@ Material * assimpMaterial(const aiMaterial * m) {
|
|||||||
|
|
||||||
Light * assimpLight(const aiLight * l) {
|
Light * assimpLight(const aiLight * l) {
|
||||||
if (!l) return 0;
|
if (!l) return 0;
|
||||||
if (l->mType != aiLightSource_POINT && l->mType != aiLightSource_SPOT)
|
if (l->mType != aiLightSource_POINT && l->mType != aiLightSource_SPOT) return 0;
|
||||||
return 0;
|
|
||||||
Light * ret = new Light();
|
Light * ret = new Light();
|
||||||
ret->setName(fromAiString(l->mName));
|
ret->setName(fromAiString(l->mName));
|
||||||
ret->setPos(fromAiVector3D(l->mPosition));
|
ret->setPos(fromAiVector3D(l->mPosition));
|
||||||
ret->setDirection(fromAiVector3D(l->mDirection));
|
ret->setDirection(fromAiVector3D(l->mDirection));
|
||||||
ret->decay_const = l->mAttenuationConstant ;
|
ret->decay_const = l->mAttenuationConstant;
|
||||||
ret->decay_linear = l->mAttenuationLinear ;
|
ret->decay_linear = l->mAttenuationLinear;
|
||||||
ret->decay_quadratic = l->mAttenuationQuadratic;
|
ret->decay_quadratic = l->mAttenuationQuadratic;
|
||||||
ret->angle_start = l->mAngleInnerCone * rad2deg;
|
ret->angle_start = l->mAngleInnerCone * rad2deg;
|
||||||
ret->angle_end = l->mAngleOuterCone * rad2deg;
|
ret->angle_end = l->mAngleOuterCone * rad2deg;
|
||||||
if (l->mType == aiLightSource_SPOT)
|
if (l->mType == aiLightSource_SPOT) ret->light_type = Light::Cone;
|
||||||
ret->light_type = Light::Cone;
|
|
||||||
QVector3D col(l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b);
|
QVector3D col(l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b);
|
||||||
ret->intensity = col.length();
|
ret->intensity = col.length();
|
||||||
col /= ret->intensity;
|
col /= ret->intensity;
|
||||||
@@ -157,25 +168,28 @@ Light * assimpLight(const aiLight * l) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ObjectBaseList assimpObject(const aiNode * n, const QVector<Mesh * > & meshes, aiMesh ** ai_meshes,
|
ObjectBaseList assimpObject(const aiNode * n,
|
||||||
const QVector<Material*> & materials,
|
const QVector<Mesh *> & meshes,
|
||||||
const QMap<QString, Light * > & light_by_name, QVector<Light*> & out_lights) {
|
aiMesh ** ai_meshes,
|
||||||
|
const QVector<Material *> & materials,
|
||||||
|
const QMap<QString, Light *> & light_by_name,
|
||||||
|
QVector<Light *> & out_lights) {
|
||||||
if (!n) return ObjectBaseList();
|
if (!n) return ObjectBaseList();
|
||||||
ObjectBaseList ret;
|
ObjectBaseList ret;
|
||||||
ObjectBase * obj = 0;
|
ObjectBase * obj = 0;
|
||||||
QString name = fromAiString(n->mName);
|
QString name = fromAiString(n->mName);
|
||||||
Light * light = light_by_name.value(name, 0);
|
Light * light = light_by_name.value(name, 0);
|
||||||
if (light) {
|
if (light) {
|
||||||
obj = light->clone();
|
obj = light->clone();
|
||||||
out_lights << (Light*)obj;
|
out_lights << (Light *)obj;
|
||||||
} else
|
} else
|
||||||
obj = new ObjectBase();
|
obj = new ObjectBase();
|
||||||
obj->setName(name);
|
obj->setName(name);
|
||||||
obj->setMatrix(fromAiMatrix4D(n->mTransformation));
|
obj->setMatrix(fromAiMatrix4D(n->mTransformation));
|
||||||
ret << obj;
|
ret << obj;
|
||||||
//qDebug() << "add object" << ret << ret->name();
|
// qDebug() << "add object" << ret << ret->name();
|
||||||
if (!light) {
|
if (!light) {
|
||||||
//qDebug() << name << "has" << n->mNumMeshes << "meshes";
|
// qDebug() << name << "has" << n->mNumMeshes << "meshes";
|
||||||
for (uint i = 0; i < n->mNumMeshes; ++i) {
|
for (uint i = 0; i < n->mNumMeshes; ++i) {
|
||||||
int mi = n->mMeshes[i];
|
int mi = n->mMeshes[i];
|
||||||
if (meshes[mi]) {
|
if (meshes[mi]) {
|
||||||
@@ -185,17 +199,16 @@ ObjectBaseList assimpObject(const aiNode * n, const QVector<Mesh * > & meshes, a
|
|||||||
}
|
}
|
||||||
obj->setMesh(meshes[mi]);
|
obj->setMesh(meshes[mi]);
|
||||||
int mati = ai_meshes[mi]->mMaterialIndex;
|
int mati = ai_meshes[mi]->mMaterialIndex;
|
||||||
if (mati >= 0 || mati < materials.size())
|
if (mati >= 0 || mati < materials.size()) obj->setMaterial(materials[mati]);
|
||||||
obj->setMaterial(materials[mati]);
|
// ret->setMesh(meshes[mi]);
|
||||||
//ret->setMesh(meshes[mi]);
|
// qDebug() << "set mesh" << mi << ret->mesh();
|
||||||
//qDebug() << "set mesh" << mi << ret->mesh();
|
// break;
|
||||||
//break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (uint i = 0; i < n->mNumChildren; ++i) {
|
for (uint i = 0; i < n->mNumChildren; ++i) {
|
||||||
ObjectBaseList cl = assimpObject(n->mChildren[i], meshes, ai_meshes, materials, light_by_name, out_lights);
|
ObjectBaseList cl = assimpObject(n->mChildren[i], meshes, ai_meshes, materials, light_by_name, out_lights);
|
||||||
foreach (ObjectBase * c, cl)
|
foreach(ObjectBase * c, cl)
|
||||||
obj->addChild(c);
|
obj->addChild(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,38 +220,36 @@ Scene * loadScene(const QString & filepath) {
|
|||||||
if (filepath.isEmpty()) return 0;
|
if (filepath.isEmpty()) return 0;
|
||||||
qDebug() << "[Loader Assimp] Import" << filepath << "...";
|
qDebug() << "[Loader Assimp] Import" << filepath << "...";
|
||||||
Assimp::Importer importer;
|
Assimp::Importer importer;
|
||||||
const aiScene * ais = importer.ReadFile(filepath.toUtf8(), aiProcess_Triangulate |
|
const aiScene * ais =
|
||||||
aiProcess_SortByPType |
|
importer.ReadFile(filepath.toUtf8(),
|
||||||
aiProcess_GenUVCoords |
|
aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_GenUVCoords | aiProcess_TransformUVCoords);
|
||||||
aiProcess_TransformUVCoords);
|
|
||||||
if (!ais) {
|
if (!ais) {
|
||||||
qDebug() << "[Loader Assimp] Error: \"" + QString(importer.GetErrorString()) + "\"";
|
qDebug() << "[Loader Assimp] Error: \"" + QString(importer.GetErrorString()) + "\"";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
qDebug() << "[Loader Assimp] Imported" << ais->mNumMeshes << "meshes";
|
qDebug() << "[Loader Assimp] Imported" << ais->mNumMeshes << "meshes";
|
||||||
QVector<Mesh * > meshes;
|
QVector<Mesh *> meshes;
|
||||||
for (uint i = 0; i < ais->mNumMeshes; ++i)
|
for (uint i = 0; i < ais->mNumMeshes; ++i)
|
||||||
meshes << assimpMesh(ais->mMeshes[i]);
|
meshes << assimpMesh(ais->mMeshes[i]);
|
||||||
QVector<Material * > materials;
|
QVector<Material *> materials;
|
||||||
for (uint i = 0; i < ais->mNumMaterials; ++i)
|
for (uint i = 0; i < ais->mNumMaterials; ++i)
|
||||||
materials << assimpMaterial(ais->mMaterials[i]);
|
materials << assimpMaterial(ais->mMaterials[i]);
|
||||||
QVector<Light * > lights;
|
QVector<Light *> lights;
|
||||||
for (uint i = 0; i < ais->mNumLights; ++i)
|
for (uint i = 0; i < ais->mNumLights; ++i)
|
||||||
lights << assimpLight(ais->mLights[i]);
|
lights << assimpLight(ais->mLights[i]);
|
||||||
QMap<QString, Light * > light_by_name;
|
QMap<QString, Light *> light_by_name;
|
||||||
foreach (Light * l, lights)
|
foreach(Light * l, lights)
|
||||||
if (l)
|
if (l) light_by_name[l->name()] = l;
|
||||||
light_by_name[l->name()] = l;
|
|
||||||
|
|
||||||
QVector<Light*> out_lights;
|
QVector<Light *> out_lights;
|
||||||
ObjectBaseList rootl = assimpObject(ais->mRootNode, meshes, ais->mMeshes, materials, light_by_name, out_lights);
|
ObjectBaseList rootl = assimpObject(ais->mRootNode, meshes, ais->mMeshes, materials, light_by_name, out_lights);
|
||||||
if (rootl.isEmpty()) return 0;
|
if (rootl.isEmpty()) return 0;
|
||||||
ObjectBase * root = rootl[0];
|
ObjectBase * root = rootl[0];
|
||||||
root->transferTransformToChildren(true);
|
root->transferTransformToChildren(true);
|
||||||
|
|
||||||
ObjectBaseList rcl = root->children(true);
|
ObjectBaseList rcl = root->children(true);
|
||||||
foreach (ObjectBase * c, rcl) {
|
foreach(ObjectBase * c, rcl) {
|
||||||
foreach (Light * l, out_lights) {
|
foreach(Light * l, out_lights) {
|
||||||
if (c->name() == (l->name() + ".Target")) {
|
if (c->name() == (l->name() + ".Target")) {
|
||||||
l->setDistance((l->worldPos() - c->worldPos()).length());
|
l->setDistance((l->worldPos() - c->worldPos()).length());
|
||||||
delete c;
|
delete c;
|
||||||
@@ -250,7 +261,7 @@ Scene * loadScene(const QString & filepath) {
|
|||||||
|
|
||||||
Scene * scene = new Scene();
|
Scene * scene = new Scene();
|
||||||
scene->setName(root->name());
|
scene->setName(root->name());
|
||||||
foreach (ObjectBase * o, root->children())
|
foreach(ObjectBase * o, root->children())
|
||||||
scene->addObject(o);
|
scene->addObject(o);
|
||||||
lights.removeAll(nullptr);
|
lights.removeAll(nullptr);
|
||||||
qDeleteAll(lights);
|
qDeleteAll(lights);
|
||||||
27
src/core/formats/loader_assimp.h
Normal file
27
src/core/formats/loader_assimp.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
QGL Loader Assimp
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LOADER_ASSIMP_H
|
||||||
|
#define LOADER_ASSIMP_H
|
||||||
|
|
||||||
|
#include "gltypes.h"
|
||||||
|
|
||||||
|
QGLENGINE_CORE_EXPORT Scene * loadScene(const QString & filepath);
|
||||||
|
QGLENGINE_CORE_EXPORT QStringList supportedFormats();
|
||||||
|
|
||||||
|
#endif // LOADER_ASSIMP_H
|
||||||
@@ -1,23 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
QGL Loader QGL
|
QGL Loader QGL
|
||||||
Ivan Pelipenko peri4ko@yandex.ru
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU Lesser General Public License for more details.
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "loader_qgl.h"
|
#include "loader_qgl.h"
|
||||||
|
|
||||||
#include "glscene.h"
|
#include "glscene.h"
|
||||||
|
|
||||||
#include <chunkstream.h>
|
#include <chunkstream.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -37,7 +39,7 @@ Scene * loadFromQGLFile(const QString & filepath) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ushort version = 0x1;
|
ushort version = 0x1;
|
||||||
f.peek((char*)&version, 2);
|
f.peek((char *)&version, 2);
|
||||||
if (version != 1) {
|
if (version != 1) {
|
||||||
qDebug() << "[Loader QGL] Error: \"" + filepath + "\" unsupported version!";
|
qDebug() << "[Loader QGL] Error: \"" + filepath + "\" unsupported version!";
|
||||||
return 0;
|
return 0;
|
||||||
@@ -45,7 +47,7 @@ Scene * loadFromQGLFile(const QString & filepath) {
|
|||||||
Scene * ret = 0;
|
Scene * ret = 0;
|
||||||
s.skipRawData(2);
|
s.skipRawData(2);
|
||||||
s >> ret;
|
s >> ret;
|
||||||
//root->buildTransform();
|
// root->buildTransform();
|
||||||
qDebug() << "[Loader QGL] Loaded" << ret->objectsCount(true) << "objects from" << filepath;
|
qDebug() << "[Loader QGL] Loaded" << ret->objectsCount(true) << "objects from" << filepath;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -53,15 +55,14 @@ Scene * loadFromQGLFile(const QString & filepath) {
|
|||||||
|
|
||||||
bool saveToQGLFile(const QString & filepath, const Scene * scene) {
|
bool saveToQGLFile(const QString & filepath, const Scene * scene) {
|
||||||
QFile f(filepath);
|
QFile f(filepath);
|
||||||
if (!f.open(QIODevice::ReadWrite))
|
if (!f.open(QIODevice::ReadWrite)) return false;
|
||||||
return false;
|
|
||||||
f.resize(0);
|
f.resize(0);
|
||||||
QDataStream s(&f);
|
QDataStream s(&f);
|
||||||
s.setVersion(QDataStream::Qt_5_0);
|
s.setVersion(QDataStream::Qt_5_0);
|
||||||
char sign[4] = {'Q', 'G', 'L', 'E'};
|
char sign[4] = {'Q', 'G', 'L', 'E'};
|
||||||
ushort version = 0x1;
|
ushort version = 0x1;
|
||||||
s.writeRawData(sign, 4);
|
s.writeRawData(sign, 4);
|
||||||
s.writeRawData((char*)&version, 2);
|
s.writeRawData((char *)&version, 2);
|
||||||
s << scene;
|
s << scene;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
29
src/core/formats/loader_qgl.h
Normal file
29
src/core/formats/loader_qgl.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
QGL Loader QGL
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LOADER_QGL_H
|
||||||
|
#define LOADER_QGL_H
|
||||||
|
|
||||||
|
#include "gltypes.h"
|
||||||
|
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
QGLENGINE_CORE_EXPORT Scene * loadFromQGLFile(const QString & filepath);
|
||||||
|
QGLENGINE_CORE_EXPORT bool saveToQGLFile(const QString & filepath, const Scene * scene);
|
||||||
|
|
||||||
|
#endif // LOADER_QGL_H
|
||||||
4
src/core/lang/qglengine_core_en.ts
Normal file
4
src/core/lang/qglengine_core_en.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!DOCTYPE TS>
|
||||||
|
<TS version="2.1" language="en_US">
|
||||||
|
</TS>
|
||||||
4
src/core/lang/qglengine_core_ru.ts
Normal file
4
src/core/lang/qglengine_core_ru.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!DOCTYPE TS>
|
||||||
|
<TS version="2.1" language="ru_RU">
|
||||||
|
</TS>
|
||||||
2
src/core/lang/update.bat
Normal file
2
src/core/lang/update.bat
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
lupdate ../ -no-obsolete -ts qglengine_core_ru.ts
|
||||||
|
lupdate ../ -no-obsolete -ts qglengine_core_en.ts
|
||||||
48
src/core/qglengine_core.qrc
Normal file
48
src/core/qglengine_core.qrc
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file>coeffs_brdf.png</file>
|
||||||
|
<file>../icons/add-type-camera.png</file>
|
||||||
|
<file>../icons/add-type-geo.png</file>
|
||||||
|
<file>../icons/add-type-light.png</file>
|
||||||
|
<file>../icons/add-type-empty.png</file>
|
||||||
|
<file>../icons/collapse.png</file>
|
||||||
|
<file>../icons/expand.png</file>
|
||||||
|
<file>../icons/edit-rename.png</file>
|
||||||
|
<file>../icons/alpha.png</file>
|
||||||
|
<file>../icons/application-exit.png</file>
|
||||||
|
<file>../icons/configure.png</file>
|
||||||
|
<file>../icons/dialog-close.png</file>
|
||||||
|
<file>../icons/document-edit.png</file>
|
||||||
|
<file>../icons/document-import.png</file>
|
||||||
|
<file>../icons/document-new.png</file>
|
||||||
|
<file>../icons/document-open.png</file>
|
||||||
|
<file>../icons/document-save.png</file>
|
||||||
|
<file>../icons/document-save-all.png</file>
|
||||||
|
<file>../icons/edit-clear.png</file>
|
||||||
|
<file>../icons/edit-clear-locationbar-rtl.png</file>
|
||||||
|
<file>../icons/edit-copy.png</file>
|
||||||
|
<file>../icons/edit-delete.png</file>
|
||||||
|
<file>../icons/edit-find.png</file>
|
||||||
|
<file>../icons/edit-paste.png</file>
|
||||||
|
<file>../icons/go-jump.png</file>
|
||||||
|
<file>../icons/go-top.png</file>
|
||||||
|
<file>../icons/go-up.png</file>
|
||||||
|
<file>../icons/go-down.png</file>
|
||||||
|
<file>../icons/layer-visible-on.png</file>
|
||||||
|
<file>../icons/layer-visible-off.png</file>
|
||||||
|
<file>../icons/light-+.png</file>
|
||||||
|
<file>../icons/list-add.png</file>
|
||||||
|
<file>../icons/object-flip-horizontal.png</file>
|
||||||
|
<file>../icons/object-flip-vertical.png</file>
|
||||||
|
<file>../icons/picker.png</file>
|
||||||
|
<file>../icons/qglview.png</file>
|
||||||
|
<file>../icons/transform-move.png</file>
|
||||||
|
<file>../icons/transform-rotate.png</file>
|
||||||
|
<file>../icons/transform-scale.png</file>
|
||||||
|
<file>../icons/type-camera.png</file>
|
||||||
|
<file>../icons/type-geo.png</file>
|
||||||
|
<file>../icons/type-light.png</file>
|
||||||
|
<file>../icons/type-empty.png</file>
|
||||||
|
<file>../icons/view-refresh.png</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
||||||
277
src/core/render/gltexture_manager.cpp
Normal file
277
src/core/render/gltexture_manager.cpp
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
/*
|
||||||
|
QGL TextureManager
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gltexture_manager.h"
|
||||||
|
|
||||||
|
#include "gltexturearray.h"
|
||||||
|
#include "gltypes.h"
|
||||||
|
|
||||||
|
QStringList TextureManager::search_pathes(".");
|
||||||
|
|
||||||
|
|
||||||
|
QVector3D colorVector(QRgb c) {
|
||||||
|
return QVector3D(((uchar *)(&c))[0] / 255.f, ((uchar *)(&c))[1] / 255.f, ((uchar *)(&c))[2] / 255.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TextureManager::addSearchPath(const QString & path) {
|
||||||
|
if (!search_pathes.contains(path)) search_pathes << path;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString TextureManager::findFile(const QString & path) {
|
||||||
|
return ::findFile(path, search_pathes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
GLuint TextureManager::loadTexture(const QString & path, bool is_normal, MapBakeOptions opts) {
|
||||||
|
QString p = findFile(path);
|
||||||
|
if (p.isEmpty()) return 0;
|
||||||
|
uint hash = mapHash(p, is_normal, opts);
|
||||||
|
int tid = cache_loaded.value(hash, 0);
|
||||||
|
if (tid > 0) {
|
||||||
|
qDebug() << "[TextureManager] Found" << path << "as" << tid;
|
||||||
|
return tid;
|
||||||
|
}
|
||||||
|
QImage image(p);
|
||||||
|
if (is_normal) convertToNormal(image);
|
||||||
|
applyBakeOption(image, opts);
|
||||||
|
// qDebug() << p << image.width() << image.height() << image.format() << is_normal;
|
||||||
|
GLuint tid_ = tid;
|
||||||
|
createGLTexture(f, tid_, image);
|
||||||
|
tid = tid_;
|
||||||
|
if (tid == 0) {
|
||||||
|
qDebug() << "[TextureManager] Can`t load" << p;
|
||||||
|
return tid;
|
||||||
|
}
|
||||||
|
qDebug() << "[TextureManager] Loaded" << p << "as" << tid;
|
||||||
|
tex_ids[is_normal ? 1 : 0].insert(p, tid);
|
||||||
|
tex_im[is_normal ? 1 : 0].insert(p, image);
|
||||||
|
return tid;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
QImage TextureManager::loadTextureImage(const QString & path, bool is_normal, MapBakeOptions opts, uint * result_hash) {
|
||||||
|
if (result_hash) *result_hash = 0;
|
||||||
|
if (path.isEmpty()) return QImage();
|
||||||
|
QString p = findFile(path);
|
||||||
|
if (p.isEmpty()) {
|
||||||
|
missed << path;
|
||||||
|
// p = findFile(path);
|
||||||
|
// if (p.isEmpty()) return QImage();
|
||||||
|
return QImage();
|
||||||
|
}
|
||||||
|
uint hash = mapHash(p, is_normal, opts);
|
||||||
|
QImage image = cache_image.value(hash);
|
||||||
|
if (!image.isNull()) {
|
||||||
|
if (result_hash) *result_hash = hash;
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
image = QImage(p).convertToFormat(QImage::Format_ARGB32);
|
||||||
|
if (image.isNull()) return image;
|
||||||
|
if (is_normal) convertToNormal(image);
|
||||||
|
applyBakeOption(image, opts);
|
||||||
|
cache_image[hash] = image;
|
||||||
|
if (result_hash) *result_hash = hash;
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
GLuint TextureManager::loadTexture(const QImage & im, bool ownership, bool is_normal, MapBakeOptions opts) {
|
||||||
|
if (im.isNull()) return 0;
|
||||||
|
QImage image(im);
|
||||||
|
if (is_normal) convertToNormal(image);
|
||||||
|
applyBakeOption(image, opts);
|
||||||
|
GLuint tid = 0;
|
||||||
|
createGLTexture(f, tid, im);
|
||||||
|
if (tid == 0) {
|
||||||
|
qDebug() << "[TextureManager] Can`t load image";
|
||||||
|
return tid;
|
||||||
|
}
|
||||||
|
qDebug() << "[TextureManager] Loaded image as" << tid;
|
||||||
|
return tid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TextureManager::reloadTexture(GLuint tid, const QString & path) {
|
||||||
|
QString p = findFile(path);
|
||||||
|
if (p.isEmpty() || (tid == 0)) return;
|
||||||
|
QImage image(p);
|
||||||
|
createGLTexture(f, tid, image);
|
||||||
|
if (tid == 0) {
|
||||||
|
qDebug() << "[TextureManager] Can`t load" << p;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qDebug() << "[TextureManager] Reloaded" << p << "as" << tid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TextureManager::reloadTexture(GLuint tid, const QImage & im) {
|
||||||
|
if (im.isNull() || (tid == 0)) return;
|
||||||
|
QImage image(im);
|
||||||
|
createGLTexture(f, tid, image);
|
||||||
|
qDebug() << "[TextureManager] Reloaded" << tid;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
int TextureManager::textureID(const QString & path, bool is_normal, MapBakeOptions opts) {
|
||||||
|
return cache_loaded.value(mapHash(findFile(path), is_normal, opts), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QImage TextureManager::textureImage(const QString & path, bool is_normal, MapBakeOptions opts) {
|
||||||
|
return cache_image.value(mapHash(findFile(path), is_normal, opts));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TextureManager::convertToNormal(QImage & im) {
|
||||||
|
if (im.isNull()) return;
|
||||||
|
float sum[3] = {0., 0., 0.};
|
||||||
|
llong a = 0;
|
||||||
|
const uchar * sd = im.constBits();
|
||||||
|
for (int i = 0; i < im.height(); i++) {
|
||||||
|
for (int j = 0; j < im.width(); j++) {
|
||||||
|
sum[2] += sd[a] / 255.f - 0.5f;
|
||||||
|
++a;
|
||||||
|
sum[1] += sd[a] / 255.f - 0.5f;
|
||||||
|
++a;
|
||||||
|
sum[0] += sd[a] / 255.f - 0.5f;
|
||||||
|
++a;
|
||||||
|
++a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float wh = im.width() * im.height();
|
||||||
|
sum[0] /= wh;
|
||||||
|
sum[1] /= wh;
|
||||||
|
sum[2] /= wh;
|
||||||
|
// qDebug() << sum[0] << sum[1] << sum[2];
|
||||||
|
if ((qAbs(sum[0]) <= 0.05f) && (qAbs(sum[1]) <= 0.05f) && (sum[2] >= 0.25f)) /// already normal
|
||||||
|
return;
|
||||||
|
// qDebug() << "convert to normal";
|
||||||
|
QImage dim = QImage(im.width(), im.height(), QImage::Format_ARGB32);
|
||||||
|
int tx, ty, w = im.width(), h = im.height();
|
||||||
|
a = 0;
|
||||||
|
uchar * dd = dim.bits();
|
||||||
|
for (int i = 0; i < im.height(); i++) {
|
||||||
|
for (int j = 0; j < im.width(); j++) {
|
||||||
|
tx = j - 1;
|
||||||
|
tx = tx < 0 ? w + tx : tx % w;
|
||||||
|
ty = i - 1;
|
||||||
|
ty = ty < 0 ? h + ty : ty % h;
|
||||||
|
QVector3D p[3], res;
|
||||||
|
p[0] = colorVector(im.pixel(j, i));
|
||||||
|
p[1] = colorVector(im.pixel(j, ty));
|
||||||
|
p[2] = colorVector(im.pixel(tx, i));
|
||||||
|
res.setY(piClamp(0.5f + (p[0].length() - p[1].length()) / 2.f, 0.f, 1.f));
|
||||||
|
res.setX(piClamp(0.5f - (p[0].length() - p[2].length()) / 2.f, 0.f, 1.f));
|
||||||
|
tx = (j + 1) % w;
|
||||||
|
ty = (i + 1) % h;
|
||||||
|
p[1] = colorVector(im.pixel(j, ty));
|
||||||
|
p[2] = colorVector(im.pixel(tx, i));
|
||||||
|
res.setY(piClamp(0.5f + (p[0].length() - p[1].length()) / 2.f, 0.f, 1.f));
|
||||||
|
res.setX(piClamp(0.5f - (p[0].length() - p[2].length()) / 2.f, 0.f, 1.f));
|
||||||
|
res.setZ(1.f);
|
||||||
|
dd[a] = res.z() * 255;
|
||||||
|
++a;
|
||||||
|
dd[a] = res.y() * 255;
|
||||||
|
++a;
|
||||||
|
dd[a] = res.x() * 255;
|
||||||
|
++a;
|
||||||
|
dd[a] = 255;
|
||||||
|
++a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
im = dim;
|
||||||
|
// im.save("_normal.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TextureManager::applyBakeOption(QImage & im, MapBakeOptions opts) {
|
||||||
|
if (im.isNull()) return;
|
||||||
|
if (!opts.invert_R && !opts.invert_G && !opts.invert_B) return;
|
||||||
|
QRgb * data = (QRgb *)im.bits();
|
||||||
|
uint pixels = im.width() * im.height();
|
||||||
|
for (uint i = 0; i < pixels; ++i) {
|
||||||
|
uchar * p = (uchar *)&(data[i]);
|
||||||
|
if (opts.invert_B) p[0] = 255 - p[0];
|
||||||
|
if (opts.invert_G) p[1] = 255 - p[1];
|
||||||
|
if (opts.invert_R) p[2] = 255 - p[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint TextureManager::mapHash(const QString & path, bool is_normal, MapBakeOptions opts) {
|
||||||
|
return qHash(path) ^ ((uint)is_normal << 8) ^ opts.hash();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
bool TextureManager::loadTextures() {
|
||||||
|
QFileInfoList fil;
|
||||||
|
foreach(const QString & i, tex_pathes)
|
||||||
|
loadTexture(i, true);
|
||||||
|
tex_pathes.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TextureManager::deleteTextures() {
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
QList<GLuint> texs = tex_ids[i].values();
|
||||||
|
qDebug() << "[TextureManager] Delete" << texs.size() << "textures";
|
||||||
|
if (!texs.isEmpty()) f->glDeleteTextures(texs.size(), &texs[0]);
|
||||||
|
tex_ids[i].clear();
|
||||||
|
tex_im[i].clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TextureManager::deleteTexture(const QString & name) {
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
if (tex_ids[i].contains(name)) {
|
||||||
|
GLuint id = tex_ids[i][name];
|
||||||
|
f->glDeleteTextures(1, &id);
|
||||||
|
tex_ids[i].remove(name);
|
||||||
|
tex_im[i].remove(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void TextureManager::clearImageCache() {
|
||||||
|
cache_image.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TextureManager::clearMissed() {
|
||||||
|
missed.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TextureManager::loadToTexture2DArray(Texture2DArray * array, QSize map_size) {
|
||||||
|
array->resize(f, map_size, texturesCount());
|
||||||
|
array_layers.clear();
|
||||||
|
QMapIterator<uint, QImage> it(cache_image);
|
||||||
|
int cl = -1;
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
array->load(f, it.value(), ++cl);
|
||||||
|
array_layers[it.key()] = cl;
|
||||||
|
}
|
||||||
|
array->mipmaps(f);
|
||||||
|
emit filesUsed(texturesCount());
|
||||||
|
}
|
||||||
86
src/core/render/gltexture_manager.h
Normal file
86
src/core/render/gltexture_manager.h
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
QGL TextureManager
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLTEXTUREMANAGER_H
|
||||||
|
#define GLTEXTUREMANAGER_H
|
||||||
|
|
||||||
|
#include "glmaterial.h"
|
||||||
|
#include "qglengine_core_export.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QImage>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QOpenGLExtraFunctions>
|
||||||
|
|
||||||
|
|
||||||
|
class QGLENGINE_CORE_EXPORT TextureManager: public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
TextureManager(QOpenGLExtraFunctions * f_): f(f_) {}
|
||||||
|
virtual ~TextureManager() {}
|
||||||
|
|
||||||
|
// GLuint loadTexture(const QString & path, bool is_normal = false, MapBakeOptions opts = {});
|
||||||
|
// GLuint loadTexture(const QImage & image, bool ownership = true, bool is_normal = false, MapBakeOptions opts = {});
|
||||||
|
QImage loadTextureImage(const QString & path, bool is_normal = false, MapBakeOptions opts = {}, uint * result_hash = nullptr);
|
||||||
|
// void reloadTexture(GLuint tid, const QString & path);
|
||||||
|
// void reloadTexture(GLuint tid, const QImage & image);
|
||||||
|
int textureID(const QString & path, bool is_normal = false, MapBakeOptions opts = {});
|
||||||
|
QImage textureImage(const QString & path, bool is_normal = false, MapBakeOptions opts = {});
|
||||||
|
QImage textureImage(uint hash) const { return cache_image.value(hash); }
|
||||||
|
int textureLayer(uint hash) const { return array_layers.value(hash); }
|
||||||
|
// void addTexture(const QString & path) { tex_pathes << path; }
|
||||||
|
// bool loadTextures();
|
||||||
|
// void deleteTextures();
|
||||||
|
// void deleteTexture(const QString & name);
|
||||||
|
int texturesCount() const { return cache_image.size(); }
|
||||||
|
uint texturesHash() const { return qHash(cache_image.keys()); }
|
||||||
|
void clearImageCache();
|
||||||
|
void clearMissed();
|
||||||
|
const QSet<QString> & missedFiles() const { return missed; }
|
||||||
|
|
||||||
|
void loadToTexture2DArray(Texture2DArray * array, QSize map_size);
|
||||||
|
|
||||||
|
static void addSearchPath(const QString & path);
|
||||||
|
static void clearSearchPathes() { search_pathes.clear(); }
|
||||||
|
static QStringList searchPathes() { return search_pathes; }
|
||||||
|
static void setSearchPathes(const QStringList & pl) { search_pathes = pl; }
|
||||||
|
static QString findFile(const QString & path);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void convertToNormal(QImage & im);
|
||||||
|
static void applyBakeOption(QImage & im, MapBakeOptions opts);
|
||||||
|
static uint mapHash(const QString & path, bool is_normal, MapBakeOptions opts);
|
||||||
|
|
||||||
|
static QStringList search_pathes;
|
||||||
|
|
||||||
|
QOpenGLExtraFunctions * f;
|
||||||
|
QMap<uint, GLuint> cache_loaded;
|
||||||
|
QMap<uint, QImage> cache_image;
|
||||||
|
QMap<uint, int> array_layers;
|
||||||
|
QSet<QString> missed;
|
||||||
|
QStringList tex_pathes;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void loadingDone();
|
||||||
|
void filesUsed(int);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // GLTEXTUREMANAGER_H
|
||||||
748
src/core/render/renderer.cpp
Normal file
748
src/core/render/renderer.cpp
Normal file
@@ -0,0 +1,748 @@
|
|||||||
|
/*
|
||||||
|
QGL Renderer
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GL_GLEXT_PROTOTYPES
|
||||||
|
#include "renderer.h"
|
||||||
|
|
||||||
|
#include "ccm_qglengine_core.h"
|
||||||
|
#include "glmesh.h"
|
||||||
|
#include "glshaders.h"
|
||||||
|
#include "gltexture_manager.h"
|
||||||
|
#include "qglview.h"
|
||||||
|
|
||||||
|
#include <QOpenGLExtraFunctions>
|
||||||
|
#include <picodeinfo.h>
|
||||||
|
#include <piiostream.h>
|
||||||
|
#include <piqt.h>
|
||||||
|
#include <qad_types.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace QGLEngineShaders;
|
||||||
|
|
||||||
|
|
||||||
|
Renderer::Renderer(QGLView * view_)
|
||||||
|
: RendererBase(view_)
|
||||||
|
, fbo_ds(view_,
|
||||||
|
QVector<GLenum>() << GL_RGBA16F << GL_RGBA32F << GL_RGBA16F << GL_RGBA16F << GL_RGBA16F << GL_RGBA16F << GL_RGBA32F
|
||||||
|
<< GL_RGBA16F)
|
||||||
|
, fbo_out(view_, obrBuffersCount, false, GL_RGBA16F)
|
||||||
|
, rend_mat(this)
|
||||||
|
, rend_service(this)
|
||||||
|
, rend_selection(this)
|
||||||
|
, tone_proc(this)
|
||||||
|
, tex_env(view_, 512) {
|
||||||
|
mat_norm_to_tex_coord.scale(0.5, 0.5);
|
||||||
|
mat_norm_to_tex_coord.translate(1, 1);
|
||||||
|
mat_proj_90 = glMatrixPerspective(90., 1., 0.1);
|
||||||
|
for (int i = 0; i < 6; ++i) {
|
||||||
|
QMatrix4x4 fvm;
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
fvm.rotate(-90., QVector3D(0, 1, 0));
|
||||||
|
fvm.rotate(180., QVector3D(0, 0, 1));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
fvm.rotate(90., QVector3D(0, 1, 0));
|
||||||
|
fvm.rotate(180., QVector3D(0, 0, 1));
|
||||||
|
break;
|
||||||
|
case 2: fvm.rotate(-90., QVector3D(1, 0, 0)); break;
|
||||||
|
case 3: fvm.rotate(90., QVector3D(1, 0, 0)); break;
|
||||||
|
case 4:
|
||||||
|
fvm.rotate(180., QVector3D(0, 0, 1));
|
||||||
|
fvm.rotate(180., QVector3D(0, 1, 0));
|
||||||
|
break;
|
||||||
|
case 5: fvm.rotate(180., QVector3D(0, 0, 1)); break;
|
||||||
|
}
|
||||||
|
mat_faces[i] = fvm;
|
||||||
|
}
|
||||||
|
|
||||||
|
quad = Primitive::plane(2., 2.);
|
||||||
|
cam_light = new Light();
|
||||||
|
cam_light->intensity = 0.75;
|
||||||
|
cam_light->setName("Camera_Light");
|
||||||
|
cam_light->setCastShadows(false);
|
||||||
|
|
||||||
|
shader_files[srSelectionFill] = "selection.glsl";
|
||||||
|
shader_files[srSelectionHalo] = "selection_halo.glsl";
|
||||||
|
shader_files[srSelectionApply] = "selection_apply.glsl";
|
||||||
|
shader_files[srSelectionFrame] = "selection_frame.glsl";
|
||||||
|
|
||||||
|
shader_files[srServiceFill] = "service_fill.glsl";
|
||||||
|
shader_files[srServiceFrame] = "service_frame.glsl";
|
||||||
|
shader_files[srServiceLine] = "service_line.glsl";
|
||||||
|
|
||||||
|
shader_files[srGeometrySolidPass] = "ds_geom.glsl";
|
||||||
|
shader_files[srGeometryTransparentPass] = "ds_geom.glsl";
|
||||||
|
shader_files[srLightOmniPass] = "ds_light.glsl";
|
||||||
|
shader_files[srLightSpotPass] = "ds_light.glsl";
|
||||||
|
shader_files[srFinalPass] = "ds_final.glsl";
|
||||||
|
shader_files[srTonemapPass] = "ds_tonemap.glsl";
|
||||||
|
|
||||||
|
shader_files[srShadowConePass] = "shadow.glsl";
|
||||||
|
shader_files[srShadowOmniPass] = "shadow.glsl";
|
||||||
|
|
||||||
|
shader_defines[srGeometrySolidPass] << "SOLID";
|
||||||
|
shader_defines[srLightSpotPass] << "SPOT";
|
||||||
|
shader_defines[srShadowOmniPass] << "OMNI";
|
||||||
|
shader_defines[srLightSpotPass] << "SHADOWS";
|
||||||
|
shader_defines[srLightOmniPass] << "SHADOWS";
|
||||||
|
|
||||||
|
PICodeInfo::EnumInfo * obre = PICodeInfo::enumsInfo->value("Renderer::DeferredBufferRole");
|
||||||
|
if (obre) {
|
||||||
|
for (auto e: obre->members) {
|
||||||
|
obr_defines += "#define " + PI2QString(e.name) + " " + QString::number(e.value) + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
edit_mode = need_init_shaders = true;
|
||||||
|
camera_light_mode = QGLView::clmAuto;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Renderer::~Renderer() {
|
||||||
|
delete quad;
|
||||||
|
delete cam_light;
|
||||||
|
qDeleteAll(shaders.values());
|
||||||
|
if (shader_fxaa) delete shader_fxaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer::init(int width, int height) {
|
||||||
|
fbo_ds.reinit();
|
||||||
|
fbo_out.reinit();
|
||||||
|
quad->reinit();
|
||||||
|
buffer_materials.reinit();
|
||||||
|
buffer_lights.reinit();
|
||||||
|
buffer_lights_pos.reinit();
|
||||||
|
textures_maps.reinit();
|
||||||
|
textures_empty.reinit();
|
||||||
|
shadow_maps_cone.reinit();
|
||||||
|
shadow_maps_omni.reinit();
|
||||||
|
depth_maps_cone.reinit();
|
||||||
|
depth_maps_omni.reinit();
|
||||||
|
resize(width, height);
|
||||||
|
rend_mat.init(width, height);
|
||||||
|
rend_service.init(width, height);
|
||||||
|
rend_selection.init(width, height);
|
||||||
|
tone_proc.init();
|
||||||
|
initQuad(quad);
|
||||||
|
initTextureArrays();
|
||||||
|
initCoeffTextures();
|
||||||
|
markReloadTextures();
|
||||||
|
tex_env.init();
|
||||||
|
if (is_grabbing) fbo_out.enablePixelBuffer();
|
||||||
|
need_init_shaders = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer::resize(int width, int height) {
|
||||||
|
rend_mat.resize(width, height);
|
||||||
|
rend_service.resize(width, height);
|
||||||
|
rend_selection.resize(width, height);
|
||||||
|
fbo_ds.resize(width, height);
|
||||||
|
fbo_out.resize(width, height);
|
||||||
|
tone_proc.resize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer::reloadShaders() {
|
||||||
|
__reinit_debug = true;
|
||||||
|
QMapIterator<ShaderRole, QString> it(shader_files);
|
||||||
|
qDeleteAll(shaders.values());
|
||||||
|
shaders.clear();
|
||||||
|
if (shader_fxaa) delete shader_fxaa;
|
||||||
|
shader_fxaa = nullptr;
|
||||||
|
if (tone_proc.shader_sum) delete tone_proc.shader_sum;
|
||||||
|
tone_proc.shader_sum = nullptr;
|
||||||
|
QString dir = ":/shaders/";
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
loadShadersMulti(shaders[it.key()], dir + it.value(), true, shader_defines.value(it.key()), obr_defines);
|
||||||
|
}
|
||||||
|
loadShadersMulti(tone_proc.shader_sum, dir + "sum.glsl", false);
|
||||||
|
QStringList fxaa_defs;
|
||||||
|
fxaa_defs << "FXAA_PC 1"
|
||||||
|
<< "FXAA_GLSL_130 1"
|
||||||
|
<< "FXAA_QUALITY__PRESET 15";
|
||||||
|
loadShaders(shader_fxaa, QStringList() << (dir + "fxaa.vert") << (dir + "fxaa.frag"), true, fxaa_defs);
|
||||||
|
for (auto * e: fb_effects) {
|
||||||
|
e->reloadShaders();
|
||||||
|
e->is_loaded = true;
|
||||||
|
}
|
||||||
|
need_init_shaders = true;
|
||||||
|
view->scene()->setLightsChanged();
|
||||||
|
view->scene()->setTreeStructChanged();
|
||||||
|
view->scene()->setMaterialsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Renderer::bindShader(Renderer::ShaderRole role, QOpenGLShaderProgram ** ret) {
|
||||||
|
QOpenGLShaderProgram * prog = shaders.value(role);
|
||||||
|
if (ret) *ret = prog;
|
||||||
|
if (!prog) return false;
|
||||||
|
if (!prog->isLinked()) return false;
|
||||||
|
prog->bind();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Renderer::bindShader(QOpenGLShaderProgram * sp) {
|
||||||
|
if (!sp) return true;
|
||||||
|
if (!sp->isLinked()) return true;
|
||||||
|
if (!sp->bind()) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer::initShaders() {
|
||||||
|
if (!need_init_shaders) return;
|
||||||
|
need_init_shaders = false;
|
||||||
|
QOpenGLShaderProgram * prog = 0;
|
||||||
|
for (ShaderRole role: {srLightOmniPass, srLightSpotPass}) {
|
||||||
|
if (!bindShader(role, &prog)) continue;
|
||||||
|
initUniformBuffer(prog, &buffer_materials, bpMaterials, "QGLMaterialData");
|
||||||
|
initUniformBuffer(prog, &buffer_lights, bpLightParameters, "QGLLightParameterData");
|
||||||
|
initUniformBuffer(prog, &buffer_lights_pos, bpLightPositions, "QGLLightPositionData");
|
||||||
|
for (int i = 0; i <= 5; ++i)
|
||||||
|
prog->setUniformValue(QString("tex_%1").arg(i).toLatin1().constData(), i);
|
||||||
|
prog->setUniformValue("tex_coeff_brdf", trCoeffBRDF);
|
||||||
|
prog->setUniformValue("tex_env", trEnvironment);
|
||||||
|
setUniformMaps(prog);
|
||||||
|
}
|
||||||
|
if (bindShader(srFinalPass, &prog)) {
|
||||||
|
prog->setUniformValue("tex_g1", 0);
|
||||||
|
prog->setUniformValue("tex_s_0", 1);
|
||||||
|
prog->setUniformValue("tex_s_1", 2);
|
||||||
|
prog->setUniformValue("tex_t_0", 3);
|
||||||
|
prog->setUniformValue("tex_t_1", 4);
|
||||||
|
}
|
||||||
|
for (ShaderRole role: {srGeometrySolidPass, srGeometryTransparentPass, srShadowConePass, srShadowOmniPass}) {
|
||||||
|
if (!bindShader(role, &prog)) continue;
|
||||||
|
initUniformBuffer(prog, &buffer_materials, bpMaterials, "QGLMaterialData");
|
||||||
|
setUniformMaps(prog);
|
||||||
|
}
|
||||||
|
if (bindShader(srTonemapPass, &prog)) {
|
||||||
|
prog->setUniformValue("tex_0", 0);
|
||||||
|
prog->setUniformValue("tex_sum", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer::releaseShader() {
|
||||||
|
view->glUseProgram(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QVector<int> Renderer::getFreePlanes(int count) {
|
||||||
|
prev_write_plane = cur_write_plane;
|
||||||
|
QVector<int> ret;
|
||||||
|
bool output_done = false;
|
||||||
|
const int total_count = 4;
|
||||||
|
for (int i = 0; i < total_count; ++i) {
|
||||||
|
int plane = obrGeneral0 + i;
|
||||||
|
if (prev_write_plane == plane) continue;
|
||||||
|
if (!output_done) {
|
||||||
|
fbo_out.setWriteBuffer(plane);
|
||||||
|
cur_write_plane = plane;
|
||||||
|
output_done = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ret << plane;
|
||||||
|
if (ret.size() == count) break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer::fillObjectsBuffer(const ObjectBaseList & ol, RenderPass pass) {
|
||||||
|
cur_objects_.resize(ol.size());
|
||||||
|
for (int i = 0; i < ol.size(); ++i) {
|
||||||
|
Object & so(cur_objects_[i]);
|
||||||
|
ObjectBase * o = ol[i];
|
||||||
|
if (o->material()) {
|
||||||
|
so.material = o->material()->_index;
|
||||||
|
so.color = QVector4D(1, 1, 1, 1);
|
||||||
|
} else {
|
||||||
|
so.material = 0;
|
||||||
|
so.color = QColor2QVector(o->color());
|
||||||
|
}
|
||||||
|
so.object_id = o->id();
|
||||||
|
so.flags = 0;
|
||||||
|
so.f_accept_light = o->isAcceptLight();
|
||||||
|
so.f_accept_fog = o->isAcceptFog();
|
||||||
|
so.f_accept_cast_shadow = o->isCastShadows();
|
||||||
|
so.f_accept_rec_shadow = o->isReceiveShadows();
|
||||||
|
o->worldTransform().transposed().copyDataTo(so.modelmatrix);
|
||||||
|
o->textureGLMatrix().copyDataTo(so.texturematrix);
|
||||||
|
// qDebug() << "load obj" << o->name() << o->textureMatrix() << tmat;
|
||||||
|
}
|
||||||
|
// qDebug() << "fillObjectsBuffer" << ol.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer::renderObjects(Scene & scene, RenderPass pass) {
|
||||||
|
QOpenGLExtraFunctions * f = view;
|
||||||
|
QMapIterator<Mesh *, ObjectBaseList> it(scene.geometries_used[pass]);
|
||||||
|
bool emit_pos_change = false;
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
Mesh * mesh = it.key();
|
||||||
|
if (mesh->isObjectsChanged(pass)) {
|
||||||
|
mesh->setObjectsChanged(pass, false);
|
||||||
|
emit_pos_change = true;
|
||||||
|
fillObjectsBuffer(it.value(), pass);
|
||||||
|
// qDebug() << "loadObjects" << pass << cur_objects_.size();
|
||||||
|
mesh->loadObjects(f, cur_objects_, pass);
|
||||||
|
}
|
||||||
|
if (mesh->isSelectionChanged(pass) && edit_mode) {
|
||||||
|
mesh->setSelectionChanged(pass, false);
|
||||||
|
fillSelectionsBuffer(rend_selection.cur_selections_, it.value());
|
||||||
|
// qDebug() << "fillSelectionsBuffer" << pass << rend_selection.cur_selections_.size();
|
||||||
|
mesh->loadSelections(f, rend_selection.cur_selections_, pass);
|
||||||
|
}
|
||||||
|
// qDebug() << "draw" << pass << it.value().size();
|
||||||
|
mesh->draw(f, it.value().size(), pass);
|
||||||
|
}
|
||||||
|
if (emit_pos_change) emit view->objectsPositionChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer::renderLight(int first_wr_buff, bool clear_only) {
|
||||||
|
QOpenGLShaderProgram * prog = 0;
|
||||||
|
Camera * cam = view->camera();
|
||||||
|
view->glActiveTexture(GL_TEXTURE0 + trCoeffBRDF);
|
||||||
|
view->glBindTexture(GL_TEXTURE_2D, tex_coeff[0]);
|
||||||
|
// tex_env.bind((int)Renderer::dbrBuffersCount + 1);
|
||||||
|
typedef QPair<Renderer::ShaderRole, Light::Type> PassPair;
|
||||||
|
QVector<PassPair> passes;
|
||||||
|
passes << PassPair(srLightOmniPass, Light::Omni) << PassPair(srLightSpotPass, Light::Cone);
|
||||||
|
QColor back = view->fogColor();
|
||||||
|
back.setAlpha(0);
|
||||||
|
foreach(PassPair pass, passes) {
|
||||||
|
if (bindShader(pass.first, &prog)) {
|
||||||
|
/*if (pass.second == Light::Cone) {
|
||||||
|
auto & cone_ll(cur_lights[pass.second]);
|
||||||
|
for (int i = 0; i < cone_ll.size(); ++i) {
|
||||||
|
Light * l = cone_ll[i];
|
||||||
|
// l->shadow_map.bindDepthTexture(mtShadowCone + i);
|
||||||
|
l->shadow_map.bindColorTexture(0, mtShadowCone + i);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
fbo_out.setWriteBuffer(first_wr_buff + pass.second);
|
||||||
|
glClearFramebuffer(back, false);
|
||||||
|
if (clear_only) continue;
|
||||||
|
setUniformCamera(prog, cam);
|
||||||
|
setUniformViewCorners(prog, cam);
|
||||||
|
prog->setUniformValue("lights_start", lights_start[pass.second]);
|
||||||
|
prog->setUniformValue("lights_count", (int)cur_lights[pass.second].size());
|
||||||
|
prog->setUniformValue("fog_color", view->fogColor());
|
||||||
|
prog->setUniformValue("fog_decay", qMax(view->fogDecay(), 0.001f));
|
||||||
|
prog->setUniformValue("fog_density", view->fogDensity());
|
||||||
|
prog->setUniformValue("view_mat", cam->viewMatrix().inverted().toGenericMatrix<3, 3>());
|
||||||
|
if (shadows_enabled) {
|
||||||
|
prog->setUniformValue("shadow_size", view->shadow_map_size);
|
||||||
|
prog->setUniformValue("noise_size", noise_size);
|
||||||
|
prog->setUniformValue("soft_shadows_enabled", view->soft_shadows);
|
||||||
|
prog->setUniformValue("soft_shadows_samples", view->soft_shadows_samples);
|
||||||
|
prog->setUniformValue("soft_shadows_quality", view->soft_shadows_quality);
|
||||||
|
prog->setUniformValue("tex_shadows_cone", (int)tarShadowsCone);
|
||||||
|
prog->setUniformValue("tex_shadows_omni", (int)tarShadowsOmni);
|
||||||
|
prog->setUniformValue("tex_depths_cone", (int)tarDepthsCone);
|
||||||
|
prog->setUniformValue("tex_depths_omni", (int)tarDepthsOmni);
|
||||||
|
GLenum filter = view->softShadows() ? GL_NEAREST : GL_LINEAR;
|
||||||
|
shadow_maps_cone.bind(view, tarShadowsCone);
|
||||||
|
view->glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, filter);
|
||||||
|
view->glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, filter);
|
||||||
|
shadow_maps_omni.bind(view, tarShadowsOmni);
|
||||||
|
view->glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, filter);
|
||||||
|
view->glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, filter);
|
||||||
|
depth_maps_cone.bind(view, tarDepthsCone);
|
||||||
|
depth_maps_omni.bind(view, tarDepthsOmni);
|
||||||
|
}
|
||||||
|
renderQuad(prog, quad, cam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer::renderConeShadows() {
|
||||||
|
QOpenGLExtraFunctions * f = view;
|
||||||
|
QOpenGLShaderProgram * prog = 0;
|
||||||
|
if (bindShader(srShadowConePass, &prog)) {
|
||||||
|
glEnableDepth();
|
||||||
|
textures_empty.bind(f, tarEmpty);
|
||||||
|
textures_maps.bind(f, tarMaps);
|
||||||
|
auto cone_ll = cur_lights.value(Light::Cone);
|
||||||
|
if (shadow_maps_cone.resize(f, view->shadow_map_size, cone_ll.size())) {
|
||||||
|
f->glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
f->glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
f->glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||||
|
f->glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
|
||||||
|
}
|
||||||
|
depth_maps_cone.resize(f, view->shadow_map_size, cone_ll.size());
|
||||||
|
for (int i = 0; i < cone_ll.size(); ++i) {
|
||||||
|
Light * l = cone_ll[i];
|
||||||
|
QMatrix4x4 pm = glMatrixPerspective(l->angle_end, 1., 0.1), om, vm;
|
||||||
|
om.translate(-l->worldAim());
|
||||||
|
vm.translate(0., 0., -l->distance());
|
||||||
|
// vm.rotate(-roll_, 0., 0., 1.);
|
||||||
|
QMatrix4x4 pmat = l->worldTransform();
|
||||||
|
pmat(0, 3) = pmat(1, 3) = pmat(2, 3) = 0.;
|
||||||
|
vm *= pmat.inverted();
|
||||||
|
auto vpm = pm * (vm * om);
|
||||||
|
if (l->isCastShadows()) {
|
||||||
|
prog->setUniformValue("qgl_ViewProjMatrix", vpm);
|
||||||
|
renderConeShadow(i, l);
|
||||||
|
}
|
||||||
|
l->shadow_matrix = mat_norm_to_tex_coord * vpm * mat_camera_fullview_inv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer::renderOmniShadows() {
|
||||||
|
QOpenGLExtraFunctions * f = view;
|
||||||
|
QOpenGLShaderProgram * prog = 0;
|
||||||
|
if (bindShader(srShadowOmniPass, &prog)) {
|
||||||
|
glEnableDepth();
|
||||||
|
textures_empty.bind(f, tarEmpty);
|
||||||
|
textures_maps.bind(f, tarMaps);
|
||||||
|
auto omni_ll = cur_lights.value(Light::Omni);
|
||||||
|
if (shadow_maps_omni.resize(f, view->shadow_map_size, omni_ll.size())) {
|
||||||
|
f->glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||||
|
f->glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
|
||||||
|
}
|
||||||
|
depth_maps_omni.resize(f, view->shadow_map_size, omni_ll.size());
|
||||||
|
for (int i = 0; i < omni_ll.size(); ++i) {
|
||||||
|
Light * l = omni_ll[i];
|
||||||
|
QMatrix4x4 om;
|
||||||
|
om.translate(-l->worldPos());
|
||||||
|
// vm.translate(0., 0., -l->distance());
|
||||||
|
// vm.rotate(-roll_, 0., 0., 1.);
|
||||||
|
if (l->isCastShadows()) {
|
||||||
|
renderOmniShadow(i, l, prog, om);
|
||||||
|
}
|
||||||
|
// l->shadow_matrix = mat_norm_to_tex_coord * vpm * mat_camera_fullview_inv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer::renderConeShadow(int index, Light * light) {
|
||||||
|
Scene & scene(*(view->scene()));
|
||||||
|
bool force_resize = false;
|
||||||
|
if (!light->shadow_map.isInit()) {
|
||||||
|
light->shadow_map.reinit(view);
|
||||||
|
force_resize = true;
|
||||||
|
}
|
||||||
|
light->shadow_map.resize(view->shadow_map_size, force_resize);
|
||||||
|
light->shadow_map.bind();
|
||||||
|
|
||||||
|
view->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadow_maps_cone.ID(), 0, index);
|
||||||
|
view->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, depth_maps_cone.ID(), 0, index);
|
||||||
|
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||||
|
glClearFramebuffer();
|
||||||
|
renderObjects(scene, rpSolid);
|
||||||
|
light->shadow_map.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer::renderOmniShadow(int index, Light * light, QOpenGLShaderProgram * prog, QMatrix4x4 om) {
|
||||||
|
Scene & scene(*(view->scene()));
|
||||||
|
bool force_resize = false;
|
||||||
|
if (!light->shadow_map.isInit()) {
|
||||||
|
light->shadow_map.reinit(view);
|
||||||
|
force_resize = true;
|
||||||
|
}
|
||||||
|
light->shadow_map.resize(view->shadow_map_size, force_resize);
|
||||||
|
light->shadow_map.bind();
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; ++i) {
|
||||||
|
QMatrix4x4 vm = mat_proj_90 * mat_faces[i] * om;
|
||||||
|
prog->setUniformValue("qgl_ViewProjMatrix", vm);
|
||||||
|
view->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadow_maps_omni.ID(), 0, index * 6 + i);
|
||||||
|
view->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, depth_maps_omni.ID(), 0, index * 6 + i);
|
||||||
|
// static GLenum faces[6] = {GL_COLOR_ATTACHMENT0,
|
||||||
|
// GL_COLOR_ATTACHMENT1,
|
||||||
|
// GL_COLOR_ATTACHMENT2,
|
||||||
|
// GL_COLOR_ATTACHMENT3,
|
||||||
|
// GL_COLOR_ATTACHMENT4,
|
||||||
|
// GL_COLOR_ATTACHMENT5};
|
||||||
|
// view->glDrawBuffers(6, faces);
|
||||||
|
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||||
|
glClearFramebuffer();
|
||||||
|
renderObjects(scene, rpSolid);
|
||||||
|
}
|
||||||
|
light->shadow_map.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer::renderScene() {
|
||||||
|
timings.clear();
|
||||||
|
Measurer phase(&timings);
|
||||||
|
|
||||||
|
phase.begin("init");
|
||||||
|
initShaders();
|
||||||
|
tex_env.load();
|
||||||
|
QOpenGLExtraFunctions * f = view;
|
||||||
|
Scene & scene(*(view->scene()));
|
||||||
|
Camera * cam = view->camera();
|
||||||
|
QOpenGLShaderProgram * prog = 0;
|
||||||
|
bool scene_changed = scene.prepare();
|
||||||
|
cur_lights = scene.lights_used;
|
||||||
|
mat_camera_fullview_inv = cam->fullViewMatrix().inverted();
|
||||||
|
scene.destroyUnused(f);
|
||||||
|
phase.end();
|
||||||
|
|
||||||
|
/// reload materials on change
|
||||||
|
phase.begin("scene reload");
|
||||||
|
if (scene_changed || scene.need_reload_materials) {
|
||||||
|
rend_selection.generateObjectsID(scene);
|
||||||
|
reloadMaterials(scene);
|
||||||
|
if (edit_mode) recreateMaterialThumbnails();
|
||||||
|
emit view->materialsChanged();
|
||||||
|
}
|
||||||
|
phase.end();
|
||||||
|
|
||||||
|
/// material thumbnails
|
||||||
|
phase.begin("materials");
|
||||||
|
if (edit_mode && !scene_changed) {
|
||||||
|
rend_mat.procQueue();
|
||||||
|
}
|
||||||
|
phase.end();
|
||||||
|
|
||||||
|
if (shadows_enabled) {
|
||||||
|
/// cone shadows and shadow matrix
|
||||||
|
phase.begin("shadows cone");
|
||||||
|
renderConeShadows();
|
||||||
|
phase.end();
|
||||||
|
|
||||||
|
/// omni shadows and shadow matrix
|
||||||
|
phase.begin("shadows omni");
|
||||||
|
renderOmniShadows();
|
||||||
|
phase.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// lights
|
||||||
|
phase.begin("lights prepare");
|
||||||
|
bool use_camlight = (camera_light_mode == QGLView::clmOn);
|
||||||
|
if ((camera_light_mode == QGLView::clmAuto) && cur_lights.isEmpty()) {
|
||||||
|
use_camlight = true;
|
||||||
|
}
|
||||||
|
if (use_camlight) {
|
||||||
|
cur_lights[Light::Omni] << cam_light;
|
||||||
|
cam_light->setPos(cam->pos());
|
||||||
|
}
|
||||||
|
if (scene.lights_changed) {
|
||||||
|
scene.lights_changed = false;
|
||||||
|
reloadLightsParameters(cur_lights);
|
||||||
|
}
|
||||||
|
reloadLightsPositions(cam);
|
||||||
|
phase.end();
|
||||||
|
|
||||||
|
/// selection
|
||||||
|
phase.begin("selection");
|
||||||
|
if (edit_mode) {
|
||||||
|
rend_selection.renderSelection(scene);
|
||||||
|
}
|
||||||
|
phase.end();
|
||||||
|
|
||||||
|
|
||||||
|
/// solid geometry pass
|
||||||
|
phase.begin("geometry solid");
|
||||||
|
fbo_ds.bind();
|
||||||
|
glEnableDepth();
|
||||||
|
glClearFramebuffer();
|
||||||
|
if (bindShader(srGeometrySolidPass, &prog)) {
|
||||||
|
setUniformCamera(prog, cam);
|
||||||
|
textures_empty.bind(f, tarEmpty);
|
||||||
|
textures_maps.bind(f, tarMaps);
|
||||||
|
prog->setUniformValue("out_index_normal", dbrNormalZSolid);
|
||||||
|
prog->setUniformValue("out_index_metal", dbrMetalRoughReflectFlagsSolid);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, view->renderMode());
|
||||||
|
renderObjects(scene, rpSolid);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
}
|
||||||
|
// fbo_ds.blit(dbrNormalZ, fbo_ds.id(), dbrNormalZSolid, fbo_ds.rect(), fbo_ds.rect());
|
||||||
|
// fbo_ds.blit(dbrMetalRoughReflectFlags, fbo_ds.id(), dbrMetalRoughReflectFlagsSolid, fbo_ds.rect(), fbo_ds.rect());
|
||||||
|
fbo_ds.release();
|
||||||
|
phase.end();
|
||||||
|
|
||||||
|
/// lighting passes
|
||||||
|
phase.begin("... light");
|
||||||
|
fbo_out.bind();
|
||||||
|
fbo_ds.bindColorTextures({dbrDiffuse, dbrNormalZSolid, dbrMetalRoughReflectFlagsSolid, dbrEmission, dbrSpeedBitangXY, dbrGeoNormal});
|
||||||
|
renderLight(obrSolidOmni, scene.geometries_used[rpSolid].isEmpty());
|
||||||
|
phase.end();
|
||||||
|
|
||||||
|
/// transparent geometry pass
|
||||||
|
phase.begin("geometry trans");
|
||||||
|
fbo_ds.bind();
|
||||||
|
glEnableDepth();
|
||||||
|
fbo_ds.setWriteBuffers({0, 1, 2, 3, 4});
|
||||||
|
glClearFramebuffer(Qt::black, false);
|
||||||
|
fbo_ds.setWriteBuffers();
|
||||||
|
if (bindShader(srGeometryTransparentPass, &prog)) {
|
||||||
|
setUniformCamera(prog, cam);
|
||||||
|
textures_empty.bind(f, tarEmpty);
|
||||||
|
textures_maps.bind(f, tarMaps);
|
||||||
|
prog->setUniformValue("out_index_normal", dbrNormalZ);
|
||||||
|
prog->setUniformValue("out_index_metal", dbrMetalRoughReflectFlags);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, view->renderMode());
|
||||||
|
renderObjects(scene, rpTransparent);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
}
|
||||||
|
fbo_ds.release();
|
||||||
|
phase.end();
|
||||||
|
|
||||||
|
/// lighting passes
|
||||||
|
phase.begin("... light");
|
||||||
|
fbo_out.bind();
|
||||||
|
fbo_ds.bindColorTextures({dbrDiffuse, dbrNormalZ, dbrMetalRoughReflectFlags, dbrEmission, dbrSpeedBitangXY, dbrGeoNormal});
|
||||||
|
renderLight(obrTransparentOmni, scene.geometries_used[rpTransparent].isEmpty());
|
||||||
|
phase.end();
|
||||||
|
|
||||||
|
/// blending layers
|
||||||
|
phase.begin("blending");
|
||||||
|
if (bindShader(srFinalPass, &prog)) {
|
||||||
|
fbo_out.bindColorTexture(obrSolidOmni, 1);
|
||||||
|
fbo_out.bindColorTexture(obrSolidSpot, 2);
|
||||||
|
fbo_out.bindColorTexture(obrTransparentOmni, 3);
|
||||||
|
fbo_out.bindColorTexture(obrTransparentSpot, 4);
|
||||||
|
fbo_out.setWriteBuffer(obrLighting);
|
||||||
|
renderQuad(prog, quad);
|
||||||
|
}
|
||||||
|
phase.end();
|
||||||
|
|
||||||
|
fbo_out.bind();
|
||||||
|
cur_write_plane = obrLighting;
|
||||||
|
|
||||||
|
/// tonemapping
|
||||||
|
phase.begin("tonemap");
|
||||||
|
tone_proc.process();
|
||||||
|
auto free = getFreePlanes(0);
|
||||||
|
if (bindShader(srTonemapPass, &prog)) {
|
||||||
|
prog->setUniformValue("gamma", gamma_);
|
||||||
|
prog->setUniformValue("frame_max", tone_proc.frameMax());
|
||||||
|
// qDebug() << tone_proc.frameMax();
|
||||||
|
fbo_out.bindColorTexture(prev_write_plane, 0);
|
||||||
|
renderQuad(prog, quad);
|
||||||
|
} else {
|
||||||
|
fbo_out.blit(prev_write_plane, fbo_out.id(), cur_write_plane, fbo_out.rect(), fbo_out.rect());
|
||||||
|
}
|
||||||
|
phase.end();
|
||||||
|
|
||||||
|
/// FXAA
|
||||||
|
phase.begin("fxaa");
|
||||||
|
if (view->FXAA_) {
|
||||||
|
prog = shader_fxaa;
|
||||||
|
if (bindShader(prog)) {
|
||||||
|
auto free = getFreePlanes(0);
|
||||||
|
setUniformCamera(prog, 0, true, fbo_out.size());
|
||||||
|
fbo_out.bindColorTexture(prev_write_plane);
|
||||||
|
renderQuad(prog, quad, 0, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
phase.end();
|
||||||
|
|
||||||
|
/// custom effects
|
||||||
|
for (auto * e: fb_effects) {
|
||||||
|
if (!e->isEnabled()) continue;
|
||||||
|
phase.begin("fb effect " + e->name());
|
||||||
|
e->reloadShadersInternal();
|
||||||
|
e->drawInternal();
|
||||||
|
phase.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
fbo_out.release();
|
||||||
|
|
||||||
|
/// apply hovers and selection frame
|
||||||
|
phase.begin("service");
|
||||||
|
if (edit_mode) {
|
||||||
|
rend_selection.drawSelection(fbo_out, cur_write_plane);
|
||||||
|
rend_service.renderService();
|
||||||
|
} else {
|
||||||
|
fbo_out.blit(cur_write_plane, 0, 0, fbo_out.rect(), QRect(QPoint(), view->pixelSize()));
|
||||||
|
}
|
||||||
|
phase.end();
|
||||||
|
|
||||||
|
/// grab framebuffer
|
||||||
|
phase.begin("grab");
|
||||||
|
if (is_grabbing) {
|
||||||
|
fbo_out.queryImage(0);
|
||||||
|
last_img = fbo_out.getImage().mirrored();
|
||||||
|
// qDebug() << last_img.size();
|
||||||
|
}
|
||||||
|
phase.end();
|
||||||
|
|
||||||
|
/*
|
||||||
|
static QOpenGLShaderProgram * tprog = nullptr;
|
||||||
|
if (tprog && __reinit_debug) {
|
||||||
|
delete tprog;
|
||||||
|
tprog = nullptr;
|
||||||
|
}
|
||||||
|
if (!tprog) {
|
||||||
|
loadShadersMulti(tprog, "./shaders/debug.glsl");
|
||||||
|
tprog->bind();
|
||||||
|
tprog->setUniformValue("tex_cone", (int)tarShadowsCone);
|
||||||
|
tprog->setUniformValue("tex_omni", (int)tarShadowsOmni);
|
||||||
|
tprog->setUniformValue("dep_cone", (int)tarDepthsCone);
|
||||||
|
tprog->setUniformValue("dep_omni", (int)tarDepthsOmni);
|
||||||
|
QMatrix4x4 mat;
|
||||||
|
double sz = 0.33;
|
||||||
|
mat.translate(sz - 1, sz - 1);
|
||||||
|
mat.scale(sz, sz);
|
||||||
|
tprog->setUniformValue("qgl_ViewProjMatrix", mat);
|
||||||
|
}
|
||||||
|
__reinit_debug = false;
|
||||||
|
tprog->bind();
|
||||||
|
shadow_maps_cone.bind(f, tarShadowsCone);
|
||||||
|
shadow_maps_omni.bind(f, tarShadowsOmni);
|
||||||
|
depth_maps_cone.bind(f, tarDepthsCone);
|
||||||
|
depth_maps_omni.bind(f, tarDepthsOmni);
|
||||||
|
quad->draw(f, 1);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer::setCameraLightMode(int m) {
|
||||||
|
camera_light_mode = m;
|
||||||
|
view->scene()->setLightsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::setGrabImage(bool on) {
|
||||||
|
is_grabbing = on;
|
||||||
|
// fbo_out.enablePixelBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer::addFramebufferEffect(FramebufferEffectBase * e) {
|
||||||
|
e->r = this;
|
||||||
|
fb_effects << e;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::setSadowsEnabled(bool on) {
|
||||||
|
shader_defines[srLightSpotPass].removeAll("SHADOWS");
|
||||||
|
shader_defines[srLightOmniPass].removeAll("SHADOWS");
|
||||||
|
if (on) {
|
||||||
|
shader_defines[srLightSpotPass] << "SHADOWS";
|
||||||
|
shader_defines[srLightOmniPass] << "SHADOWS";
|
||||||
|
}
|
||||||
|
shadows_enabled = on;
|
||||||
|
reloadShaders();
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user