├── .cproject
├── .gitignore
├── .project
├── .settings
└── org.eclipse.cdt.codan.core.prefs
├── CMakeLists.txt
├── GUI
├── About.ui
├── AnimationPanel.cpp
├── AnimationPanel.h
├── AnimationPanel.ui
├── EditorWindow.cpp
├── EditorWindow.h
├── Main.cpp
├── MainWindow.cpp
├── MainWindow.h
├── MainWindow.ui
├── OffScreenRenderer.cpp
├── OffScreenRenderer.h
├── ProgramState.cpp
├── ProgramState.h
├── SidePanel.cpp
├── SidePanel.h
├── SidePanel.ui
├── icon
│ ├── i.iconset
│ │ └── icon_32x32.png
│ ├── icon.png
│ ├── macicon.icns
│ ├── winicon.ico
│ └── winicon.rc
├── resources
│ ├── add.png
│ ├── backward.png
│ ├── pause.png
│ ├── play.png
│ ├── repeat.png
│ └── resources.rc
└── widgets
│ ├── ActionButton.cpp
│ └── ActionButton.h
├── README.txt
├── core
├── BDMORPH.cpp
├── BDMORPH.h
├── KVFModel.cpp
├── KVFModel.h
├── MeshModel.cpp
├── MeshModel.h
├── OutlineModel.cpp
├── OutlineModel.h
├── VideoModel.cpp
└── VideoModel.h
└── utils
├── cholmod_common.cpp
├── cholmod_common.h
├── cholmod_matrix.cpp
├── cholmod_matrix.h
├── cholmod_vector.h
├── ffmpeg_encoder.cpp
├── ffmpeg_encoder.h
├── triangle.c
├── triangle.h
├── utils.cpp
├── utils.h
├── vector2d.cpp
└── vector2d.h
/.cproject:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
41 |
42 |
43 |
44 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | KVF
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder
10 | clean,full,incremental,
11 |
12 |
13 |
14 |
15 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
16 | full,incremental,
17 |
18 |
19 |
20 |
21 |
22 | org.eclipse.cdt.core.cnature
23 | org.eclipse.cdt.core.ccnature
24 | org.eclipse.cdt.managedbuilder.core.managedBuildNature
25 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
26 |
27 |
28 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.cdt.codan.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.cdt.codan.checkers.errnoreturn=Warning
3 | org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false}
4 | org.eclipse.cdt.codan.checkers.errreturnvalue=Error
5 | org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
6 | org.eclipse.cdt.codan.checkers.noreturn=Error
7 | org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false}
8 | org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error
9 | org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
10 | org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error
11 | org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
12 | org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning
13 | org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
14 | org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error
15 | org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
16 | org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning
17 | org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false}
18 | org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning
19 | org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},unknown\=>false,exceptions\=>()}
20 | org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error
21 | org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
22 | org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning
23 | org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},skip\=>true}
24 | org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error
25 | org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
26 | org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error
27 | org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
28 | org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error
29 | org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
30 | org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error
31 | org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
32 | org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error
33 | org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
34 | org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error
35 | org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
36 | org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error
37 | org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
38 | org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info
39 | org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},pattern\=>"^[a-z]",macro\=>true,exceptions\=>()}
40 | org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning
41 | org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
42 | org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error
43 | org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
44 | org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error
45 | org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
46 | org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error
47 | org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
48 | org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning
49 | org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
50 | org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning
51 | org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
52 | org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning
53 | org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>()}
54 | org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning
55 | org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},paramNot\=>false}
56 | org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning
57 | org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},else\=>false,afterelse\=>false}
58 | org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error
59 | org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
60 | org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning
61 | org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true}
62 | org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning
63 | org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true}
64 | org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning
65 | org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>("@(\#)","$Id")}
66 | org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error
67 | org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
68 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.6)
2 |
3 | PROJECT(bdmorph)
4 | FIND_PACKAGE(Qt4 REQUIRED)
5 | FIND_PACKAGE(OpenGL REQUIRED)
6 | SET(QT_USE_QTOPENGL TRUE)
7 | INCLUDE(${QT_USE_FILE})
8 |
9 | if(NOT CMAKE_BUILD_TYPE)
10 | set(CMAKE_BUILD_TYPE "Release" CACHE STRING
11 | "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
12 | FORCE)
13 | endif(NOT CMAKE_BUILD_TYPE)
14 |
15 | ###################################################################################################
16 |
17 | if (WIN32)
18 | SET(ROOT C:/Users/mlevtsky/Workspace/external)
19 | SET (EXTERNAL_LIBRARIES
20 | ${ROOT}/lib/libamd.lib
21 | ${ROOT}/lib/libcamd.lib
22 | ${ROOT}/lib/libcolamd.lib
23 | ${ROOT}/lib/libccolamd.lib
24 | ${ROOT}/lib/libcholmod.lib
25 |
26 | ${ROOT}/lib/libgoto_CHOLMOD.lib
27 | ${ROOT}/lib/libmetis_CHOLMOD.lib
28 |
29 | ${ROOT}/lib/avcodec.lib
30 | ${ROOT}/lib/avformat.lib
31 | ${ROOT}/lib/avutil.lib
32 | ${ROOT}/lib/swscale.lib
33 | )
34 |
35 | SET(EXTERNAL_INCLUDES
36 | ${ROOT}/include/
37 | ${ROOT}/include/suitesparse/
38 | )
39 |
40 | SET(ICON_RC_FILE GUI/icon/winicon.rc)
41 |
42 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -DNOMINMAX -D_USE_MATH_DEFINES ")
43 | set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -DNOMINMAX -D_USE_MATH_DEFINES ")
44 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /OPT:NOREF" )
45 |
46 | endif(WIN32)
47 |
48 | ###################################################################################################
49 |
50 | if (APPLE)
51 | SET (EXTERNAL_LIBRARIES
52 | cholmod amd camd colamd suitesparseconfig
53 | blas lapack
54 |
55 | avcodec avformat avutil swscale swresample
56 | "-framework CoreFoundation"
57 | "-framework CoreVideo"
58 | "-framework VideoDecodeAcceleration"
59 | x264 z bz2 iconv
60 | )
61 |
62 | SET (EXTERNAL_INCLUDES
63 | /usr/local/include/suitesparse
64 | )
65 |
66 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wno-reorder")
67 |
68 | set(MACOSX_BUNDLE_ICON_FILE macicon.icns)
69 |
70 | set(bdmorph_ICON ${CMAKE_CURRENT_SOURCE_DIR}/GUI/icon/macicon.icns)
71 | set_source_files_properties(${bdmorph_ICON} PROPERTIES
72 | MACOSX_PACKAGE_LOCATION "Resources")
73 |
74 | SET(ICON_RC_FILE ${bdmorph_ICON})
75 |
76 | endif(APPLE)
77 |
78 | ###################################################################################################
79 |
80 | if (NOT APPLE AND UNIX) # <- this is the way it should be
81 | SET (EXTERNAL_LIBRARIES
82 | cholmod amd camd colamd
83 | openblas lapack
84 | avcodec avformat avutil swscale
85 | )
86 |
87 | SET (EXTERNAL_INCLUDES
88 | /usr/include/suitesparse
89 | )
90 |
91 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wno-reorder -Woverloaded-virtual")
92 | endif(NOT APPLE AND UNIX)
93 |
94 | ###################################################################################################
95 |
96 | INCLUDE_DIRECTORIES(
97 | ${CMAKE_CURRENT_BINARY_DIR}
98 | ${EXTERNAL_INCLUDES}
99 | . ./GUI ./core ./utils ./GUI/widgets
100 | )
101 |
102 | SET(bdmorph_SOURCES
103 | GUI/EditorWindow.cpp GUI/Main.cpp GUI/MainWindow.cpp
104 | GUI/SidePanel.cpp GUI/AnimationPanel.cpp GUI/OffScreenRenderer.cpp
105 | GUI/widgets/ActionButton.cpp GUI/ProgramState.cpp
106 |
107 | core/MeshModel.cpp core/KVFModel.cpp core/VideoModel.cpp
108 | core/BDMORPH.cpp core/OutlineModel.cpp
109 |
110 | utils/cholmod_matrix.cpp utils/cholmod_common.cpp utils/vector2d.cpp
111 | utils/triangle.c utils/utils.cpp utils/ffmpeg_encoder.cpp
112 |
113 | )
114 |
115 | SET(bdmorph_HEADERS_QT
116 | GUI/EditorWindow.h GUI/MainWindow.h GUI/SidePanel.h
117 | GUI/AnimationPanel.h GUI/OffScreenRenderer.h GUI/widgets/ActionButton.h
118 | GUI/ProgramState.h
119 | )
120 |
121 | SET(bdmorph_HEADERS
122 | ${bdmorph_HEADERS_QT}
123 | core/MeshModel.h core/KVFModel.h core/VideoModel.h
124 | core/BDMORPH.h core/OutlineModel.h
125 |
126 | utils/cholmod_matrix.h utils/cholmod_common.h utils/vector2d.h
127 | utils/triangle.h utils/utils.h
128 | utils/ffmpeg_encoder.h
129 | )
130 |
131 | SET(bdmorph_FORMS
132 | GUI/MainWindow.ui GUI/SidePanel.ui GUI/AnimationPanel.ui GUI/About.ui
133 | )
134 |
135 | SET(bdmorph_RESOURCES GUI/resources/resources.rc )
136 |
137 | ###################################################################################################
138 |
139 | QT4_WRAP_CPP(bdmorph_HEADERS_MOC ${bdmorph_HEADERS_QT})
140 | QT4_WRAP_UI(bdmorph_FORMS_HEADERS ${bdmorph_FORMS})
141 | QT4_ADD_RESOURCES(bdmorph_RESOURCES_RCC ${bdmorph_RESOURCES})
142 |
143 | ADD_EXECUTABLE(bdmorph WIN32 MACOSX_BUNDLE
144 | ${bdmorph_SOURCES}
145 | ${bdmorph_RESOURCES_RCC}
146 | ${bdmorph_HEADERS_MOC}
147 | ${bdmorph_FORMS_HEADERS}
148 | ${bdmorph_HEADERS}
149 | ${ICON_RC_FILE}
150 | )
151 |
152 | TARGET_LINK_LIBRARIES(bdmorph
153 | ${QT_LIBRARIES}
154 | ${OPENGL_LIBRARIES}
155 | ${EXTERNAL_LIBRARIES}
156 | )
157 |
158 |
159 | ###################################################################################################
160 |
161 |
--------------------------------------------------------------------------------
/GUI/About.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | aboutDialog
4 |
5 |
6 |
7 | 0
8 | 0
9 | 693
10 | 307
11 |
12 |
13 |
14 | About
15 |
16 |
17 |
18 | :/MainWindow/icon/icon.png:/MainWindow/icon/icon.png
19 |
20 |
21 | -
22 |
23 |
24 | <html><head/><body><p>Animation program based on following papers:</p><p><span style=" font-weight:600;">"As-Killing-As-Possible Vector Fields for Planar Deformation"</span></p><p><span style=" font-weight:600;">"Planar Shape Interpolation with Bounded Distortion"</span></p><p>Based on <a href="http://www.cs.technion.ac.il/~cggc/Upload/Projects/KVFDeformation/download.html"><span style=" text-decoration: underline; color:#0000ff;">KVFDeformation</span></a></p><p>Implemented by Maxim Levitsky & Inbar Donag</p></body></html>
25 |
26 |
27 | Qt::AlignCenter
28 |
29 |
30 | false
31 |
32 |
33 | true
34 |
35 |
36 |
37 | -
38 |
39 |
40 |
41 | 0
42 | 0
43 |
44 |
45 |
46 |
47 | 256
48 | 256
49 |
50 |
51 |
52 |
53 |
54 |
55 | :/MainWindow/icon/icon.png
56 |
57 |
58 | true
59 |
60 |
61 |
62 | -
63 |
64 |
65 | Qt::Horizontal
66 |
67 |
68 | QDialogButtonBox::Ok
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | buttonBox
80 | accepted()
81 | aboutDialog
82 | accept()
83 |
84 |
85 | 248
86 | 254
87 |
88 |
89 | 157
90 | 274
91 |
92 |
93 |
94 |
95 | buttonBox
96 | rejected()
97 | aboutDialog
98 | reject()
99 |
100 |
101 | 316
102 | 260
103 |
104 |
105 | 286
106 | 274
107 |
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/GUI/AnimationPanel.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | #include "AnimationPanel.h"
14 | #include "VideoModel.h"
15 | #include "MeshModel.h"
16 | #include "OffScreenRenderer.h"
17 | #include "utils.h"
18 |
19 | #define INTEREVAL (1000/60)
20 |
21 | /******************************************************************************************************************************/
22 | AnimationPanel::AnimationPanel(QWidget* parent) :
23 | QDockWidget(parent), programstate(NULL)
24 | {
25 | setupUi(this);
26 | plusIcon = QIcon(":/AnimationPanel/add.png");
27 |
28 | cloneAction = new QAction("Clone frame", lstKeyFrames);
29 | deleteFramesAction = new QAction("Delete frame", lstKeyFrames);
30 | changeTimeAction = new QAction("Change time...", lstKeyFrames);
31 | loadKeyframe = new QAction("Load from file...", lstKeyFrames);
32 |
33 | lstKeyFrames->addAction(cloneAction);
34 | lstKeyFrames->addAction(deleteFramesAction);
35 | lstKeyFrames->addAction(changeTimeAction);
36 | lstKeyFrames->addAction(loadKeyframe);
37 | lstKeyFrames->setContextMenuPolicy(Qt::ActionsContextMenu);
38 |
39 | /* Play/pause buttons */
40 | connect_(btnAnimationPlay, clicked(bool), this, onPlayPauseButtonPressed());
41 | connect_(btnRepeat, clicked(bool), this, onRepeatButtonClicked(bool));
42 |
43 | /* Slider*/
44 | connect_(sliderAnimationTime, sliderMoved (int), this, onTimeSliderMoved(int));
45 |
46 | /* Keyframes list */
47 | connect_(lstKeyFrames, itemPressed(QListWidgetItem*), this, onItemClicked(QListWidgetItem*));
48 | connect_(cloneAction, triggered(), this, onCloneKeyFramePressed());
49 | connect_(changeTimeAction, triggered(), this, onKeyframeChangeTime());
50 | connect_(deleteFramesAction, triggered(), this, onDeleteKeyframe());
51 | connect_(loadKeyframe, triggered(), this, onLoadKeyframe());
52 |
53 | /* Time edit */
54 | timeEdit = new QLineEdit(lstKeyFrames);
55 | timeEdit->setInputMask("00:00.000");
56 | timeEdit->setAlignment(Qt::AlignCenter);
57 | timeEdit->hide();
58 | connect_(timeEdit, editingFinished (), this, onTimeTextFinished());
59 | connect_(btnBackward, clicked(), this, onBackwardButtonPressed());
60 |
61 | sliderAnimationTime->setMinimum(0);
62 | sliderAnimationTime->setTickPosition(QSlider::NoTicks);
63 |
64 | thumbnailRenderer = new OffScreenRenderer(NULL, NULL,128,128);
65 | }
66 |
67 | /******************************************************************************************************************************/
68 |
69 | AnimationPanel::~AnimationPanel()
70 | {
71 | delete thumbnailRenderer;
72 | }
73 |
74 | /******************************************************************************************************************************/
75 | /* EXTERNAL EVENTS */
76 | /******************************************************************************************************************************/
77 |
78 | void AnimationPanel::programStateUpdated(int flags)
79 | {
80 | if (!programstate) return;
81 |
82 | if (flags & ProgramState::KEYFRAME_LIST_EDITED)
83 | {
84 | /* See if one of our keyframes got updated
85 | * If so, update list items for it and all following keyframes */
86 | int updated_index = programstate->getCurrentKeyframeId();
87 | if (updated_index != -1)
88 | {
89 | updateItems(updated_index);
90 | updateTimeSlider();
91 | }
92 | }
93 |
94 | if (flags & ProgramState::MODEL_EDITED )
95 | {
96 | int updated_index = programstate->getCurrentKeyframeId();
97 | updateListItem(updated_index);
98 | }
99 |
100 | if (flags & ProgramState::TEXTURE_CHANGED)
101 | {
102 | /* Texture changed - need to re-render everything */
103 | thumbnailRenderer->setTexture(programstate->getTexture());
104 | updateItems(0);
105 | }
106 |
107 | if ( flags & (ProgramState::ANIMATION_POSITION_CHANGED))
108 | {
109 | sliderAnimationTime->setValue(programstate->getAnimationPosition());
110 | int index = programstate->getCurrentKeyframeId();
111 | selectFrame(index);
112 | }
113 |
114 | if (flags & ProgramState::MODE_CHANGED)
115 | {
116 | bool animation_running = programstate->getCurrentMode() == ProgramState::PROGRAM_MODE_ANIMATION_RUNNING;
117 | bool busy = programstate->isBusy() && !animation_running;
118 |
119 | lstKeyFrames->setDisabled(busy);
120 | sliderAnimationTime->setDisabled(busy);
121 | btnBackward->setDisabled(busy);
122 | btnAnimationPlay->setIcon(QIcon(animation_running ? ":/icons/pause.png" : ":/icons/play.png"));
123 | btnAnimationPlay->setEnabled(!busy);
124 | btnRepeat->setEnabled(!busy);
125 | }
126 |
127 | if (flags & ProgramState::CURRENT_MODEL_CHANGED)
128 | {
129 | sliderAnimationTime->setValue(programstate->getAnimationPosition());
130 | /* See if one of our frames is selected - if so select it */
131 | int newIndex = programstate->getCurrentKeyframeId();
132 | if (newIndex != -1)
133 | selectFrame(newIndex);
134 | }
135 | }
136 |
137 | /******************************************************************************************************************************/
138 | /* User input on our list */
139 | /******************************************************************************************************************************/
140 |
141 | void AnimationPanel::onItemClicked(QListWidgetItem *item)
142 | {
143 | if (!programstate) return;
144 | int newID = lstKeyFrames->row(item);
145 | selectFrame(newID);
146 |
147 | programstate->switchToKeyframe(newID);
148 |
149 | changeTimeAction->setEnabled(newID != 0);
150 | deleteFramesAction->setEnabled(programstate->getKeyframeCount() > 1);
151 |
152 | /* If we clicked on + sign, add new as a clone of last one */
153 | if (newID == programstate->getKeyframeCount()) {
154 | programstate->cloneKeyframe(programstate->getKeyframeCount()-1);
155 | return;
156 | }
157 |
158 | }
159 |
160 | /******************************************************************************************************************************/
161 | void AnimationPanel::onCloneKeyFramePressed()
162 | {
163 | if (!programstate) return;
164 |
165 | int currentID = programstate->getCurrentKeyframeId();
166 | if (currentID == -1) return;
167 | programstate->cloneKeyframe(currentID);
168 | }
169 |
170 | /******************************************************************************************************************************/
171 | void AnimationPanel::onDeleteKeyframe()
172 | {
173 | if (!programstate) return;
174 |
175 | /* Find what keyframe is selected - if none then its false call */
176 | int currentID = programstate->getCurrentKeyframeId();
177 | if (currentID == -1) return;
178 | programstate->deleteKeyFrame(currentID);
179 | }
180 |
181 | /******************************************************************************************************************************/
182 | void AnimationPanel::onKeyframeChangeTime()
183 | {
184 | if (!programstate) return;
185 |
186 | int currentID = programstate->getCurrentKeyframeId();
187 | if (currentID == -1 || currentID == 0) return;
188 |
189 | QRect r = lstKeyFrames->visualItemRect(lstKeyFrames->item(currentID));
190 |
191 | int upstripe = (r.height() - 128)/2;
192 |
193 | r.setLeft(r.left()+10);
194 | r.setRight(r.right()-10);
195 |
196 | timeEdit->move(r.left(),r.bottom() - timeEdit->height()/2 - upstripe);
197 | timeEdit->resize(r.width(),timeEdit->height());
198 | timeEdit->setText(QString::fromStdString(printTime(programstate->getKeyframeTime(currentID))));
199 | timeEdit->show();
200 | timeEdit->setFocus();
201 | timeEdit->setCursorPosition(0);
202 | }
203 |
204 | /******************************************************************************************************************************/
205 | void AnimationPanel::onTimeTextFinished()
206 | {
207 | timeEdit->hide();
208 | if (!programstate) return;
209 |
210 | int newTime = getTime(timeEdit->text().toStdString());
211 |
212 | if (newTime < 0)
213 | return;
214 |
215 | int currentID = programstate->getCurrentKeyframeId();
216 | if (currentID == -1 || currentID == 0) return;
217 |
218 | int prevFrameTime = programstate->getKeyframeTime(currentID-1);
219 | programstate->setKeyframeTime(currentID-1,newTime-prevFrameTime);
220 | programstate->switchToKeyframe(currentID);
221 | }
222 |
223 | /******************************************************************************************************************************/
224 | /* Time Slider */
225 | /******************************************************************************************************************************/
226 |
227 | void AnimationPanel::onPlayPauseButtonPressed()
228 | {
229 | if (!programstate) return;
230 | programstate->startStopAnimations();
231 | }
232 | /******************************************************************************************************************************/
233 |
234 | void AnimationPanel::onRepeatButtonClicked(bool checked)
235 | {
236 | if (!programstate) return;
237 | programstate->setAnimationRepeat(checked);
238 | }
239 |
240 | /******************************************************************************************************************************/
241 | void AnimationPanel::onTimeSliderMoved(int newValue)
242 | {
243 | if (!programstate) return;
244 | programstate->setAnimationPosition(newValue);
245 | }
246 |
247 | /******************************************************************************************************************************/
248 | /* Other */
249 | /******************************************************************************************************************************/
250 | void AnimationPanel::updateItems(int startItem)
251 | {
252 | if (!programstate) return;
253 | if (startItem == -1) return;
254 |
255 | int frameCount = programstate->getKeyframeCount();
256 | for (int frame = startItem ; frame < frameCount ; frame++)
257 | updateListItem(frame);
258 |
259 | insertPlus(frameCount);
260 | int firstItemToRemove = frameCount + 1;
261 |
262 | while (lstKeyFrames->count() > firstItemToRemove)
263 | {
264 | QListWidgetItem* item = lstKeyFrames->takeItem(firstItemToRemove);
265 | delete item;
266 | }
267 |
268 | lstKeyFrames->repaint();
269 | }
270 |
271 | /******************************************************************************************************************************/
272 | void AnimationPanel::updateListItem(int id)
273 | {
274 | if (!programstate || !programstate->videoModel) return;
275 |
276 | VideoKeyFrame* frame = programstate->videoModel->getKeyframeByIndex(id);
277 | if (!frame) return;
278 |
279 | QListWidgetItem* item = lstKeyFrames->item(id);
280 |
281 | if (!item) {
282 | item = new QListWidgetItem;
283 | lstKeyFrames->insertItem(id,item);
284 | }
285 |
286 | /* This code is gross... yuck and I wrote it*/
287 | QImage im;
288 | thumbnailRenderer->renderToQImage(frame, im,30,1);
289 | QPixmap p = QPixmap::fromImage(im);
290 |
291 | QPainter painter(&p);
292 | painter.drawText(im.rect(), Qt::AlignBottom | Qt::AlignCenter,
293 | QString::fromStdString(printTime(programstate->videoModel->getKeyFrameTimeMsec(frame))));
294 | item->setIcon(QIcon(p));
295 | }
296 |
297 | /******************************************************************************************************************************/
298 | void AnimationPanel::insertPlus(int id)
299 | {
300 | QListWidgetItem* item = lstKeyFrames->item(id);
301 |
302 | if (!item) {
303 | item = new QListWidgetItem;
304 | lstKeyFrames->insertItem(id,item);
305 | }
306 |
307 | item->setIcon(plusIcon);
308 | }
309 | /******************************************************************************************************************************/
310 |
311 | void AnimationPanel::selectFrame(int index)
312 | {
313 | lstKeyFrames->scrollToItem(lstKeyFrames->item(index+1));
314 | lstKeyFrames->setCurrentRow(index);
315 | }
316 |
317 | /******************************************************************************************************************************/
318 | void AnimationPanel::updateTimeSlider()
319 | {
320 | if (!programstate || !programstate->videoModel) return;
321 |
322 | int totalDuration = programstate->videoModel->getTotalTime();
323 | int current_time = programstate->getKeyframeTime(programstate->getCurrentKeyframeId());
324 | sliderAnimationTime->setMaximum(totalDuration);
325 | sliderAnimationTime->setValue(current_time);
326 | }
327 |
328 | /******************************************************************************************************************************/
329 | void AnimationPanel::onShowHide(bool show)
330 | {
331 | setVisible(show);
332 | }
333 | /******************************************************************************************************************************/
334 |
335 | void AnimationPanel::onBackwardButtonPressed()
336 | {
337 | if (!programstate) return;
338 |
339 | if (programstate->isAnimations())
340 | programstate->setAnimationPosition(0);
341 | else
342 | programstate->switchToKeyframe(0);
343 | }
344 |
345 | /******************************************************************************************************************************/
346 |
347 | void AnimationPanel::onLoadKeyframe()
348 | {
349 | QString filename = QFileDialog::getOpenFileName(this, tr("Choose model for the keyframe"),
350 | QString(), QLatin1String("*.obj *.off"));
351 | if (filename == NULL)
352 | return;
353 |
354 | programstate->loadKeyframe(filename.toStdString());
355 | }
356 |
--------------------------------------------------------------------------------
/GUI/AnimationPanel.h:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include "ui_AnimationPanel.h"
9 |
10 | #include "ProgramState.h"
11 |
12 | class VideoModel;
13 | class KVFModel;
14 | class VideoKeyFrame;
15 | class MeshModel;
16 | class OffScreenRenderer;
17 |
18 | /*****************************************************************************************/
19 | class AnimationPanel : public QDockWidget, public Ui_AnimationPanel
20 | {
21 | Q_OBJECT
22 | public:
23 | AnimationPanel(QWidget* parent);
24 | virtual ~AnimationPanel();
25 | public slots:
26 | void programStateUpdated(int flags);
27 | void programStateCreated(ProgramState* state) { programstate = state; }
28 |
29 | /* Signals from list view*/
30 | void onItemClicked(QListWidgetItem *item);
31 | void onCloneKeyFramePressed();
32 | void onDeleteKeyframe();
33 | void onKeyframeChangeTime();
34 | void onTimeTextFinished();
35 | void onTimeSliderMoved(int newValue);
36 | void onPlayPauseButtonPressed();
37 | void onRepeatButtonClicked(bool checked);
38 | void onShowHide(bool show);
39 | void onBackwardButtonPressed();
40 | void onLoadKeyframe();
41 | private:
42 | void updateItems(int startItem);
43 | void updateListItem(int id);
44 | void updateTimeSlider();
45 |
46 | void insertPlus(int id);
47 | void selectFrame(int index);
48 | private:
49 | QIcon plusIcon;
50 | QLineEdit *timeEdit;
51 | ProgramState* programstate;
52 | OffScreenRenderer *thumbnailRenderer;
53 |
54 | QAction *cloneAction;
55 | QAction *deleteFramesAction;
56 | QAction *changeTimeAction;
57 | QAction *loadKeyframe ;
58 |
59 | };
60 |
--------------------------------------------------------------------------------
/GUI/AnimationPanel.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | AnimationPanel
4 |
5 |
6 |
7 | 0
8 | 0
9 | 549
10 | 223
11 |
12 |
13 |
14 | QDockWidget::DockWidgetClosable|QDockWidget::DockWidgetMovable
15 |
16 |
17 | Qt::BottomDockWidgetArea
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | 4
26 |
27 |
28 | 2
29 |
30 |
31 | 2
32 |
33 |
34 | 6
35 |
36 |
37 | 2
38 |
39 | -
40 |
41 |
42 | 0
43 |
44 |
-
45 |
46 |
47 |
48 | 0
49 | 0
50 |
51 |
52 |
53 | Press to start/stop the animations
54 |
55 |
56 |
57 |
58 |
59 |
60 | :/icons/play.png:/icons/play.png
61 |
62 |
63 | true
64 |
65 |
66 |
67 | -
68 |
69 |
70 | Toggle loop mode (animation restarts when reaches end)
71 |
72 |
73 |
74 |
75 |
76 |
77 | :/icons/repeat.png:/icons/repeat.png
78 |
79 |
80 | true
81 |
82 |
83 | false
84 |
85 |
86 |
87 | -
88 |
89 |
90 | Rewind animation to start
91 |
92 |
93 |
94 |
95 |
96 |
97 | :/icons/backward.png:/icons/backward.png
98 |
99 |
100 |
101 | -
102 |
103 |
104 | Shows relative position of current frame to whole animation sequence
105 |
106 |
107 | Qt::Horizontal
108 |
109 |
110 | QSlider::TicksBelow
111 |
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
119 |
120 | 0
121 | 160
122 |
123 |
124 |
125 | true
126 |
127 |
128 | false
129 |
130 |
131 | false
132 |
133 |
134 | QAbstractItemView::DropOnly
135 |
136 |
137 | QAbstractItemView::SingleSelection
138 |
139 |
140 |
141 | 128
142 | 128
143 |
144 |
145 |
146 | QAbstractItemView::ScrollPerPixel
147 |
148 |
149 | QAbstractItemView::ScrollPerPixel
150 |
151 |
152 | QListView::Static
153 |
154 |
155 | QListView::LeftToRight
156 |
157 |
158 | false
159 |
160 |
161 | QListView::Adjust
162 |
163 |
164 | QListView::ListMode
165 |
166 |
167 | true
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 | ActionButton
177 | QPushButton
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
--------------------------------------------------------------------------------
/GUI/EditorWindow.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include "EditorWindow.h"
10 | #include "MeshModel.h"
11 | #include "KVFModel.h"
12 | #include "OutlineModel.h"
13 | #include "VideoModel.h"
14 | #include
15 |
16 | /******************************************************************************************************************************/
17 | EditorWindow::EditorWindow(QWidget* parent) :
18 | programstate(NULL),
19 | QGLWidget(QGLFormat(QGL::SampleBuffers), parent),
20 | textureRef(0)
21 | {
22 | setAttribute(Qt::WA_AcceptTouchEvents);
23 | setAttribute(Qt::WA_StaticContents);
24 | setFocusPolicy(Qt::WheelFocus);
25 | setMouseTracking(true);
26 | setContextMenuPolicy(Qt::ActionsContextMenu);
27 | }
28 |
29 | /******************************************************************************************************************************/
30 |
31 | EditorWindow::~EditorWindow()
32 | {
33 | deleteTexture(textureRef);
34 | }
35 |
36 | /******************************************************************************************************************************/
37 |
38 | void EditorWindow::programStateUpdated(int flags)
39 | {
40 | if (!programstate) return;
41 | MeshModel *currentModel = programstate->currentModel;
42 | bool need_repaint = false;
43 |
44 | if (flags & (ProgramState::CURRENT_MODEL_CHANGED))
45 | {
46 | programstate->setSelectedVertexAndFace(-1,-1);
47 | need_repaint = true;
48 | }
49 |
50 | if (flags & (ProgramState::MODEL_EDITED | ProgramState::ANIMATION_POSITION_CHANGED)) {
51 | need_repaint = true;
52 | }
53 |
54 | if (flags & ProgramState::RENDER_SETTINGS_CHANGED)
55 | {
56 | setMouseTracking(programstate->getRenderSettings().showSelection);
57 | programstate->setSelectedVertexAndFace(-1,-1);
58 | need_repaint = true;
59 | }
60 |
61 | if (flags & ProgramState::TEXTURE_CHANGED) {
62 | makeCurrent();
63 | deleteTexture(textureRef);
64 | textureRef = bindTexture(programstate->getTexture(),GL_TEXTURE_2D,GL_RGBA);
65 | need_repaint = true;
66 | }
67 |
68 | if (flags & ProgramState::TRANSFORM_RESET) {
69 | if (currentModel) {
70 | double maxZoomX = width() / currentModel->getWidth();
71 | double maxZoomY = height() / currentModel->getHeight();
72 | double maxZoom = std::min(maxZoomX,maxZoomY);
73 | modelWidth = currentModel->getWidth() * maxZoom * 0.5;
74 | modelLocation = QPointF(0, 0);
75 | need_repaint = true;
76 | }
77 | }
78 |
79 | if (need_repaint)
80 | repaint();
81 | }
82 |
83 | /******************************************************************************************************************************/
84 |
85 | void EditorWindow::initializeGL()
86 | {
87 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
88 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
89 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
90 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
91 |
92 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
93 |
94 | glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
95 | glEnable(GL_LINE_SMOOTH);
96 |
97 | glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
98 | glEnable(GL_POLYGON_SMOOTH);
99 |
100 | glEnable(GL_BLEND);
101 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
102 | }
103 |
104 | /******************************************************************************************************************************/
105 | void EditorWindow::resizeGL(int w, int h)
106 | {
107 | repaint();
108 | }
109 |
110 | /******************************************************************************************************************************/
111 |
112 | void EditorWindow::paintGL()
113 | {
114 | glViewport(0,0,(GLint)width(), (GLint)height());
115 | glClearColor(1.,1.,1., 1.0f);
116 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
117 |
118 | if (!programstate) return;
119 | MeshModel *renderModel = programstate->currentModel;
120 | const RenderSettings& editSettings = programstate->getRenderSettings();
121 |
122 | if (!renderModel)
123 | return;
124 |
125 | TimeMeasurment t;
126 |
127 | double ratio = (renderModel->getWidth()) / modelWidth;
128 |
129 | double centerX = (-ratio * modelLocation.x()) + renderModel->center.x;
130 | double centerY = (-ratio * modelLocation.y()) + renderModel->center.y;
131 | double neededWidth = ratio * width();
132 | double neededHeight = ratio * height();
133 |
134 | /* Setup projection */
135 | glMatrixMode(GL_PROJECTION);
136 | glLoadIdentity();
137 | glOrtho(centerX - neededWidth/2 , centerX + neededWidth/2, centerY - neededHeight/2 , centerY + neededHeight/2, 0, 1);
138 |
139 | /* render the model*/
140 | renderModel->renderFaces();
141 | if (programstate->getRenderSettings().wireframeTransparency)
142 | {
143 | glColor4f(0,0,0,editSettings.wireframeTransparency);
144 | renderModel->renderWireframe();
145 | }
146 |
147 | /* Some models will render stuff on top, like pined vertexes, extra wireframes, etc*/
148 | renderModel->renderOverlay(ratio);
149 |
150 |
151 | /* Render hovered vertices */
152 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
153 | if (programstate->getStatusbarData().selectedFace != -1)
154 | {
155 | glColor4f(0,0,1,0.5);
156 | renderModel->renderFace(programstate->getStatusbarData().selectedFace);
157 | }
158 |
159 | if (programstate->getStatusbarData().selectedVertex != -1)
160 | {
161 | glColor3f(0,0,1);
162 | renderModel->renderVertex(programstate->getStatusbarData().selectedVertex, ratio);
163 | }
164 |
165 | /* render selected vertices */
166 | glColor3f(1,0,0);
167 | for (unsigned int i = 0; i < selectedVertices.size(); i++)
168 | renderModel->renderVertex(selectedVertices[i], ratio);
169 |
170 |
171 | /* render VF of KVF model */
172 | KVFModel* kvfModel = dynamic_cast(renderModel);
173 | if (kvfModel)
174 | {
175 | if (editSettings.showVForig)
176 | kvfModel->renderVFOrig();
177 | if (editSettings.showVF)
178 | kvfModel->renderVF();
179 | }
180 |
181 | BDMORPHModel* bdmodel = dynamic_cast(renderModel);
182 |
183 | if (bdmodel) {
184 | if (editSettings.showBDmorphEdge)
185 | bdmodel->renderInitialEdge(ratio);
186 |
187 | if (editSettings.showBDmorphOrigMesh && bdmodel->modela ) {
188 | glColor4f(1,0,0,editSettings.wireframeTransparency);
189 | bdmodel->modela->renderWireframe();
190 | }
191 | }
192 |
193 | printf("Editor: took %f msec to render\n",t.measure_msec());
194 | }
195 |
196 | /******************************************************************************************************************************/
197 | bool EditorWindow::event(QEvent *event)
198 | {
199 | switch (event->type()) {
200 | case QEvent::TouchBegin:
201 | case QEvent::TouchUpdate:
202 | case QEvent::TouchEnd:
203 | return touchEvent(static_cast(event));
204 | default:
205 | return QWidget::event(event);
206 | }
207 | }
208 |
209 | /******************************************************************************************************************************/
210 | bool EditorWindow::touchEvent(QTouchEvent* te)
211 | {
212 | if (!programstate) return false;
213 | if (programstate->getRenderSettings().pinMode) return false;
214 | if (!programstate->isDeformationEditor()) return false;
215 |
216 | KVFModel *kvfModel = dynamic_cast(programstate->currentModel);
217 | if (!kvfModel) return false;
218 |
219 | QList touchPoints = te->touchPoints();
220 |
221 | #if 0
222 | if (!programstate->multitouchMode && touchPoints.count() == 2)
223 | {
224 | //zoom only in normal mode
225 | QTouchEvent::TouchPoint p0 = touchPoints.first();
226 | QTouchEvent::TouchPoint p1 = touchPoints.last();
227 | QLineF line1(p0.startPos(), p1.startPos());
228 | QLineF line2(p0.pos(), p1.pos());
229 | qreal scaleFactor = line2.length() / line1.length();
230 | zoom(scaleFactor + (1 - scaleFactor) / 1.05);
231 | return true;
232 | }
233 | #endif
234 |
235 | if (te->type() == QEvent::TouchEnd)
236 | {
237 | touchPointLocations.clear();
238 | selectedVertices.clear();
239 | return true;
240 | }
241 |
242 | // fix set of pins
243 | std::set ids;
244 |
245 | for (int i = 0; i < touchPoints.size(); i++)
246 | {
247 | QTouchEvent::TouchPoint p = touchPoints[i];
248 | if (touchPointLocations.count(p.id()) == 0) {
249 | touchPointLocations[p.id()] = p.pos();
250 | touchToVertex[p.id()] = kvfModel->getClosestVertex(screenToModel(kvfModel,p.pos()));
251 | }
252 | ids.insert(p.id());
253 | }
254 |
255 | std::map::iterator it = touchPointLocations.begin();
256 | std::set toRemove;
257 | while (it != touchPointLocations.end()) {
258 | if (ids.count(it->first) == 0)
259 | toRemove.insert(it->first);
260 | ++it;
261 | }
262 |
263 | for (std::set::iterator iter = toRemove.begin();iter != toRemove.end(); ++iter)
264 | touchPointLocations.erase(*iter);
265 |
266 | // figure out if anything moved significantly
267 | double maxDistance = 0;
268 |
269 | for (int i = 0; i < touchPoints.size(); i++)
270 | {
271 | QPointF loc = touchPoints[i].pos();
272 | QPointF old = touchPointLocations[touchPoints[i].id()];
273 | QPointF diff = old - loc;
274 | double d = sqrt(diff.x() * diff.x() + diff.y() * diff.y());
275 | if (d > maxDistance)
276 | maxDistance = d;
277 | }
278 |
279 | if (maxDistance >= 1)
280 | {
281 | // moved more than one pixel!
282 | std::set disps;
283 |
284 | for (int i = 0; i < touchPoints.size(); i++)
285 | {
286 | if (touchToVertex[touchPoints[i].id()] == -1)
287 | continue;
288 |
289 | Vector2 displacement = screenToModel(kvfModel,touchPoints[i].pos()) -
290 | screenToModel(kvfModel,touchPointLocations[touchPoints[i].id()]);
291 |
292 | disps.insert(DisplacedVertex(touchToVertex[touchPoints[i].id()], displacement));
293 | touchPointLocations[touchPoints[i].id()] = touchPoints[i].pos();
294 | }
295 |
296 | if (disps.size() > 0)
297 | {
298 | RenderSettings settings = programstate->getRenderSettings();
299 |
300 | if (settings.showVF || settings.showVForig)
301 | kvfModel->calculateVF(disps,settings.alpha);
302 | else
303 | kvfModel->displaceMesh(disps,settings.alpha);
304 |
305 | programstate->informModelEdited();
306 | programstate->setFPS(1000.0 / (kvfModel->lastVFApplyTime + kvfModel->lastVFCalcTime));
307 | }
308 | }
309 |
310 | selectedVertices.clear();
311 | for (std::map::iterator it = touchPointLocations.begin();it != touchPointLocations.end(); ++it)
312 | selectedVertices.push_back(touchToVertex[it->first]);
313 |
314 | return true;
315 | }
316 | /******************************************************************************************************************************/
317 | void EditorWindow::keyPressEvent(QKeyEvent *e)
318 | {
319 | if (!programstate) return;
320 |
321 | switch(e->key()) {
322 | case Qt::Key_Up:
323 | moveUp();
324 | repaint();
325 | break;
326 | case Qt::Key_Down:
327 | moveDown();
328 | repaint();
329 | break;
330 | case Qt::Key_Left:
331 | moveLeft();
332 | repaint();
333 | break;
334 | case Qt::Key_Right:
335 | moveRight();
336 | repaint();
337 | break;
338 | case Qt::Key_Plus:
339 | case Qt::Key_Equal:
340 | zoomIn();
341 | repaint();
342 | break;
343 | case Qt::Key_Minus:
344 | case Qt::Key_Underscore:
345 | zoomOut();
346 | repaint();
347 | break;
348 | }
349 | }
350 |
351 | /******************************************************************************************************************************/
352 | void EditorWindow::mousePressEvent(QMouseEvent *event)
353 | {
354 | mouseMoved = false;
355 | mouseLeft = event->buttons() & Qt::LeftButton;
356 | QPointF pos = event->pos(); // (0,0) is upper left
357 | pos.setY(height()-pos.y()-1);
358 | lastMousePos = pos;
359 |
360 | if (!programstate) return;
361 | MeshModel *model = programstate->currentModel;
362 | if (!model) return;
363 |
364 | setCursor(Qt::BlankCursor);
365 | Point2 modelPos = screenToModel(model,pos);
366 |
367 | if ((QApplication::keyboardModifiers() == Qt::NoModifier) &&
368 | !programstate->getRenderSettings().pinMode && programstate->isDeformationEditor())
369 | {
370 | Vertex v = model->getClosestVertex(modelPos);
371 | /* Select this vertex */
372 | selectedVertices.clear();
373 | selectedVertices.push_back(v);
374 | repaint();
375 | return;
376 | }
377 |
378 | if (programstate->isBusy())
379 | return;
380 |
381 | if (event->buttons() & Qt::LeftButton)
382 | model->mousePressAction(modelPos,getRadius(model));
383 |
384 | repaint();
385 | return;
386 | }
387 | /******************************************************************************************************************************/
388 | void EditorWindow::mouseMoveEvent(QMouseEvent *event)
389 | {
390 | mouseLeft = event->buttons() & Qt::LeftButton;
391 |
392 | QPointF oldPos = lastMousePos;
393 | QPointF curPos = event->pos();
394 | curPos.setY(height()-curPos.y()-1);
395 |
396 | if (lastMousePos == curPos)
397 | return;
398 |
399 | lastMousePos = curPos;
400 |
401 | if (!programstate) return;
402 | MeshModel *model = programstate->currentModel;
403 | KVFModel *kvfModel = dynamic_cast(programstate->currentModel);
404 | if (!model) return;
405 |
406 | Qt::KeyboardModifiers mods = QApplication::keyboardModifiers();
407 |
408 |
409 | /* Plain mouse move */
410 | if (event->buttons() == Qt::NoButton && programstate->getRenderSettings().showSelection &&
411 | mods == Qt::NoModifier)
412 | {
413 | programstate->setSelectedVertexAndFace(
414 | model->getClosestVertex(screenToModel(model,curPos)),
415 | model->getFaceUnderPoint(screenToModel(model,curPos)));
416 |
417 | repaint();
418 | return;
419 | }
420 |
421 | /* Right button pressed - always mouse move */
422 | if ((event->buttons() & Qt::RightButton))
423 | {
424 | QPointF diff = curPos - oldPos;
425 | move(QPointF(diff.x(),diff.y()));
426 | repaint();
427 | mouseMoved = true;
428 | return;
429 | }
430 |
431 | /* Left button pressed - edit */
432 | if ((event->buttons() & Qt::LeftButton))
433 | {
434 | bool deformMode =
435 | programstate->isDeformationEditor()
436 | && kvfModel && !programstate->getRenderSettings().pinMode && !(mods & Qt::ShiftModifier);
437 |
438 | if (deformMode)
439 | {
440 | QPointF diff = curPos - oldPos;
441 | Vertex selectedVertex = selectedVertices[0];
442 | diff *= kvfModel->getWidth() / modelWidth;
443 | if (diff.rx() == 0 && diff.ry() == 0)
444 | return;
445 |
446 | std::set disps;
447 | disps.insert(DisplacedVertex(selectedVertex, Vector2(diff.x(),diff.y())));
448 |
449 | RenderSettings settings = programstate->getRenderSettings();
450 |
451 | if (settings.showVF || settings.showVForig)
452 | kvfModel->calculateVF(disps,settings.alpha);
453 | else
454 | kvfModel->displaceMesh(disps,settings.alpha);
455 |
456 | programstate->informModelEdited();
457 | programstate->setFPS(1000.0 / (kvfModel->lastVFCalcTime+kvfModel->lastVFApplyTime));
458 | repaint();
459 | return;
460 | }
461 |
462 | if (!model->moveAction(screenToModel(model,oldPos), screenToModel(model,curPos), getRadius(model)))
463 | return;
464 | mouseMoved = true;
465 | repaint();
466 | }
467 | }
468 |
469 | /******************************************************************************************************************************/
470 | void EditorWindow::mouseReleaseEvent(QMouseEvent *event)
471 | {
472 | setCursor(Qt::ArrowCursor);
473 | selectedVertices.clear();
474 |
475 | if (!programstate) return;
476 | MeshModel *model = programstate->currentModel;
477 | if (!model) return;
478 |
479 | QPointF curPos = event->pos();
480 | curPos.setY(height()-curPos.y()-1);
481 |
482 | model->mouseReleaseAction(screenToModel(model,curPos),mouseMoved, getRadius(model), !mouseLeft);
483 | model->historySnapshot();
484 |
485 | update();
486 | mouseMoved = false;
487 | }
488 |
489 | /******************************************************************************************************************************/
490 | void EditorWindow::wheelEvent(QWheelEvent *event)
491 | {
492 | if (!programstate) return;
493 | MeshModel *model = programstate->currentModel;
494 | if (!model) return;
495 |
496 | QPointF pos = event->pos();
497 | pos.setY(height()-pos.y()-1);
498 |
499 | Point2 posBefore = screenToModel(model,pos);
500 | zoom(event->delta() > 0 ? ZOOM_FACTOR : 1 / ZOOM_FACTOR);
501 | Point2 posAfter = screenToModel(model,pos);
502 |
503 | Vector2 diff = (posAfter-posBefore) * (modelWidth / model->getWidth());
504 | QPointF m = QPointF(diff.x,diff.y);
505 | move(m);
506 |
507 | update();
508 | }
509 |
510 | /******************************************************************************************************************************/
511 | void EditorWindow::zoom(double factor)
512 | {
513 | modelWidth *= factor;
514 | }
515 |
516 | /******************************************************************************************************************************/
517 | void EditorWindow::move(QPointF direction)
518 | {
519 | modelLocation += direction;
520 | }
521 |
522 | /******************************************************************************************************************************/
523 | Point2 EditorWindow::screenToModel(MeshModel *model,QPointF pos)
524 | {
525 | assert(model);
526 | pos -= modelLocation;
527 | pos -= QPointF((double)width()/2,(double)height()/2);
528 | pos *= model->getWidth() / modelWidth;
529 | pos.rx() += model->center.x;
530 | pos.ry() += model->center.y;
531 | return Point2(pos.x(), pos.y());
532 | }
533 |
534 |
535 | double EditorWindow::getRadius(MeshModel *model)
536 | {
537 | Point2 modelPos = screenToModel(model,QPointF(0,0));
538 | Point2 modelPos2 = screenToModel(model,QPointF(0,5));
539 | return modelPos.distance(modelPos2);
540 | }
541 | /******************************************************************************************************************************/
542 |
--------------------------------------------------------------------------------
/GUI/EditorWindow.h:
--------------------------------------------------------------------------------
1 | #ifndef DEFORMATIONSCENE_H
2 | #define DEFORMATIONSCENE_H
3 |
4 | #include
5 | #include