1
git-svn-id: svn://db.shs.com.ru/libs@1 a8b55f48-bf90-11e4-a774-851b48703e85
40
qglview/.kdev4/glview.kdev4
Normal file
@@ -0,0 +1,40 @@
|
||||
[Buildset]
|
||||
BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00\x0c\x00g\x00l\x00v\x00i\x00e\x00w)
|
||||
|
||||
[CMake]
|
||||
Build Directory Count=1
|
||||
CMakeDir=/usr/share/cmake/Modules
|
||||
Current Build Directory Index=0
|
||||
ProjectRootRelative=./
|
||||
|
||||
[CMake][CMake Build Directory 0]
|
||||
Build Directory Path=file:///home/peri4/pprojects/glview/
|
||||
Build Type=
|
||||
CMake Binary=file:///usr/bin/cmake
|
||||
Environment Profile=
|
||||
Extra Arguments=
|
||||
Install Directory=file:///usr/local
|
||||
|
||||
[Launch]
|
||||
Launch Configurations=Launch Configuration 0
|
||||
|
||||
[Launch][Launch Configuration 0]
|
||||
Configured Launch Modes=execute
|
||||
Configured Launchers=nativeAppLauncher
|
||||
Name=glview
|
||||
Type=Native Application
|
||||
|
||||
[Launch][Launch Configuration 0][Data]
|
||||
Arguments=
|
||||
Dependencies=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x02\x00\x00\x00\x0c\x00g\x00l\x00v\x00i\x00e\x00w\x00\x00\x00\x0c\x00g\x00l\x00v\x00i\x00e\x00w)
|
||||
Dependency Action=Build
|
||||
EnvironmentGroup=default
|
||||
Executable=
|
||||
External Terminal=konsole --noclose --workdir %workdir -e %exe
|
||||
Project Target=glview,glview
|
||||
Use External Terminal=false
|
||||
Working Directory=
|
||||
isExecutable=false
|
||||
|
||||
[MakeBuilder]
|
||||
Number Of Jobs=8
|
||||
162
qglview/.kdev4/qglview.kdev4
Normal file
@@ -0,0 +1,162 @@
|
||||
[Buildset]
|
||||
BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00\x0e\x00q\x00g\x00l\x00v\x00i\x00e\x00w)
|
||||
|
||||
[CMake]
|
||||
Build Directory Count=1
|
||||
Current Build Directory Index=0
|
||||
ProjectRootRelative=./
|
||||
|
||||
[CMake][CMake Build Directory 0]
|
||||
Build Directory Path=file:///mnt/data/orders/libs/qglview/
|
||||
Build Type=
|
||||
CMake Binary=file:///usr/bin/cmake
|
||||
Environment Profile=
|
||||
Extra Arguments=
|
||||
Install Directory=file:///usr/local
|
||||
|
||||
[Defines And Includes][Compiler]
|
||||
Name=GCC
|
||||
Path=gcc
|
||||
Type=GCC
|
||||
|
||||
[Filters]
|
||||
size=23
|
||||
|
||||
[Filters][0]
|
||||
inclusive=0
|
||||
pattern=.*
|
||||
targets=3
|
||||
|
||||
[Filters][1]
|
||||
inclusive=0
|
||||
pattern=.git
|
||||
targets=2
|
||||
|
||||
[Filters][10]
|
||||
inclusive=0
|
||||
pattern=*.a
|
||||
targets=1
|
||||
|
||||
[Filters][11]
|
||||
inclusive=0
|
||||
pattern=*.so
|
||||
targets=1
|
||||
|
||||
[Filters][12]
|
||||
inclusive=0
|
||||
pattern=*.so.*
|
||||
targets=1
|
||||
|
||||
[Filters][13]
|
||||
inclusive=0
|
||||
pattern=moc_*
|
||||
targets=1
|
||||
|
||||
[Filters][14]
|
||||
inclusive=0
|
||||
pattern=*.moc
|
||||
targets=1
|
||||
|
||||
[Filters][15]
|
||||
inclusive=0
|
||||
pattern=ui_*
|
||||
targets=1
|
||||
|
||||
[Filters][16]
|
||||
inclusive=0
|
||||
pattern=qrc_*
|
||||
targets=1
|
||||
|
||||
[Filters][17]
|
||||
inclusive=0
|
||||
pattern=*~
|
||||
targets=1
|
||||
|
||||
[Filters][18]
|
||||
inclusive=0
|
||||
pattern=.*.kate-swp
|
||||
targets=1
|
||||
|
||||
[Filters][19]
|
||||
inclusive=0
|
||||
pattern=.*.swp
|
||||
targets=1
|
||||
|
||||
[Filters][2]
|
||||
inclusive=0
|
||||
pattern=CVS
|
||||
targets=2
|
||||
|
||||
[Filters][20]
|
||||
inclusive=0
|
||||
pattern=*.pyc
|
||||
targets=1
|
||||
|
||||
[Filters][21]
|
||||
inclusive=0
|
||||
pattern=*.pyo
|
||||
targets=1
|
||||
|
||||
[Filters][22]
|
||||
inclusive=0
|
||||
pattern=__pycache__
|
||||
targets=1
|
||||
|
||||
[Filters][3]
|
||||
inclusive=0
|
||||
pattern=.svn
|
||||
targets=2
|
||||
|
||||
[Filters][4]
|
||||
inclusive=0
|
||||
pattern=_svn
|
||||
targets=2
|
||||
|
||||
[Filters][5]
|
||||
inclusive=0
|
||||
pattern=SCCS
|
||||
targets=2
|
||||
|
||||
[Filters][6]
|
||||
inclusive=0
|
||||
pattern=_darcs
|
||||
targets=2
|
||||
|
||||
[Filters][7]
|
||||
inclusive=0
|
||||
pattern=.hg
|
||||
targets=2
|
||||
|
||||
[Filters][8]
|
||||
inclusive=0
|
||||
pattern=.bzr
|
||||
targets=2
|
||||
|
||||
[Filters][9]
|
||||
inclusive=0
|
||||
pattern=*.o
|
||||
targets=1
|
||||
|
||||
[Launch]
|
||||
Launch Configurations=Launch Configuration 0
|
||||
|
||||
[Launch][Launch Configuration 0]
|
||||
Configured Launch Modes=execute
|
||||
Configured Launchers=nativeAppLauncher
|
||||
Name=test
|
||||
Type=Native Application
|
||||
|
||||
[Launch][Launch Configuration 0][Data]
|
||||
Arguments=
|
||||
Dependencies=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x02\x00\x00\x00\x0e\x00q\x00g\x00l\x00v\x00i\x00e\x00w\x00\x00\x00\x18\x00q\x00g\x00l\x00v\x00i\x00e\x00w\x00_\x00t\x00e\x00s\x00t)
|
||||
Dependency Action=Build
|
||||
EnvironmentGroup=default
|
||||
Executable=file:///mnt/data/orders/libs/qglview/
|
||||
External Terminal=konsole --noclose --workdir %workdir -e %exe
|
||||
Project Target=qglview,qglview_test
|
||||
Use External Terminal=false
|
||||
Working Directory=
|
||||
isExecutable=false
|
||||
|
||||
[MakeBuilder]
|
||||
Number Of Jobs=8
|
||||
49
qglview/CMakeLists.txt
Normal file
@@ -0,0 +1,49 @@
|
||||
project(qglview)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
find_package(Qt4 REQUIRED)
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${QT_INCLUDES})
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall")
|
||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
|
||||
add_definitions(-DGL_GLEXT_PROTOTYPES)
|
||||
set(LIBS ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} qad_widgets)
|
||||
if (${WIN32})
|
||||
list(APPEND LIBS opengl32 glu32)
|
||||
else (${WIN32})
|
||||
list(APPEND LIBS GL GLU)
|
||||
endif (${WIN32})
|
||||
|
||||
file(GLOB MOCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.h")
|
||||
file(GLOB CPPS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cpp")
|
||||
file(GLOB UIS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.ui")
|
||||
file(GLOB RES "*.qrc")
|
||||
list(REMOVE_ITEM CPPS "main.cpp" "mainwindow.cpp")
|
||||
list(REMOVE_ITEM MOCS "mainwindow.h")
|
||||
list(REMOVE_ITEM UIS "mainwindow.ui")
|
||||
qt4_wrap_cpp(CMOCS ${MOCS} OPTIONS -nw)
|
||||
qt4_wrap_ui(CUIS ${UIS})
|
||||
qt4_add_resources(CRES ${RES})
|
||||
add_library(qglview SHARED ${CPPS} ${CMOCS} ${CUIS} ${CRES})
|
||||
target_link_libraries(qglview ${LIBS})
|
||||
if (DEFINED LIB)
|
||||
set(LIB 1)
|
||||
if (${WIN32})
|
||||
find_package(MinGW REQUIRED)
|
||||
set(CMAKE_INSTALL_PREFIX ${MINGW_DIR})
|
||||
install(FILES ${MOCS} DESTINATION ${MINGW_INCLUDE})
|
||||
install(TARGETS qglview DESTINATION ${MINGW_LIB})
|
||||
else ()
|
||||
set(CMAKE_INSTALL_PREFIX /usr)
|
||||
install(FILES ${MOCS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
|
||||
install(TARGETS qglview DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
|
||||
endif ()
|
||||
else ()
|
||||
install(TARGETS qglview DESTINATION bin)
|
||||
endif ()
|
||||
|
||||
qt4_wrap_cpp(CMOCS_TEST "mainwindow.h" OPTIONS -nw)
|
||||
qt4_wrap_ui(CUIS_TEST "mainwindow.ui")
|
||||
add_executable(qglview_test "main.cpp" "mainwindow.cpp" ${CMOCS_TEST} ${CUIS_TEST})
|
||||
target_link_libraries(qglview_test ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} qglview qad_widgets)
|
||||
18170
qglview/GLee.cpp
Normal file
17648
qglview/GLee.h
Normal file
4
qglview/clean
Normal file
@@ -0,0 +1,4 @@
|
||||
#! /bin/bash
|
||||
VERBOSE=1 make clean
|
||||
rm -rvf CMakeFiles
|
||||
rm -vf CMakeCache.txt Makefile cmake_install.cmake install_manifest.txt *.dll *.a *.so *.user* *~ *cxx moc_* ui_* qrc_* *.o
|
||||
4
qglview/clean.bat
Normal file
@@ -0,0 +1,4 @@
|
||||
#make clean
|
||||
del /q /f /s CMakeFiles
|
||||
rmdir /q /s CMakeFiles
|
||||
del /q /f CMakeCache.txt Makefile cmake_install.cmake install_manifest.txt *.user* *~ *cxx moc_* ui_* qrc_* *.o *.exe *.a *.dll *.lib core *.qrc.depends
|
||||
BIN
qglview/data/34.3DS
Normal file
BIN
qglview/data/NMBalls.png
Normal file
|
After Width: | Height: | Size: 73 KiB |
BIN
qglview/data/NMBumpsOut.png
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
qglview/data/NMHollyBumps.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
qglview/data/NMStripes.png
Normal file
|
After Width: | Height: | Size: 128 KiB |
BIN
qglview/data/celtic_010.jpg
Normal file
|
After Width: | Height: | Size: 210 KiB |
BIN
qglview/data/celtic_010n.jpg
Normal file
|
After Width: | Height: | Size: 442 KiB |
BIN
qglview/data/e/back.jpg
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
qglview/data/e/bottom.jpg
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
qglview/data/e/front.jpg
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
qglview/data/e/left.jpg
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
qglview/data/e/right.jpg
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
qglview/data/e/top.jpg
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
qglview/data/expl_07.png
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
qglview/data/hel.3DS
Normal file
BIN
qglview/data/l.3DS
Normal file
BIN
qglview/data/l_.3DS
Normal file
19878
qglview/data/l_.ASE
Normal file
BIN
qglview/data/media-record.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
qglview/data/proj_plane_d.tga
Normal file
BIN
qglview/data/proj_plane_h.tga
Normal file
BIN
qglview/data/proj_plane_n.tga
Normal file
BIN
qglview/data/s.3DS
Normal file
BIN
qglview/data/test.3DS
Normal file
42823
qglview/data/test.DAE
Normal file
BIN
qglview/data/test_.3DS
Normal file
BIN
qglview/data/waveNM.png
Normal file
|
After Width: | Height: | Size: 123 KiB |
127
qglview/glframebuffer.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "glframebuffer.h"
|
||||
|
||||
|
||||
GLFramebuffer::GLFramebuffer(int colorAttachments_, bool withDepth, GLenum colorFormat_, GLenum target__) {
|
||||
is_depth = withDepth;
|
||||
color_format = colorFormat_;
|
||||
target_ = target__;
|
||||
colors.fill(0, colorAttachments_);
|
||||
fbo = drbo = 0;
|
||||
tex_d = 0;
|
||||
wid = hei = 0;
|
||||
is_changed = false;
|
||||
}
|
||||
|
||||
|
||||
GLFramebuffer::~GLFramebuffer() {
|
||||
deleteGLFramebuffer(fbo);
|
||||
deleteGLRenderbuffer(drbo);
|
||||
for (int i = 0; i < colors.size(); ++i)
|
||||
deleteGLTexture(colors[i]);
|
||||
deleteGLTexture(tex_d);
|
||||
}
|
||||
|
||||
|
||||
void GLFramebuffer::resize(int width, int height) {
|
||||
wid = width;
|
||||
hei = height;
|
||||
deleteGLFramebuffer(fbo);
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
for (int i = 0; i < colors.size(); ++i) {
|
||||
deleteGLTexture(colors[i]);
|
||||
createGLTexture(colors[i], width, height, color_format, target_);
|
||||
glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(target_, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, target_, colors[i], 0);
|
||||
}
|
||||
if (is_depth) {
|
||||
deleteGLTexture(tex_d);
|
||||
deleteGLRenderbuffer(drbo);
|
||||
glGenRenderbuffers(1, &drbo);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, drbo);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, drbo);
|
||||
createGLTexture(tex_d, width, height, GL_DEPTH_COMPONENT);
|
||||
glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(target_, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, target_, tex_d, 0);
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
is_changed = false;
|
||||
}
|
||||
|
||||
|
||||
void GLFramebuffer::bind() {
|
||||
if (is_changed) resize(wid, hei);
|
||||
if (fbo == 0) return;
|
||||
glFlush();
|
||||
glGetIntegerv(GL_VIEWPORT, prev_view);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
QVector<GLenum> buffers;
|
||||
for (int i = 0; i < colors.size(); ++i)
|
||||
buffers << GL_COLOR_ATTACHMENT0 + i;
|
||||
glDrawBuffers(colors.size(), buffers.constData());
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
//glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glViewport(0, 0, wid, hei);
|
||||
}
|
||||
|
||||
|
||||
void GLFramebuffer::release() {
|
||||
is_changed = false;
|
||||
if (fbo == 0) return;
|
||||
glFlush();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glViewport(prev_view[0], prev_view[1], prev_view[2], prev_view[3]);
|
||||
}
|
||||
|
||||
|
||||
void GLFramebuffer::setWriteBuffers(int indeces[]) {
|
||||
QVector<GLenum> buffers;
|
||||
for (uint i = 0; i < sizeof(indeces); ++i)
|
||||
buffers << GL_COLOR_ATTACHMENT0 + indeces[i];
|
||||
glDrawBuffers(colors.size(), buffers.constData());
|
||||
}
|
||||
|
||||
|
||||
void GLFramebuffer::setWriteBuffers(int * indeces, int count) {
|
||||
QVector<GLenum> buffers;
|
||||
for (int i = 0; i < count; ++i)
|
||||
buffers << GL_COLOR_ATTACHMENT0 + indeces[i];
|
||||
glDrawBuffers(colors.size(), buffers.constData());
|
||||
}
|
||||
|
||||
|
||||
void GLFramebuffer::bindColorTextures() {
|
||||
for (int i = colors.size() - 1; i >= 0; --i) {
|
||||
glActiveTextureChannel(i);
|
||||
glBindTexture(GL_TEXTURE_2D, colors[i]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
}
|
||||
}
|
||||
57
qglview/glframebuffer.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GLFRAMEBUFFER_H
|
||||
#define GLFRAMEBUFFER_H
|
||||
|
||||
#include "gltypes.h"
|
||||
|
||||
class GLFramebuffer
|
||||
{
|
||||
public:
|
||||
GLFramebuffer(int colorAttachments = 1, bool withDepth = true, GLenum colorFormat = GL_RGBA8, GLenum target = GL_TEXTURE_2D);
|
||||
virtual ~GLFramebuffer();
|
||||
|
||||
GLuint id() const {return fbo;}
|
||||
GLuint colorTexture(int index = 0) const {return colors[index];}
|
||||
GLenum colorFormat() const {return color_format;}
|
||||
GLuint depthTexture() const {return tex_d;}
|
||||
GLenum target() const {return target_;}
|
||||
|
||||
void resize(int width, int height);
|
||||
void bind();
|
||||
void release();
|
||||
void setReadBuffer(int index) {glReadBuffer(GL_COLOR_ATTACHMENT0 + index);}
|
||||
void setWriteBuffer(int index) {glDrawBuffer(GL_COLOR_ATTACHMENT0 + index);}
|
||||
void setWriteBuffers(int indeces[]);
|
||||
void setWriteBuffers(int * indeces, int count);
|
||||
void setColorFormat(GLenum format) {color_format = format; is_changed = true;}
|
||||
|
||||
void copyDepthFrom(GLuint tex) {;}
|
||||
void bindColorTextures();
|
||||
|
||||
private:
|
||||
bool is_depth, is_changed;
|
||||
QVector<GLuint> colors;
|
||||
GLenum color_format, target_;
|
||||
GLuint fbo, drbo, tex_d;
|
||||
GLint prev_view[4], wid, hei;
|
||||
|
||||
};
|
||||
|
||||
#endif // GLFRAMEBUFFER_H
|
||||
203
qglview/globject.cpp
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
GLObjectBase & Light
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "globject.h"
|
||||
|
||||
|
||||
GLObjectBase::GLObjectBase() {
|
||||
type_ = Mesh;
|
||||
render_mode = View;
|
||||
pass_ = Solid;
|
||||
geom_prim = Triangles;
|
||||
scale_ = QVector3D(1., 1., 1.);
|
||||
parent_ = 0;
|
||||
is_init = is_tex_loaded = selected_ = false;
|
||||
visible_ = accept_fog = accept_light = cast_shadow = rec_shadow = select_ = true;
|
||||
line_width = -1.;
|
||||
blend_src = GL_SRC_ALPHA;
|
||||
blend_dest = GL_ONE_MINUS_SRC_ALPHA;
|
||||
type_ = Mesh;
|
||||
view_ = 0;
|
||||
}
|
||||
|
||||
|
||||
GLObjectBase * GLObjectBase::clone(bool withChildren) {
|
||||
GLObjectBase * o = new GLObjectBase();
|
||||
o->pass_ = pass_;
|
||||
o->is_init = false;
|
||||
o->accept_light = accept_light;
|
||||
o->accept_fog = accept_fog;
|
||||
o->visible_ = visible_;
|
||||
o->type_ = type_;
|
||||
o->pos_ = pos_;
|
||||
o->angles_ = angles_;
|
||||
o->scale_ = scale_;
|
||||
o->itransform_ = itransform_;
|
||||
o->bound = bound;
|
||||
o->name_ = name_ + "_copy";
|
||||
o->blend_src = blend_src;
|
||||
o->blend_dest = blend_dest;
|
||||
o->material_ = material_;
|
||||
o->pos_h = pos_h;
|
||||
o->points = points;
|
||||
o->puvws = puvws;
|
||||
o->faces = faces;
|
||||
o->uvws = uvws;
|
||||
o->normals = normals;
|
||||
o->vbo = vbo;
|
||||
o->view_ = 0;
|
||||
o->children_.clear();
|
||||
if (withChildren) {
|
||||
for (int i = 0; i < children_.size(); ++i)
|
||||
o->addChild(children_[i]->clone(withChildren));
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
void GLObjectBase::draw(bool simplest) {
|
||||
vbo.draw(geom_prim, simplest);
|
||||
/*if (!d_vertices.isEmpty()) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glVertexPointer(3, GL_FLOAT, 0, d_vertices.constData());
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, d_uvs.constData());
|
||||
//glColorPointer(4, GL_FLOAT, 0, d_colors.constData());
|
||||
glNormalPointer(GL_FLOAT, 0, d_normals.constData());
|
||||
glDrawArrays(geom_prim, 0, d_vertices.size() / 3);*/
|
||||
/*if (pass_ == Reflection) {
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
|
||||
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
|
||||
}*/
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
QList<GLObjectBase * > GLObjectBase::children(bool all_) {
|
||||
if (!all_) return children_;
|
||||
QList<GLObjectBase * > cl;
|
||||
addChildren(cl, this);
|
||||
return cl;
|
||||
}
|
||||
|
||||
|
||||
void GLObjectBase::addChildren(QList<GLObjectBase * > & list, GLObjectBase * where) {
|
||||
foreach (GLObjectBase * i, where->children_) {
|
||||
list << i;
|
||||
addChildren(list, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GLObjectBase::calculateBoundingBox() {
|
||||
if (points.isEmpty()) return;
|
||||
GLfloat mix, miy, miz, max, may, maz;
|
||||
mix = max = points[0].x;
|
||||
miy = may = points[0].y;
|
||||
miz = maz = points[0].z;
|
||||
foreach (const Vector3d & i, points) {
|
||||
if (mix > i.x) mix = i.x;
|
||||
if (max < i.x) max = i.x;
|
||||
if (miy > i.y) miy = i.y;
|
||||
if (may < i.y) may = i.y;
|
||||
if (miz > i.z) miz = i.z;
|
||||
if (maz < i.z) maz = i.z;
|
||||
}
|
||||
bound.x = (mix + max) / 2.;
|
||||
bound.y = (miy + may) / 2.;
|
||||
bound.z = (miz + maz) / 2.;
|
||||
bound.length = max - mix;
|
||||
bound.width = may - miy;
|
||||
bound.height = maz - miz;
|
||||
}
|
||||
|
||||
|
||||
void GLObjectBase::buildTransform() {
|
||||
itransform_.setToIdentity();
|
||||
GLObjectBase * p = parent_;
|
||||
if (p != 0)
|
||||
itransform_ *= p->itransform_;
|
||||
itransform_.translate(pos_);
|
||||
itransform_.rotate(angles_.z(), 0., 0., 1.);
|
||||
itransform_.rotate(angles_.y(), 0., 1., 0.);
|
||||
itransform_.rotate(angles_.x(), 1., 0., 0.);
|
||||
itransform_.scale(scale_);
|
||||
foreach (GLObjectBase * i, children_)
|
||||
i->buildTransform();
|
||||
}
|
||||
|
||||
|
||||
void GLObjectBase::checkPass() {
|
||||
if (material_.reflectivity > 0.f || material_.color_diffuse.alphaF() * (1.f - material_.transparency) < 1.f) pass_ = Transparent;
|
||||
else pass_ = Solid;
|
||||
}
|
||||
|
||||
|
||||
void GLObjectBase::render(int * id, QMap<int, GLObjectBase * > * ids, int sh_id_loc) {
|
||||
if (!visible_) return;
|
||||
glPushMatrix();
|
||||
if (pos_.x() != 0. || pos_.y() != 0. || pos_.z() != 0.) glTranslated(pos_.x(), pos_.y(), pos_.z());
|
||||
if (angles_.z() != 0.) glRotated(angles_.z(), 0., 0., 1.);
|
||||
if (angles_.y() != 0.) glRotated(angles_.y(), 0., 1., 0.);
|
||||
if (angles_.x() != 0.) glRotated(angles_.x(), 1., 0., 0.);
|
||||
if (scale_.x() != 1. || scale_.y() != 1. || scale_.z() != 1.) glScaled(scale_.x(), scale_.y(), scale_.z());
|
||||
material_.apply();
|
||||
if (id != 0) {
|
||||
++(*id);
|
||||
ids->insert(*id, this);
|
||||
//glVertexAttrib1f(sh_id_loc, (*id) / 255.f);
|
||||
//qDebug() << "assign to" << sh_id_loc << (*id) / 255.f;
|
||||
}
|
||||
draw();
|
||||
foreach (GLObjectBase * i, children_)
|
||||
i->render(id, ids, sh_id_loc);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
GLObjectBase * Light::clone(bool withChildren) {
|
||||
Light * o = new Light(*this);
|
||||
//GLObjectBase::clone(withChildren);
|
||||
o->is_init = false;
|
||||
o->name_ = name_ + "_copy";
|
||||
o->view_ = 0;
|
||||
o->children_.clear();
|
||||
if (withChildren) {
|
||||
for (int i = 0; i < children_.size(); ++i)
|
||||
o->addChild(children_[i]->clone(withChildren));
|
||||
}
|
||||
o->direction = direction;
|
||||
o->intensity = intensity;
|
||||
o->decay_const = decay_const;
|
||||
o->decay_linear = decay_linear;
|
||||
o->decay_quadratic = decay_quadratic;
|
||||
o->light_type = light_type;
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
void Light::draw(bool simplest) {
|
||||
bool l = glIsEnabled(GL_LIGHTING);
|
||||
glDisable(GL_LIGHTING);
|
||||
glPointSize(8.);
|
||||
glBegin(GL_POINTS);
|
||||
glColor3f(0., 0., 0.);
|
||||
glVertex3f(0., 0., 0.);
|
||||
glEnd();
|
||||
if (l) glEnable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
240
qglview/globject.h
Normal file
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
GLObjectBase & Light
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GLOBJECT_H
|
||||
#define GLOBJECT_H
|
||||
|
||||
#include "glvbo.h"
|
||||
#include "glframebuffer.h"
|
||||
|
||||
class GLObjectBase
|
||||
{
|
||||
friend class QGLView;
|
||||
friend class GLRendererBase;
|
||||
public:
|
||||
enum Type {Mesh, Light, ParticlesSystem};
|
||||
enum Pass {Solid, Transparent, Reflection, User};
|
||||
enum GeomPrimitives {Triangles = GL_TRIANGLES, Quads = GL_QUADS};
|
||||
enum RenderMode {View = 0, Point = GL_POINT, Line = GL_LINE, Fill = GL_FILL};
|
||||
|
||||
GLObjectBase();
|
||||
virtual ~GLObjectBase() {;}
|
||||
|
||||
virtual GLObjectBase * clone(bool withChildren = true);
|
||||
|
||||
QString name() const {return name_;}
|
||||
void setName(const QString & name) {name_ = name;}
|
||||
//virtual GLuint hList() {return list;}
|
||||
virtual void init() {calculateBoundingBox(); vbo.init(); vbo.rebuffer(); material_.reflection.create(); /*qDebug() << "init" << vbo.buffer_;*/ is_init = true;}
|
||||
virtual void draw(bool simplest = false);
|
||||
virtual void update() {}
|
||||
bool isInit() const {return is_init;}
|
||||
bool isTexturesLoaded() const {return is_tex_loaded;}
|
||||
Type type() const {return type_;}
|
||||
|
||||
RenderMode renderMode() const {return render_mode;}
|
||||
void setRenderMode(RenderMode mode) {render_mode = mode;}
|
||||
|
||||
double lineWidth() const {return line_width;}
|
||||
void setLineWidth(const double & width) {line_width = width;}
|
||||
|
||||
GLObjectBase * parent() {return parent_;}
|
||||
void setParent(GLObjectBase * o) {parent_ = o;}
|
||||
bool hasParent() const {return parent_ != 0;}
|
||||
bool hasChildren() const {return children_.size() != 0;}
|
||||
|
||||
void addChild(GLObjectBase * o) {if (o == this) return; if (o->parent_ != 0) o->parent_->children_.removeAll(o); children_ << o; o->parent_ = this; o->buildTransform(); if (view_ != 0) view_->collectLights();}
|
||||
void removeChild(GLObjectBase * o) {if (o == this) return; children_.removeAll(o); o->parent_ = 0; o->buildTransform(); if (view_ != 0) view_->collectLights();}
|
||||
void removeChild(int index) {children_[index]->parent_ = 0; children_[index]->buildTransform(); children_.removeAt(index); if (view_ != 0) view_->collectLights();}
|
||||
void clearChildren(bool deleteAll = false) {foreach (GLObjectBase * i, children_) {if (deleteAll) {i->clearChildren(true); delete i;} else {i->parent_ = 0; i->buildTransform();}} children_.clear(); if (view_ != 0) view_->collectLights();}
|
||||
int childCount() const {return children_.size();}
|
||||
GLObjectBase * child(int index) {if (index < 0 || index >= children_.size()) return 0; return children_[index];}
|
||||
GLObjectBase * child(const QString & name) {foreach (GLObjectBase * i, children_) if (i->name_ == name) return i; return 0;}
|
||||
QList<GLObjectBase * > children(bool all_ = false);
|
||||
|
||||
bool isVisible() const {return visible_;}
|
||||
bool isHidden() const {return !visible_;}
|
||||
void setVisible(bool v) {visible_ = v;}
|
||||
void setHidden(bool v) {visible_ = !v;}
|
||||
void show() {visible_ = true;}
|
||||
void hide() {visible_ = 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) {pos_ += dv; buildTransform();}
|
||||
void moveTo(const QVector3D & dv) {pos_ = dv; buildTransform();}
|
||||
void move(GLdouble dx, GLdouble dy, GLdouble dz = 0.) {move(QVector3D(dx, dy, dz)); buildTransform();}
|
||||
void moveTo(GLdouble dx, GLdouble dy, GLdouble dz = 0.) {moveTo(QVector3D(dx, dy, dz)); buildTransform();}
|
||||
void moveX(GLdouble o) {pos_.setX(pos_.x() + o); buildTransform();}
|
||||
void moveY(GLdouble o) {pos_.setY(pos_.y() + o); buildTransform();}
|
||||
void moveZ(GLdouble o) {pos_.setZ(pos_.z() + o); buildTransform();}
|
||||
void setPosX(GLdouble o) {pos_.setX(o); buildTransform();}
|
||||
void setPosY(GLdouble o) {pos_.setY(o); buildTransform();}
|
||||
void setPosZ(GLdouble o) {pos_.setZ(o); buildTransform();}
|
||||
void setPos(GLdouble x, GLdouble y, GLdouble z) {pos_ = QVector3D(x, y, z); buildTransform();}
|
||||
void setPos(const QVector3D & p) {pos_ = p; buildTransform();}
|
||||
void resetPos() {pos_ = QVector3D(0., 0., 0.); buildTransform();}
|
||||
|
||||
QVector3D pos() const {return pos_;}
|
||||
double posX() const {return pos_.x();}
|
||||
double posY() const {return pos_.y();}
|
||||
double posZ() const {return pos_.z();}
|
||||
QVector3D worldPos() const {return (itransform_ * QVector4D(0, 0, 0, 1.)).toVector3D();}
|
||||
|
||||
void rotateX(GLdouble a) {angles_.setX(angles_.x() + a); buildTransform();}
|
||||
void rotateY(GLdouble a) {angles_.setY(angles_.y() + a); buildTransform();}
|
||||
void rotateZ(GLdouble a) {angles_.setZ(angles_.z() + a); while (angles_.z() < -360.) angles_.setZ(angles_.z() + 360.); while (angles_.z() > 360.) angles_.setZ(angles_.z() - 360.); buildTransform();}
|
||||
void setRotationX(GLdouble a) {angles_.setX(a); buildTransform();}
|
||||
void setRotationY(GLdouble a) {angles_.setY(a); buildTransform();}
|
||||
void setRotationZ(GLdouble a) {angles_.setZ(a); while (angles_.z() < -360.) angles_.setZ(angles_.z() + 360.); while (angles_.z() > 360.) angles_.setZ(angles_.z() - 360.); buildTransform();}
|
||||
void setRotation(const QVector3D & a) {angles_= a; buildTransform();}
|
||||
void resetRotation() {angles_ = QVector3D(0., 0., 0.); buildTransform();}
|
||||
|
||||
QVector3D rotation() const {return angles_;}
|
||||
double rotationX() const {return angles_.x();}
|
||||
double rotationY() const {return angles_.y();}
|
||||
double rotationZ() const {return angles_.z();}
|
||||
|
||||
QVector3D scale() {return scale_;}
|
||||
double scaleX() {return scale_.x();}
|
||||
double scaleY() {return scale_.y();}
|
||||
double scaleZ() {return scale_.z();}
|
||||
void scale(const QVector3D & sv) {scale_ *= sv; buildTransform();}
|
||||
void scale(GLdouble sx, GLdouble sy, GLdouble sz) {scale(QVector3D(sx, sy, sz)); buildTransform();}
|
||||
void scale(GLdouble sx, GLdouble sy) {scale(QVector3D(sx, sy, sy)); buildTransform();}
|
||||
void scale(GLdouble sx) {scale(QVector3D(sx, sx, sx)); buildTransform();}
|
||||
void scaleX(GLdouble a) {scale_.setX(scale_.x() + a); buildTransform();}
|
||||
void scaleY(GLdouble a) {scale_.setY(scale_.y() + a); buildTransform();}
|
||||
void scaleZ(GLdouble a) {scale_.setZ(scale_.z() + a); buildTransform();}
|
||||
void setScale(const QVector3D & a) {scale_ = a; buildTransform();}
|
||||
void setScale(GLdouble a) {scale_ = QVector3D(a, a, a); buildTransform();}
|
||||
void setScaleX(GLdouble a) {scale_.setX(a); buildTransform();}
|
||||
void setScaleY(GLdouble a) {scale_.setY(a); buildTransform();}
|
||||
void setScaleZ(GLdouble a) {scale_.setZ(a); buildTransform();}
|
||||
void resetScale() {scale_ = QVector3D(1., 1., 1.); buildTransform();}
|
||||
|
||||
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() const {return selected_;}
|
||||
void setSelected(bool yes) {selected_ = yes;}
|
||||
void select() {selected_ = true;}
|
||||
void deselect() {selected_ = false;}
|
||||
|
||||
bool isSelectable() const {return select_;}
|
||||
void setSelectable(bool yes) {select_ = yes;}
|
||||
/*
|
||||
bool isWriteDepth() const {return write_depth_;}
|
||||
void setWriteDepth(bool yes) {write_depth_ = yes;}*/
|
||||
|
||||
QColor color() const {return material_.color_diffuse;}
|
||||
void setColor(const QColor & c) {material_.color_diffuse = c; checkPass();}
|
||||
|
||||
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(const Material & m, bool with_children = false) {material_ = m; if (with_children) foreach (GLObjectBase * i, children_) i->setMaterial(m, true); checkPass(); is_tex_loaded = false;}
|
||||
Material & material() {/*is_tex_loaded = false;*/ return material_;}
|
||||
|
||||
const Box3D & boundingBox(bool withChildren = true) const {return bound;}
|
||||
GLVBO & VBO() {return vbo;}
|
||||
|
||||
QVector3D pos_h;
|
||||
QVector<Vector3d> points, puvws;
|
||||
QVector<Vector3i> faces, uvws;
|
||||
QVector<Vector3d> normals;
|
||||
|
||||
//QVector<GLfloat> d_vertices, d_normals, d_uvs;
|
||||
|
||||
protected:
|
||||
void addChildren(QList<GLObjectBase * > & list, GLObjectBase * where);
|
||||
void loadTextures(bool with_children = false) {material_.loadTextures((GLTextureManagerBase * )currentGLTextureManager); if (with_children) foreach (GLObjectBase * i, children_) i->loadTextures(); is_tex_loaded = true; checkPass();}
|
||||
void deleteTextures() {foreach (GLuint i, textures) currentQGLView->deleteTexture(i); textures.clear();}
|
||||
void calculateBoundingBox();
|
||||
void buildTransform();
|
||||
void initInternal() {init(); loadTextures(); foreach (GLObjectBase * i, children_) i->initInternal();}
|
||||
void render(int * id = 0, QMap<int, GLObjectBase * > * ids = 0, int sh_id_loc = 0);
|
||||
void checkPass();
|
||||
|
||||
int pass_; // Pass
|
||||
bool is_init, is_tex_loaded, accept_light, accept_fog, /*write_depth_,*/ visible_, cast_shadow, rec_shadow, select_, selected_;
|
||||
double line_width;
|
||||
Type type_;
|
||||
GeomPrimitives geom_prim;
|
||||
RenderMode render_mode;
|
||||
Material material_;
|
||||
Box3D bound;
|
||||
QVector3D pos_, angles_, scale_;
|
||||
QList<GLObjectBase * > children_;
|
||||
QList<GLuint> textures;
|
||||
QMatrix4x4 itransform_;
|
||||
//QColor color_;
|
||||
QString name_;
|
||||
GLenum blend_src, blend_dest;
|
||||
GLObjectBase * parent_;
|
||||
QGLViewBase * view_;
|
||||
GLVBO vbo;
|
||||
|
||||
};
|
||||
|
||||
inline bool operator <(const GLObjectBase & f, const GLObjectBase & s) {return f.pos_h.z() < s.pos_h.z();}
|
||||
|
||||
class Light: public GLObjectBase {
|
||||
friend class QGLView;
|
||||
friend class GLRendererBase;
|
||||
public:
|
||||
enum Type {Omni, Directional, Cone};
|
||||
|
||||
Light(): GLObjectBase(), shadow_map(true, 1, GL_R16F) {type_ = GLObjectBase::Light; light_type = Omni; intensity = 1.; decay_linear = decay_quadratic = angle_spread = angle_decay_exp = decay_start = 0.; decay_const = decay_end = 1.; direction.setZ(1.);}
|
||||
Light(const QVector3D & p, const QColor & c = Qt::white, GLdouble i = 1.): GLObjectBase(), shadow_map(true, 1, GL_R16F) {type_ = GLObjectBase::Light; light_type = Omni; pos_ = p; intensity = i; /*color_ = c;*/ decay_linear = decay_quadratic = angle_spread = angle_decay_exp = decay_start = 0.; decay_const = decay_end = 1.; direction.setZ(1.);}
|
||||
virtual GLObjectBase * clone(bool withChildren = true);
|
||||
virtual void init() {shadow_map.resize(512, 512); is_init = true;}
|
||||
virtual void draw(bool simplest = false);
|
||||
|
||||
QVector3D direction;
|
||||
GLdouble angle_spread;
|
||||
GLdouble angle_decay_exp;
|
||||
GLdouble intensity;
|
||||
GLdouble decay_const;
|
||||
GLdouble decay_linear;
|
||||
GLdouble decay_quadratic;
|
||||
GLdouble decay_start;
|
||||
GLdouble decay_end;
|
||||
Type light_type;
|
||||
|
||||
protected:
|
||||
GLFramebuffer shadow_map;
|
||||
QMatrix4x4 shadow_matrix;
|
||||
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline T globject_cast(GLObjectBase * object) {return reinterpret_cast<T>(object);}
|
||||
|
||||
template <class T>
|
||||
inline T globject_cast(const GLObjectBase * object) {return reinterpret_cast<T>(object);}
|
||||
|
||||
#endif // GLOBJECT_H
|
||||
119
qglview/globject_editor.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "globject_editor.h"
|
||||
|
||||
|
||||
GLObjectEditor::GLObjectEditor(QWidget * parent): QWidget(parent) {
|
||||
setupUi(this);
|
||||
active = true;
|
||||
object = 0;
|
||||
rmodes << GLObjectBase::View << GLObjectBase::Point << GLObjectBase::Line << GLObjectBase::Fill;
|
||||
groupLight->setEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
void GLObjectEditor::changeEvent(QEvent * e) {
|
||||
return;
|
||||
QWidget::changeEvent(e);
|
||||
switch (e->type()) {
|
||||
case QEvent::LanguageChange:
|
||||
retranslateUi(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GLObjectEditor::setObject(GLObjectBase * o) {
|
||||
object = o;
|
||||
if (object == 0) {
|
||||
groupLight->setEnabled(false);
|
||||
return;
|
||||
}
|
||||
active = false;
|
||||
spinPosX->setValue(object->posX());
|
||||
spinPosY->setValue(object->posY());
|
||||
spinPosZ->setValue(object->posZ());
|
||||
spinRotationX->setValue(object->rotationX());
|
||||
spinRotationY->setValue(object->rotationY());
|
||||
spinRotationZ->setValue(object->rotationZ());
|
||||
spinScaleX->setValue(object->scaleX());
|
||||
spinScaleY->setValue(object->scaleY());
|
||||
spinScaleZ->setValue(object->scaleZ());
|
||||
spinLineWidth->setValue(object->lineWidth());
|
||||
checkVisible->setChecked(object->isVisible());
|
||||
checkAcceptLight->setChecked(object->isAcceptLight());
|
||||
checkAcceptFog->setChecked(object->isAcceptFog());
|
||||
checkCastShadows->setChecked(object->isCastShadows());
|
||||
checkReceiveShadows->setChecked(object->isReceiveShadows());
|
||||
comboRenderMode->setCurrentIndex(rmodes.indexOf(object->renderMode()));
|
||||
groupLight->setEnabled(object->type() == GLObjectBase::Light);
|
||||
if (object->type() == GLObjectBase::Light) {
|
||||
Light * l = globject_cast<Light * >(object);
|
||||
//bool is_dir = l->light_type == Light::Directional, is_cone = l->light_type == Light::Cone;
|
||||
buttonLightColor->setColor(l->color());
|
||||
comboLightType->setCurrentIndex(l->light_type);
|
||||
spinLightIntensity->setValue(l->intensity);
|
||||
spinLightDecayConst->setValue(l->decay_const);
|
||||
spinLightDecayLinear->setValue(l->decay_linear);
|
||||
spinLightDecayQuadratic->setValue(l->decay_quadratic);
|
||||
spinLightAngleSpread->setValue(l->angle_spread);
|
||||
spinLightAngleDecayExp->setValue(l->angle_decay_exp);
|
||||
spinLightDirectionX->setValue(l->direction.x());
|
||||
spinLightDirectionY->setValue(l->direction.y());
|
||||
spinLightDirectionZ->setValue(l->direction.z());
|
||||
}
|
||||
active = true;
|
||||
}
|
||||
|
||||
|
||||
void GLObjectEditor::objectChanged() {
|
||||
if (!active || object == 0) return;
|
||||
object->setPosX(spinPosX->value());
|
||||
object->setPosY(spinPosY->value());
|
||||
object->setPosZ(spinPosZ->value());
|
||||
object->setRotationX(spinRotationX->value());
|
||||
object->setRotationY(spinRotationY->value());
|
||||
object->setRotationZ(spinRotationZ->value());
|
||||
object->setScaleX(spinScaleX->value());
|
||||
object->setScaleY(spinScaleY->value());
|
||||
object->setScaleZ(spinScaleZ->value());
|
||||
object->setLineWidth(spinLineWidth->value());
|
||||
object->setVisible(checkVisible->isChecked());
|
||||
object->setAcceptLight(checkAcceptLight->isChecked());
|
||||
object->setAcceptFog(checkAcceptFog->isChecked());
|
||||
object->setCastShadows(checkCastShadows->isChecked());
|
||||
object->setReceiveShadows(checkReceiveShadows->isChecked());
|
||||
object->setRenderMode((GLObjectBase::RenderMode)rmodes[comboRenderMode->currentIndex()]);
|
||||
if (object->type() == GLObjectBase::Light) {
|
||||
Light * l = globject_cast<Light * >(object);
|
||||
//bool is_dir = l->light_type == Light::Directional, is_cone = l->light_type == Light::Cone;
|
||||
l->setColor(buttonLightColor->color());
|
||||
l->light_type = (Light::Type)comboLightType->currentIndex();
|
||||
l->intensity = spinLightIntensity->value();
|
||||
l->decay_const = spinLightDecayConst->value();
|
||||
l->decay_linear = spinLightDecayLinear->value();
|
||||
l->decay_quadratic = spinLightDecayQuadratic->value();
|
||||
l->angle_spread = spinLightAngleSpread->value();
|
||||
l->angle_decay_exp = spinLightAngleDecayExp->value();
|
||||
l->direction = QVector3D(spinLightDirectionX->value(), spinLightDirectionY->value(), spinLightDirectionZ->value()).normalized();
|
||||
}
|
||||
emit changed();
|
||||
}
|
||||
48
qglview/globject_editor.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GLOBJECT_EDITOR_H
|
||||
#define GLOBJECT_EDITOR_H
|
||||
|
||||
#include "ui_globject_editor.h"
|
||||
#include "globject.h"
|
||||
|
||||
class GLObjectEditor: public QWidget, private Ui::GLObjectEditor
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GLObjectEditor(QWidget * parent = 0);
|
||||
|
||||
void setObject(GLObjectBase * o);
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent * e);
|
||||
|
||||
bool active;
|
||||
GLObjectBase * object;
|
||||
QList<GLenum> rmodes;
|
||||
|
||||
private slots:
|
||||
void objectChanged();
|
||||
|
||||
signals:
|
||||
void changed();
|
||||
|
||||
};
|
||||
|
||||
#endif // GLOBJECT_EDITOR_H
|
||||
1026
qglview/globject_editor.ui
Normal file
@@ -0,0 +1,1026 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>GLObjectEditor</class>
|
||||
<widget class="QWidget" name="GLObjectEditor">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>329</width>
|
||||
<height>681</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="formAlignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="horizontalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Position X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="spinPosX">
|
||||
<property name="minimum">
|
||||
<double>-99999.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Position Y</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="spinPosY">
|
||||
<property name="minimum">
|
||||
<double>-99999.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Position Z</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="spinPosZ">
|
||||
<property name="minimum">
|
||||
<double>-99999.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Rotation X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Rotation Y</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Rotation Z</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="SpinSlider" name="spinRotationX">
|
||||
<property name="minimum">
|
||||
<double>-180.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>180.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="SpinSlider" name="spinRotationY">
|
||||
<property name="minimum">
|
||||
<double>-180.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>180.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="SpinSlider" name="spinRotationZ">
|
||||
<property name="minimum">
|
||||
<double>-180.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>180.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Scale X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Scale Y</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Scale Z</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QDoubleSpinBox" name="spinScaleX">
|
||||
<property name="minimum">
|
||||
<double>-99999.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99999.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QDoubleSpinBox" name="spinScaleY">
|
||||
<property name="minimum">
|
||||
<double>-99999.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99999.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QDoubleSpinBox" name="spinScaleZ">
|
||||
<property name="minimum">
|
||||
<double>-99999.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99999.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Render mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QComboBox" name="comboRenderMode">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>View</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Point</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Line</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Fill</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QCheckBox" name="checkVisible">
|
||||
<property name="text">
|
||||
<string>Visible</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QCheckBox" name="checkAcceptLight">
|
||||
<property name="text">
|
||||
<string>Accept light</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QCheckBox" name="checkAcceptFog">
|
||||
<property name="text">
|
||||
<string>Accept fog</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Line width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="1">
|
||||
<widget class="QDoubleSpinBox" name="spinLineWidth">
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99999.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="1">
|
||||
<widget class="QCheckBox" name="checkCastShadows">
|
||||
<property name="text">
|
||||
<string>Cast shadows</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<widget class="QCheckBox" name="checkReceiveShadows">
|
||||
<property name="text">
|
||||
<string>Receive shadows</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupLight">
|
||||
<property name="title">
|
||||
<string>Light</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="formAlignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="horizontalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="ColorButton" name="buttonLightColor"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboLightType">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Omni</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Directional</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Cone</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Intensity</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="SpinSlider" name="spinLightIntensity">
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>128.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="squareScale">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Decay const</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="SpinSlider" name="spinLightDecayConst">
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>64.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="squareScale">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>Decay linear</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="SpinSlider" name="spinLightDecayLinear">
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>64.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="squareScale">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>Decay quadratic</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="SpinSlider" name="spinLightDecayQuadratic">
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>64.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="squareScale">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>Angle Spread</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="SpinSlider" name="spinLightAngleSpread">
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>90.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>45.000000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="squareScale">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string>Angle decay exp</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="SpinSlider" name="spinLightAngleDecayExp">
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>64.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="squareScale">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>Direcion X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="SpinSlider" name="spinLightDirectionX">
|
||||
<property name="minimum">
|
||||
<double>-1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>Direcion Y</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>Direcion Z</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="SpinSlider" name="spinLightDirectionY">
|
||||
<property name="minimum">
|
||||
<double>-1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="SpinSlider" name="spinLightDirectionZ">
|
||||
<property name="minimum">
|
||||
<double>-1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SpinSlider</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>spinslider.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ColorButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>colorbutton.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>spinPosX</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>312</x>
|
||||
<y>9</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>321</x>
|
||||
<y>5</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinPosY</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>307</x>
|
||||
<y>40</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>320</x>
|
||||
<y>36</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinPosZ</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>317</x>
|
||||
<y>73</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>321</x>
|
||||
<y>61</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinRotationX</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>97</x>
|
||||
<y>78</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>82</x>
|
||||
<y>73</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinRotationY</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>317</x>
|
||||
<y>123</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>320</x>
|
||||
<y>96</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinRotationZ</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>292</x>
|
||||
<y>128</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>321</x>
|
||||
<y>125</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinScaleX</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>295</x>
|
||||
<y>156</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>321</x>
|
||||
<y>150</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinScaleY</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>273</x>
|
||||
<y>177</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>321</x>
|
||||
<y>175</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinScaleZ</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>297</x>
|
||||
<y>202</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>321</x>
|
||||
<y>200</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>checkVisible</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>185</x>
|
||||
<y>268</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>76</x>
|
||||
<y>242</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>checkAcceptLight</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>104</x>
|
||||
<y>277</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>61</x>
|
||||
<y>261</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>checkAcceptFog</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>210</x>
|
||||
<y>314</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>79</x>
|
||||
<y>288</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>checkCastShadows</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>208</x>
|
||||
<y>337</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>55</x>
|
||||
<y>310</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>checkReceiveShadows</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>212</x>
|
||||
<y>360</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>78</x>
|
||||
<y>334</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinLineWidth</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>303</x>
|
||||
<y>366</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>321</x>
|
||||
<y>359</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>comboRenderMode</sender>
|
||||
<signal>currentIndexChanged(int)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>299</x>
|
||||
<y>228</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>321</x>
|
||||
<y>228</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonLightColor</sender>
|
||||
<signal>colorChanged(QColor)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>270</x>
|
||||
<y>423</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>320</x>
|
||||
<y>393</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>comboLightType</sender>
|
||||
<signal>currentIndexChanged(int)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>292</x>
|
||||
<y>447</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>320</x>
|
||||
<y>429</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinLightIntensity</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>255</x>
|
||||
<y>469</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>318</x>
|
||||
<y>463</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinLightDecayConst</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>303</x>
|
||||
<y>492</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>320</x>
|
||||
<y>489</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinLightDecayLinear</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>289</x>
|
||||
<y>511</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>318</x>
|
||||
<y>517</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinLightDecayQuadratic</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>299</x>
|
||||
<y>535</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>325</x>
|
||||
<y>543</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinLightAngleSpread</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>295</x>
|
||||
<y>559</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>321</x>
|
||||
<y>569</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinLightAngleDecayExp</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>301</x>
|
||||
<y>585</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>320</x>
|
||||
<y>595</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinLightDirectionX</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>302</x>
|
||||
<y>612</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>332</x>
|
||||
<y>607</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinLightDirectionY</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>313</x>
|
||||
<y>636</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>330</x>
|
||||
<y>633</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinLightDirectionZ</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>GLObjectEditor</receiver>
|
||||
<slot>objectChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>313</x>
|
||||
<y>654</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>326</x>
|
||||
<y>659</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<slots>
|
||||
<slot>objectChanged()</slot>
|
||||
</slots>
|
||||
</ui>
|
||||
198
qglview/glparticles_system.cpp
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "glparticles_system.h"
|
||||
|
||||
|
||||
GLParticlesSystem::GLParticlesSystem(const QVector3D & pos): GLObjectBase() {
|
||||
pass_ = GLObjectBase::Transparent;
|
||||
freq = 40.f;
|
||||
birthRate_ = 10.f;
|
||||
lifeDuration_ = 2.f;
|
||||
fade_time = 0.5f;
|
||||
size_ = 1.f;
|
||||
additionalSpeed = 0.f;
|
||||
initialSpeed_ = 1.f;
|
||||
need_birth = -1.f;
|
||||
tex_rect.setRect(0., 0., 1., 1.);
|
||||
tex_scale = QSizeF();
|
||||
emitterPosition_ = pos;
|
||||
emitterDirection_.setZ(1.);
|
||||
speedDirection_.setZ(1.);
|
||||
speedDecay_ = initialAngle_ = enlargeSpeed_ = enlargeSpeedJitter_ = baseAngle_ = 0.f;
|
||||
lifeDurationJitter_ = speedJitter_ = speedDirectionJitter_ = sizeJitter_ = angleJitter_ = 0.f;
|
||||
active_ = birthEnabled_ = true;
|
||||
is_diffuse_anim = add_vert_face = false;
|
||||
emitterType_ = Cone;
|
||||
tick_life = 1.f / freq;
|
||||
tick_birth = birthRate_ / freq;
|
||||
}
|
||||
|
||||
|
||||
void GLParticlesSystem::update() {
|
||||
if (!active_) return;
|
||||
//QMutexLocker locker(&mutex);
|
||||
Particle cp(lifeDuration_);
|
||||
if (birthEnabled_) need_birth += tick_birth;
|
||||
//qDebug() << "update" << particles.size();
|
||||
if (need_birth >= 1.f) {
|
||||
cp.pos = emitterPosition_;
|
||||
//qDebug() << "speed" << cp.speed;
|
||||
cp.speedDecay = 1.f + speedDecay_;
|
||||
for (int i = 0; i < floor(need_birth); ++i) {
|
||||
cp.lifeDuration = lifeDuration_ + urand(lifeDurationJitter_);
|
||||
switch (emitterType_) {
|
||||
case Omni:
|
||||
cp.speed = QVector3D(urand(), urand(), urand()).normalized() * initialSpeed_ * (1.f + urand(speedJitter_));
|
||||
break;
|
||||
case Cone: case Box:
|
||||
cp.speed = emitterDirection_ * initialSpeed_ * (1.f + urand(speedJitter_));
|
||||
cp.speed += orthToVector(cp.speed, speedDirectionJitter_);
|
||||
break;
|
||||
}
|
||||
if (emitterType_ == Box)
|
||||
cp.pos = emitterRect_.randomPoint();
|
||||
//qDebug() << "before" << cp.speed.length();
|
||||
lengthenVector(cp.speed, additionalSpeed);
|
||||
//qDebug() << "after" << cp.speed.length();
|
||||
cp.size = size_ + urand(sizeJitter_);
|
||||
cp.angle = initialAngle_ + urand(angleJitter_);
|
||||
cp.enlargeSpeed = (enlargeSpeed_ + urand(enlargeSpeedJitter_)) * tick_life;
|
||||
/*if (is_diffuse_anim) {
|
||||
if (material_.diffuse.animation_frame_rate < 0 && animation->bitmaps.size() > 0)
|
||||
cp.animationFrameRate = animation->bitmaps.size() / cp.lifeDuration;
|
||||
else
|
||||
cp.animationFrameRate = material_.diffuse.animation_frame_rate;
|
||||
}*/
|
||||
if (tex_scale.isEmpty()) cp.tex_rect.setSize(tex_rect.size());
|
||||
else cp.tex_rect.setSize(tex_rect.size() * tex_scale);
|
||||
cp.tex_rect.moveTopLeft(tex_rect.topLeft() + QPointF(uprand(tex_rect.width() - cp.tex_rect.width()), uprand(tex_rect.height() - cp.tex_rect.height())));
|
||||
//cp.tex_rect = tex_rect;
|
||||
particles.push_back(cp);
|
||||
}
|
||||
need_birth -= floor(need_birth);
|
||||
}
|
||||
for (int i = 0; i < particles.size(); ++i) {
|
||||
Particle & c(particles[i]);
|
||||
foreach (const QVector3D & f, forces)
|
||||
c.speed += f;
|
||||
c.lifeCurrent += tick_life;
|
||||
//qDebug() << "life" << c.lifeCurrent << c.lifeDuration;
|
||||
if (c.lifeCurrent > c.lifeDuration) {
|
||||
//qDebug() << "remove" << i;
|
||||
particles.remove(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
c.pos += c.speed * tick_life;
|
||||
c.speed /= c.speedDecay;
|
||||
c.size += c.enlargeSpeed;
|
||||
//if (c.lifeCurrent > 1.) c.angle += urand(5.);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GLParticlesSystem::draw(bool) {
|
||||
if (particles.isEmpty()) return;
|
||||
if (view_ == 0) return;
|
||||
pass_ = GLObjectBase::Transparent;
|
||||
Camera & camera(view_->camera());
|
||||
QVector3D apos = camera.pos(), dir = camera.direction();
|
||||
//qDebug() << dir;
|
||||
//qDebug() << camera.angles();
|
||||
//qDebug() << camera.angle_xy;
|
||||
GLfloat cxyc, czs, czc;
|
||||
GLfloat dx, dy, cdx, cdy, cdz, a, tr_r = material_.color_diffuse.redF(),
|
||||
tr_g = material_.color_diffuse.greenF(),
|
||||
tr_b = material_.color_diffuse.blueF(),
|
||||
tr_a = material_.color_diffuse.alphaF() * (1.f - material_.transparency);
|
||||
//cxys = sin(camera.angle_xy * deg2rad);
|
||||
cxyc = cos(camera.angle_xy * deg2rad);
|
||||
czs = sin(camera.angle_z * deg2rad);
|
||||
czc = cos(camera.angle_z * deg2rad);
|
||||
|
||||
dx = -czc;
|
||||
dy = czs;
|
||||
vertices.clear();
|
||||
texcoords.clear();
|
||||
colors.clear();
|
||||
for (int i = 0; i < particles.size(); ++i)
|
||||
//particles[i].pos_h.setZ((particles[i].pos - apos).lengthSquared());
|
||||
particles[i].pos_h.setZ(particles[i].pos.distanceToPlane(apos, dir));
|
||||
//qSort(particles.begin(), particles.end());
|
||||
foreach (const Particle & i, particles) {
|
||||
a = (i.lifeDuration - i.lifeCurrent) / fade_time;
|
||||
if (a > 1.f) a = 1.f;
|
||||
a *= tr_a;
|
||||
cdx = dx * i.size;
|
||||
cdy = dy * i.size;
|
||||
cdz = i.size;
|
||||
vertices << i.pos.x() - cdx << i.pos.y() - cdy << i.pos.z() - cdz;
|
||||
vertices << i.pos.x() - cdx << i.pos.y() - cdy << i.pos.z() + cdz;
|
||||
vertices << i.pos.x() + cdx << i.pos.y() + cdy << i.pos.z() + cdz;
|
||||
vertices << i.pos.x() + cdx << i.pos.y() + cdy << i.pos.z() - cdz;
|
||||
cdx = i.size;
|
||||
cdy = i.size;
|
||||
texcoords << i.tex_rect.right() << i.tex_rect.top();
|
||||
texcoords << i.tex_rect.right() << i.tex_rect.bottom();
|
||||
texcoords << i.tex_rect.left() << i.tex_rect.bottom();
|
||||
texcoords << i.tex_rect.left() << i.tex_rect.top();
|
||||
colors << tr_r << tr_g << tr_b << a;
|
||||
colors << tr_r << tr_g << tr_b << a;
|
||||
colors << tr_r << tr_g << tr_b << a;
|
||||
colors << tr_r << tr_g << tr_b << a;
|
||||
if (add_vert_face) {
|
||||
if (cxyc > 0.) {
|
||||
vertices << i.pos.x() - cdx << i.pos.y() - cdy << i.pos.z();
|
||||
vertices << i.pos.x() + cdx << i.pos.y() - cdy << i.pos.z();
|
||||
vertices << i.pos.x() + cdx << i.pos.y() + cdy << i.pos.z();
|
||||
vertices << i.pos.x() - cdx << i.pos.y() + cdy << i.pos.z();
|
||||
} else {
|
||||
vertices << i.pos.x() - cdx << i.pos.y() - cdy << i.pos.z();
|
||||
vertices << i.pos.x() - cdx << i.pos.y() + cdy << i.pos.z();
|
||||
vertices << i.pos.x() + cdx << i.pos.y() + cdy << i.pos.z();
|
||||
vertices << i.pos.x() + cdx << i.pos.y() - cdy << i.pos.z();
|
||||
}
|
||||
texcoords << i.tex_rect.right() << i.tex_rect.top();
|
||||
texcoords << i.tex_rect.right() << i.tex_rect.bottom();
|
||||
texcoords << i.tex_rect.left() << i.tex_rect.bottom();
|
||||
texcoords << i.tex_rect.left() << i.tex_rect.top();
|
||||
colors << tr_r << tr_g << tr_b << a;
|
||||
colors << tr_r << tr_g << tr_b << a;
|
||||
colors << tr_r << tr_g << tr_b << a;
|
||||
colors << tr_r << tr_g << tr_b << a;
|
||||
}
|
||||
}
|
||||
bool cae = glIsEnabled(GL_COLOR_ARRAY), nae = glIsEnabled(GL_NORMAL_ARRAY);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
//glNormal3f(vn.x(), vn.y(), vn.z());
|
||||
glNormal3f(0., 0., 1.);
|
||||
glDepthMask(false);
|
||||
glEnable(GL_COLOR_ARRAY);
|
||||
glDisable(GL_NORMAL_ARRAY);
|
||||
glVertexPointer(3, GL_FLOAT, 0, vertices.constData());
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, texcoords.constData());
|
||||
glColorPointer(4, GL_FLOAT, 0, colors.constData());
|
||||
//glEnable(GL_ALPHA_TEST);
|
||||
//glAlphaFunc();
|
||||
glDrawArrays(GL_QUADS, 0, vertices.size() / 3);
|
||||
glDepthMask(true);
|
||||
//glDisable(GL_ALPHA_TEST);
|
||||
if (!cae) glDisable(GL_COLOR_ARRAY);
|
||||
if (nae) glEnable(GL_NORMAL_ARRAY);
|
||||
}
|
||||
131
qglview/glparticles_system.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GLPARTICLES_SYSTEM_H
|
||||
#define GLPARTICLES_SYSTEM_H
|
||||
|
||||
#include <QMutex>
|
||||
#include "gltexture_manager.h"
|
||||
#include "globject.h"
|
||||
|
||||
class GLParticlesSystem: public GLObjectBase
|
||||
{
|
||||
public:
|
||||
GLParticlesSystem(const QVector3D & pos = QVector3D());
|
||||
~GLParticlesSystem() {;}
|
||||
|
||||
enum Type {Cone, Omni, Box};
|
||||
|
||||
struct Particle {
|
||||
Particle(float life_dur = 40.) {size = 1.; angle = lifeCurrent = 0.; speedDecay = 0.; lifeDuration = life_dur;}
|
||||
QVector3D pos;
|
||||
QVector3D pos_h;
|
||||
QVector3D speed;
|
||||
QRectF tex_rect;
|
||||
float speedDecay;
|
||||
float size;
|
||||
float angle;
|
||||
float enlargeSpeed;
|
||||
float lifeDuration;
|
||||
float lifeCurrent;
|
||||
float animationFrameRate;
|
||||
};
|
||||
|
||||
void update();
|
||||
void draw(bool);
|
||||
|
||||
float birthRate() const {return birthRate_;}
|
||||
float lifeDuration() const {return lifeDuration_;}
|
||||
float size() const {return size_;}
|
||||
float enlargeSpeed() const {return enlargeSpeed_;}
|
||||
float initialAngle() const {return initialAngle_;}
|
||||
float initialSpeed() const {return initialSpeed_;}
|
||||
float speedDecay() const {return speedDecay_;}
|
||||
float baseAngle() const {return baseAngle_;}
|
||||
QVector3D speedDirection() const {return speedDirection_;}
|
||||
QVector3D emitterPosition() const {return emitterPosition_;}
|
||||
QVector3D emitterDirection() const {return emitterDirection_;}
|
||||
Box3D emitterRect() const {return emitterRect_;}
|
||||
float lifeDurationJitter() const {return lifeDurationJitter_;}
|
||||
float speedJitter() const {return speedJitter_;}
|
||||
float speedDirectionJitter() const {return speedDirectionJitter_;}
|
||||
float sizeJitter() const {return sizeJitter_;}
|
||||
float enlargeSpeedJitter() const {return enlargeSpeedJitter_;}
|
||||
float angleJitter() const {return angleJitter_;}
|
||||
bool isActive() const {return active_;}
|
||||
bool isBirthEnabled() const {return birthEnabled_;}
|
||||
GLParticlesSystem::Type emitterType() const {return emitterType_;}
|
||||
float fadeTime() const {return fade_time;}
|
||||
bool isAddVerticalFaceEnabled() const {return add_vert_face;}
|
||||
|
||||
void setBirthRate(const float & arg) {birthRate_ = arg; tick_birth = birthRate_ / freq;}
|
||||
void setLifeDuration(const float & arg) {lifeDuration_ = arg;}
|
||||
void setSize(const float & arg) {size_ = arg;}
|
||||
void setEnlargeSpeed(const float & arg) {enlargeSpeed_ = arg;}
|
||||
void setInitialAngle(const float & arg) {initialAngle_ = arg;}
|
||||
void setInitialSpeed(const float & arg) {initialSpeed_ = arg;}
|
||||
void setBaseAngle(const float & arg) {baseAngle_ = arg;}
|
||||
void setSpeedDecay(const float & arg) {speedDecay_ = arg;}
|
||||
void setSpeedDirection(const QVector3D & arg) {speedDirection_ = arg;}
|
||||
void setEmitterPosition(const QVector3D & arg) {emitterPosition_ = arg;}
|
||||
void setEmitterDirection(const QVector3D & arg) {emitterDirection_ = arg.normalized();}
|
||||
void setEmitterRect(const Box3D & arg) {emitterRect_ = arg;}
|
||||
void setLifeDurationJitter(const float & arg) {lifeDurationJitter_ = arg;}
|
||||
void setSpeedJitter(const float & arg) {speedJitter_ = arg;}
|
||||
void setSpeedDirectionJitter(const float & arg) {speedDirectionJitter_ = arg;}
|
||||
void setSizeJitter(const float & arg) {sizeJitter_ = arg;}
|
||||
void setEnlargeSpeedJitter(const float & arg) {enlargeSpeedJitter_ = arg;}
|
||||
void setActive(const bool & arg) {active_ = arg;}
|
||||
void setAngleJitter(const float & arg) {angleJitter_ = arg;}
|
||||
void setBirthEnabled(const bool & arg) {birthEnabled_ = arg;}
|
||||
void setEmitterType(const GLParticlesSystem::Type & arg) {emitterType_ = arg;}
|
||||
void setFadeTime(const float & arg) {fade_time = arg;}
|
||||
void setAddVerticalFaceEnabled(const bool & arg) {add_vert_face = arg;}
|
||||
void setTextureRect(const QRectF & arg) {tex_rect = arg;}
|
||||
void setTextureScale(const float & x, const float & y) {tex_scale = QSizeF(x, y);}
|
||||
void setTextureScale(const QSizeF & arg) {tex_scale = arg;}
|
||||
|
||||
void addForce(const QVector3D & f) {forces << f;}
|
||||
void birthParticles(int count) {need_birth += count;}
|
||||
|
||||
float frequency() const {return freq;}
|
||||
void setFrequency(const float & f) {freq = f;}
|
||||
|
||||
float additionalSpeed;
|
||||
|
||||
private:
|
||||
QVector3D speedDirection_, emitterPosition_, emitterDirection_;
|
||||
QRectF tex_rect;
|
||||
QSizeF tex_scale;
|
||||
Box3D emitterRect_;
|
||||
QMutex mutex;
|
||||
GLParticlesSystem::Type emitterType_;
|
||||
GLTextureManager::Animation * animation;
|
||||
QVector<GLfloat> vertices, texcoords, colors;
|
||||
QVector<Particle> particles;
|
||||
QVector<QVector3D> forces;
|
||||
float birthRate_, initialSpeed_, speedDecay_, lifeDuration_, size_, freq, need_birth, tick_birth, tick_life, fade_time;
|
||||
float lifeDurationJitter_, speedJitter_, speedDirectionJitter_, sizeJitter_, angleJitter_, initialAngle_;
|
||||
float enlargeSpeed_, enlargeSpeedJitter_, baseAngle_;
|
||||
bool active_, birthEnabled_, is_diffuse_anim, add_vert_face;
|
||||
|
||||
};
|
||||
|
||||
inline bool operator <(const GLParticlesSystem::Particle & f, const GLParticlesSystem::Particle & s) {return f.pos_h.z() > s.pos_h.z();}
|
||||
|
||||
#endif // GLPARTICLES_SYSTEM_H
|
||||
103
qglview/glprimitives.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "glprimitives.h"
|
||||
|
||||
|
||||
void GLPrimitivePoint::draw(bool simplest) {
|
||||
glPointSize(sz);
|
||||
glColor3f(material_.color_diffuse.redF(), material_.color_diffuse.greenF(), material_.color_diffuse.blueF());
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3d(0., 0., 0.);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
|
||||
GLPrimitiveCube::GLPrimitiveCube(double width, double length, double height, QVector3D pos): GLObjectBase() {
|
||||
geom_prim = Quads;
|
||||
w = width;
|
||||
l = length;
|
||||
h = height;
|
||||
moveTo(pos);
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
void GLPrimitiveCube::init() {
|
||||
double hw = w / 2., hl = l / 2., hh = h / 2.;
|
||||
//list = glGenLists(1);
|
||||
//glNewList(list, GL_COMPILE);
|
||||
//glColor4d(material_.color_diffuse.redF(), material_.color_diffuse.greenF(), material_.color_diffuse.blueF(), material_.color_diffuse.alphaF());
|
||||
vbo.init();
|
||||
QVector<GLfloat> & d_vertices(vbo.vertices()), & d_normals(vbo.normals()), & d_uvs(vbo.texcoords());
|
||||
d_vertices.clear();
|
||||
d_normals.clear();
|
||||
d_uvs.clear();
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
d_normals << 0. << -1. << 0.;
|
||||
d_vertices << -hw << -hl << -hh;
|
||||
d_vertices << hw << -hl << -hh;
|
||||
d_vertices << hw << -hl << hh;
|
||||
d_vertices << -hw << -hl << hh;
|
||||
d_uvs << 0. << 0. << 1. << 0. << 1. << 1. << 0. << 1.;
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
d_normals << 0. << 1. << 0.;
|
||||
d_vertices << -hw << hl << -hh;
|
||||
d_vertices << -hw << hl << hh;
|
||||
d_vertices << hw << hl << hh;
|
||||
d_vertices << hw << hl << -hh;
|
||||
d_uvs << 0. << 0. << 1. << 0. << 1. << 1. << 0. << 1.;
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
d_normals << -1. << 0. << 0.;
|
||||
d_vertices << -hw << -hl << -hh;
|
||||
d_vertices << -hw << -hl << hh;
|
||||
d_vertices << -hw << hl << hh;
|
||||
d_vertices << -hw << hl << -hh;
|
||||
d_uvs << 0. << 0. << 1. << 0. << 1. << 1. << 0. << 1.;
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
d_normals << 1. << 0. << 0.;
|
||||
d_vertices << hw << -hl << -hh;
|
||||
d_vertices << hw << hl << -hh;
|
||||
d_vertices << hw << hl << hh;
|
||||
d_vertices << hw << -hl << hh;
|
||||
d_uvs << 0. << 0. << 1. << 0. << 1. << 1. << 0. << 1.;
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
d_normals << 0. << 0. << -1.;
|
||||
d_vertices << -hw << -hl << -hh;
|
||||
d_vertices << -hw << hl << -hh;
|
||||
d_vertices << hw << hl << -hh;
|
||||
d_vertices << hw << -hl << -hh;
|
||||
d_uvs << 0. << 0. << 1. << 0. << 1. << 1. << 0. << 1.;
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
d_normals << 0. << 0. << 1.;
|
||||
d_vertices << -hw << -hl << hh;
|
||||
d_vertices << hw << -hl << hh;
|
||||
d_vertices << hw << hl << hh;
|
||||
d_vertices << -hw << hl << hh;
|
||||
d_uvs << 0. << 0. << 1. << 0. << 1. << 1. << 0. << 1.;
|
||||
|
||||
is_init = true;
|
||||
vbo.rebuffer();
|
||||
}
|
||||
42
qglview/glprimitives.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GLPRIMITIVE_CUBE_H
|
||||
#define GLPRIMITIVE_CUBE_H
|
||||
|
||||
#include "globject.h"
|
||||
|
||||
class GLPrimitivePoint: public GLObjectBase
|
||||
{
|
||||
public:
|
||||
GLPrimitivePoint(double size = 1., QVector3D pos = QVector3D()) {sz = 8.;}
|
||||
virtual void draw(bool simplest = false);
|
||||
private:
|
||||
double sz;
|
||||
};
|
||||
|
||||
class GLPrimitiveCube: public GLObjectBase
|
||||
{
|
||||
public:
|
||||
GLPrimitiveCube(double width = 1., double length = 1., double height = 1., QVector3D pos = QVector3D());
|
||||
virtual void init();
|
||||
private:
|
||||
double w, l, h;
|
||||
};
|
||||
|
||||
#endif // GLPRIMITIVE_CUBE_H
|
||||
54
qglview/gltexture_manager.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "gltexture_manager.h"
|
||||
|
||||
|
||||
bool GLTextureManager::loadTextures() {
|
||||
//glGenTextures();
|
||||
QFileInfoList fil;
|
||||
Animation anim;
|
||||
for (int i = 0; i < anim_pathes.size(); ++i) {
|
||||
anim.path = anim_pathes[i].second;
|
||||
anim.bitmaps.clear();
|
||||
fil = QDir(anim_pathes[i].first).entryInfoList(QDir::Files, QDir::Name);
|
||||
foreach (const QFileInfo & fi, fil) {
|
||||
if (fi.baseName().indexOf(anim_pathes[i].second) < 0) continue;
|
||||
anim.bitmaps << loadTexture(fi.filePath(), false);
|
||||
}
|
||||
qDebug() << "[TextureManager] Loaded" << anim.bitmaps.size() << "frames";
|
||||
anim_ids << QPair<QString, Animation>(anim_pathes[i].second, anim);
|
||||
}
|
||||
anim_pathes.clear();
|
||||
foreach (const QString & i, tex_pathes)
|
||||
loadTexture(i, true);
|
||||
tex_pathes.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void GLTextureManager::deleteTextures() {
|
||||
QList<GLuint> texs = tex_ids.values();
|
||||
qDebug() << "[TextureManager] Delete" << texs.size() << "textures";
|
||||
if (!texs.isEmpty()) glDeleteTextures(texs.size(), &texs[0]);
|
||||
tex_ids.clear();
|
||||
qDebug() << "[TextureManager] Delete" << anim_ids.size() << "animations";
|
||||
for (int i = 0; i < anim_ids.size(); ++i)
|
||||
glDeleteTextures(anim_ids[i].second.bitmaps.size(), anim_ids[i].second.bitmaps.data());
|
||||
anim_ids.clear();
|
||||
}
|
||||
53
qglview/gltexture_manager.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GLTEXTUREMANAGER_H
|
||||
#define GLTEXTUREMANAGER_H
|
||||
|
||||
#include "gltypes.h"
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
|
||||
class GLTextureManager: public GLTextureManagerBase
|
||||
{
|
||||
public:
|
||||
GLTextureManager() {;}
|
||||
~GLTextureManager() {deleteTextures();}
|
||||
|
||||
struct Animation {
|
||||
QString path;
|
||||
QVector<GLuint> bitmaps;
|
||||
GLuint bitmapID(const int frame) {if (frame < 0 || frame >= bitmaps.size()) return 0; return bitmaps[frame];}
|
||||
};
|
||||
|
||||
void addTexture(const QString & path) {tex_pathes << path;}
|
||||
void addAnimation(const QString & dir, const QString & name) {anim_pathes << QPair<QString, QString>(dir, name);}
|
||||
bool loadTextures();
|
||||
void deleteTextures();
|
||||
void deleteTexture(const QString & name) {if (tex_ids.contains(name)) {glDeleteTextures(1, &tex_ids[name]); tex_ids.remove(name);}}
|
||||
Animation * findAnimation(const QString & name) {for (int i = 0; i < anim_ids.size(); ++i) if (anim_ids[i].first == name) return &(anim_ids[i].second); return 0;}
|
||||
|
||||
QVector<QPair<QString, Animation> > anim_ids;
|
||||
|
||||
private:
|
||||
QList<QString> tex_pathes;
|
||||
QList<QPair<QString, QString> > anim_pathes;
|
||||
|
||||
};
|
||||
|
||||
#endif // GLTEXTUREMANAGER_H
|
||||
746
qglview/gltypes.cpp
Normal file
@@ -0,0 +1,746 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "gltypes.h"
|
||||
#include "qglview.h"
|
||||
|
||||
QGLWidget * currentQGLView;
|
||||
GLTextureManager * currentGLTextureManager;
|
||||
Camera * currentCamera;
|
||||
QMatrix4x4 globCameraMatrix;
|
||||
QMutex globMutex;
|
||||
|
||||
|
||||
QString readCharsUntilNull(QDataStream & s) {
|
||||
QString str;
|
||||
char ch;
|
||||
s.readRawData(&ch, 1);
|
||||
while (ch != '\0') {
|
||||
str += ch;
|
||||
s.readRawData(&ch, 1);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
void glDrawQuad(GLfloat x, GLfloat y, GLfloat w, GLfloat h) {
|
||||
glResetAllTransforms();
|
||||
glSetPolygonMode(GL_FILL);
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(1.f, 1.f, 1.f);
|
||||
glTexCoord2f(0.f, 0.f); glVertex2f(x, y);
|
||||
glTexCoord2f(1.f, 0.f); glVertex2f(x + w, y);
|
||||
glTexCoord2f(1.f, 1.f); glVertex2f(x + w, y + h);
|
||||
glTexCoord2f(0.f, 1.f); glVertex2f(x, y + h);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
QMatrix4x4 getGLMatrix(GLenum matrix) {
|
||||
GLfloat gm[16];
|
||||
glGetFloatv(matrix, gm);
|
||||
qreal qm[16];
|
||||
for (int i = 0; i < 16; ++i)
|
||||
qm[i] = gm[i];
|
||||
return QMatrix4x4(qm, 4, 4).transposed();
|
||||
}
|
||||
|
||||
|
||||
void createGLTexture(GLuint & tex, int width, int height, const GLenum & format, const GLenum & target) {
|
||||
glClearError();
|
||||
if (tex == 0) {
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(target, tex);
|
||||
}
|
||||
//glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_COMPONENT16 || format == GL_DEPTH_COMPONENT24 || format == GL_DEPTH_COMPONENT32)
|
||||
glTexImage2D(target, 0, format, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
|
||||
else
|
||||
glTexImage2D(target, 0, format, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
//qDebug() << QString::number(glGetError(), 16);
|
||||
}
|
||||
|
||||
|
||||
void createGLTexture(GLuint & tex, const QImage & image, const GLenum & format, const GLenum & target) {
|
||||
if (tex == 0) {
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(target, tex);
|
||||
}
|
||||
QImage im = QGLWidget::convertToGLFormat(image);
|
||||
//const QImage & cim(im);
|
||||
//glClearError();
|
||||
//glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D || target == GL_TEXTURE_3D) {
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT);
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
||||
}
|
||||
glTexImage2D(target, 0, format, im.width(), im.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, im.bits());
|
||||
//qDebug() << tex << im.width() << im.height() << im.bits() << glGetError();
|
||||
}
|
||||
|
||||
|
||||
bool loadShaders(QGLShaderProgram * prog, const QString & name, const QString & dir) {
|
||||
prog->removeAllShaders();
|
||||
QDir d(dir);
|
||||
QFileInfoList sl = d.entryInfoList(QStringList(name + ".geom"), QDir::Files | QDir::NoDotAndDotDot);
|
||||
#if QT_VERSION >= 0x040700
|
||||
foreach (const QFileInfo & i, sl)
|
||||
prog->addShaderFromSourceFile(QGLShader::Geometry, i.absoluteFilePath());
|
||||
#endif
|
||||
sl = d.entryInfoList(QStringList(name + ".vert"), QDir::Files | QDir::NoDotAndDotDot);
|
||||
foreach (const QFileInfo & i, sl)
|
||||
prog->addShaderFromSourceFile(QGLShader::Vertex, i.absoluteFilePath());
|
||||
sl = d.entryInfoList(QStringList(name + ".frag"), QDir::Files | QDir::NoDotAndDotDot);
|
||||
foreach (const QFileInfo & i, sl)
|
||||
prog->addShaderFromSourceFile(QGLShader::Fragment, i.absoluteFilePath());
|
||||
if (!prog->link()) {
|
||||
qDebug() << "[QGLView] Shader \"" + name + "\" link error: " + prog->log();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
QImage rotateQImageLeft(const QImage & im) {
|
||||
QImage ri(im.height(), im.width(), im.format());
|
||||
QPainter p(&ri);
|
||||
p.rotate(90);
|
||||
p.drawImage(0, -im.height(), im);
|
||||
p.end();
|
||||
return ri;
|
||||
}
|
||||
|
||||
|
||||
QImage rotateQImageRight(const QImage & im) {
|
||||
QImage ri(im.height(), im.width(), im.format());
|
||||
QPainter p(&ri);
|
||||
p.rotate(-90);
|
||||
p.drawImage(-im.width(), 0, im);
|
||||
p.end();
|
||||
return ri;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool GLCubeTexture::create() {
|
||||
//qDebug("create");
|
||||
destroy();
|
||||
glGenTextures(1, &id_);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, id_);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR/*_MIPMAP_LINEAR*/);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
//glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
||||
//glClearError();
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
//qDebug() << glGetError();
|
||||
changed_ = false;
|
||||
return id_ > 0;
|
||||
}
|
||||
|
||||
|
||||
void GLCubeTexture::load() {
|
||||
if (isEmpty()) return;
|
||||
create();
|
||||
if (!path(0).isEmpty()) loadFront(path(0));
|
||||
if (!path(1).isEmpty()) loadBack(path(1));
|
||||
if (!path(2).isEmpty()) loadLeft(path(2));
|
||||
if (!path(3).isEmpty()) loadRight(path(3));
|
||||
if (!path(4).isEmpty()) loadTop(path(4));
|
||||
if (!path(5).isEmpty()) loadBottom(path(5));
|
||||
}
|
||||
|
||||
|
||||
void GLCubeTexture::loadFromDirectory(const QString & dir) {
|
||||
QDir d(dir); QFileInfoList sl;
|
||||
sl = d.entryInfoList(QStringList("front.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadFront(sl[0].absoluteFilePath());
|
||||
sl = d.entryInfoList(QStringList("back.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadBack(sl[0].absoluteFilePath());
|
||||
sl = d.entryInfoList(QStringList("left.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadLeft(sl[0].absoluteFilePath());
|
||||
sl = d.entryInfoList(QStringList("right.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadRight(sl[0].absoluteFilePath());
|
||||
sl = d.entryInfoList(QStringList("top.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadTop(sl[0].absoluteFilePath());
|
||||
sl = d.entryInfoList(QStringList("bottom.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadBottom(sl[0].absoluteFilePath());
|
||||
}
|
||||
|
||||
|
||||
void GLCubeTexture::loadPathesFromDirectory(const QString & dir) {
|
||||
QDir d(dir); QFileInfoList sl;
|
||||
sl = d.entryInfoList(QStringList("front.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[0] = sl[0].absoluteFilePath();
|
||||
sl = d.entryInfoList(QStringList("back.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[1] = sl[0].absoluteFilePath();
|
||||
sl = d.entryInfoList(QStringList("left.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[2] = sl[0].absoluteFilePath();
|
||||
sl = d.entryInfoList(QStringList("right.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[3] = sl[0].absoluteFilePath();
|
||||
sl = d.entryInfoList(QStringList("top.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[4] = sl[0].absoluteFilePath();
|
||||
sl = d.entryInfoList(QStringList("bottom.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[5] = sl[0].absoluteFilePath();
|
||||
}
|
||||
|
||||
|
||||
|
||||
GLuint GLTextureManagerBase::loadTexture(const QString & path, bool ownership) {
|
||||
int tid = ((GLTextureManagerBase*)currentGLTextureManager)->textureID(path);
|
||||
if (tid > 0) {
|
||||
//qDebug() << "[TextureManager] Found" << path << "as" << tid;
|
||||
return tid;
|
||||
}
|
||||
tid = currentQGLView->bindTexture(QImage(path), GL_TEXTURE_2D/*, GL_RGBA, QGLContext::MipmapBindOption*/);
|
||||
if (tid == 0) {
|
||||
qDebug() << "[TextureManager] Can`t load" << path;
|
||||
return tid;
|
||||
}
|
||||
qDebug() << "[TextureManager] Loaded" << path << "as" << tid;
|
||||
if (ownership) ((GLTextureManagerBase*)currentGLTextureManager)->tex_ids.insert(path, tid);
|
||||
/*GLenum err(0);
|
||||
im = currentQGLView->convertToGLFormat(im);
|
||||
glClearError();
|
||||
glGenTextures(1, &tid);
|
||||
err = glGetError();
|
||||
if (err != GL_NO_ERROR) {
|
||||
qDebug() << "can`t generate texture," << err;
|
||||
return false;
|
||||
}
|
||||
//glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
|
||||
glClearError();
|
||||
glBindTexture(GL_TEXTURE_2D, tid);
|
||||
qDebug() << "load" << im.width() << "x" << im.height();
|
||||
glClearError();
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, im.width(), im.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, im.bits());
|
||||
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
//glBindTexture(GL_TEXTURE_2D, 0);
|
||||
err = glGetError();
|
||||
if (err != GL_NO_ERROR) {
|
||||
glDeleteTextures(1, &tid);
|
||||
qDebug() << "can`t load" << path << "," << err;
|
||||
return false;
|
||||
}
|
||||
currentGLTextureManager->tex_ids << tid;
|
||||
qDebug() << "loaded" << path << "as" << tid;*/
|
||||
return tid;
|
||||
}
|
||||
|
||||
|
||||
GLuint GLTextureManagerBase::loadTexture(const QImage & image, bool ownership) {
|
||||
GLuint tid = currentQGLView->bindTexture(image);
|
||||
if (tid == 0) {
|
||||
qDebug() << "[TextureManager] Can`t load image";
|
||||
return tid;
|
||||
}
|
||||
//qDebug() << "[TextureManager] Loaded image as" << tid;
|
||||
if (ownership) ((GLTextureManagerBase*)currentGLTextureManager)->tex_ids.insert(QString(), tid);
|
||||
return tid;
|
||||
}
|
||||
|
||||
|
||||
void Camera::anglesFromPoints() {
|
||||
QVector3D dv = aim_ - pos_, tv;
|
||||
tv = QVector3D(dv.x(), dv.y(), 0.);
|
||||
angle_z = atan2(tv.x(), tv.y()) * rad2deg;
|
||||
angle_xy = piClamp<GLdouble>(atan2(tv.length(), dv.z()) * rad2deg + 180., angle_limit_lower_xy, angle_limit_upper_xy);
|
||||
}
|
||||
|
||||
|
||||
void Camera::apply(const GLdouble & aspect) {
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
if (aspect <= 1.)
|
||||
glScaled(aspect, aspect, 1.);
|
||||
gluPerspective(fov_, aspect, depth_start, depth_end);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslated(0., 0., -distance());
|
||||
glRotated(angle_xy, 1., 0., 0.);
|
||||
glRotated(angle_roll, 0., -1., 0.);
|
||||
glRotated(angle_z, 0., 0., 1.);
|
||||
//glTranslated(pos_.x(), pos_.y(), pos_.z());
|
||||
//if (mirror_y) glScalef(1,-1,-1);
|
||||
//if (mirror_x) glScalef(-1,1,-1);
|
||||
//glScalef(-1,-1,1);
|
||||
glTranslated(-aim_.x(), -aim_.y(), -aim_.z());
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
glGetDoublev(GL_PROJECTION_MATRIX, projection);
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
|
||||
//qDebug() << "viewport" << viewport[0] << viewport[1] << viewport[2] << viewport[3];
|
||||
}
|
||||
|
||||
|
||||
void Camera::panZ(const double & a) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = QVector2D(dv.x(), dv.y()).length();
|
||||
angle_z += a;
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl, cos(angle_z * deg2rad) * tl, dv.z());
|
||||
aim_ = pos_ + dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::panXY(const double & a) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = dv.length(), tc;
|
||||
angle_xy += a;
|
||||
angle_xy = piClamp<GLdouble>(angle_xy, angle_limit_lower_xy, angle_limit_upper_xy);
|
||||
tc = -sin(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl * tc, cos(angle_z * deg2rad) * tl * tc, -cos(angle_xy * deg2rad) * tl);
|
||||
aim_ = pos_ + dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::rotateZ(const double & a) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = QVector2D(dv.x(), dv.y()).length();
|
||||
angle_z += a;
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl, cos(angle_z * deg2rad) * tl, dv.z());
|
||||
aim_ = pos_ + dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::rotateXY(const double & a) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = dv.length(), tc;
|
||||
angle_xy += a;
|
||||
angle_xy = piClamp<GLdouble>(angle_xy, angle_limit_lower_xy, angle_limit_upper_xy);
|
||||
tc = -sin(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl * tc, cos(angle_z * deg2rad) * tl * tc, -cos(angle_xy * deg2rad) * tl);
|
||||
aim_ = pos_ + dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::orbitZ(const double & a) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = QVector2D(dv.x(), dv.y()).length();
|
||||
angle_z += a;
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl, cos(angle_z * deg2rad) * tl, dv.z());
|
||||
pos_ = aim_ - dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::orbitXY(const double & a) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = dv.length(), tc;
|
||||
angle_xy += a;
|
||||
angle_xy = piClamp<GLdouble>(angle_xy, angle_limit_lower_xy, angle_limit_upper_xy);
|
||||
tc = -sin(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl * tc, cos(angle_z * deg2rad) * tl * tc, -cos(angle_xy * deg2rad) * tl);
|
||||
pos_ = aim_ - dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::setAngleZ(const double & a) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = QVector2D(dv.x(), dv.y()).length();
|
||||
angle_z = a;
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl, cos(angle_z * deg2rad) * tl, dv.z());
|
||||
aim_ = pos_ + dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::setAngleXY(const double & a) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = dv.length(), tc;
|
||||
angle_xy = a;
|
||||
tc = -sin(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl * tc, cos(angle_z * deg2rad) * tl * tc, -cos(angle_xy * deg2rad) * tl);
|
||||
//pos_ = aim_ - dv;
|
||||
aim_ = pos_ + dv;
|
||||
//anglesFromPoints();
|
||||
}
|
||||
|
||||
|
||||
void Camera::moveForward(const double & x, bool withZ) {
|
||||
QVector3D dv;// = aim_ - pos_;
|
||||
double tc = -sin(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tc, cos(angle_z * deg2rad) * tc, 0.);
|
||||
if (withZ) dv.setZ(-cos(angle_xy * deg2rad));
|
||||
dv.normalize();
|
||||
dv *= x;
|
||||
pos_ += dv;
|
||||
aim_ += dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::moveLeft(const double & x, bool withZ) {
|
||||
QVector3D dv;// = aim_ - pos_;
|
||||
double tc = -sin(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad - M_PI_2) * tc, cos(angle_z * deg2rad - M_PI_2) * tc, 0.);
|
||||
if (withZ) dv.setZ(-sin(angle_roll * deg2rad));
|
||||
dv.normalize();
|
||||
dv *= x;
|
||||
pos_ += dv;
|
||||
aim_ += dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::moveUp(const double & x, bool onlyZ) {
|
||||
QVector3D dv;
|
||||
if (onlyZ)
|
||||
dv = QVector3D(0., 0., x);
|
||||
else {
|
||||
double tc = cos(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tc, cos(angle_z * deg2rad) * tc, -sin(angle_xy * deg2rad));
|
||||
dv.normalize();
|
||||
dv *= x;
|
||||
}
|
||||
pos_ += dv;
|
||||
aim_ += dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::flyCloser(const double & s) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = dv.length() / (1. + s), tc = -sin(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl * tc, cos(angle_z * deg2rad) * tl * tc, -cos(angle_xy * deg2rad) * tl);
|
||||
pos_ = aim_ - dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::flyFarer(const double & s) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = dv.length() * (1. + s), tc = -sin(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl * tc, cos(angle_z * deg2rad) * tl * tc, -cos(angle_xy * deg2rad) * tl);
|
||||
pos_ = aim_ - dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::flyToDistance(const double & d) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tc = -sin(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * d * tc, cos(angle_z * deg2rad) * d * tc, -cos(angle_xy * deg2rad) * d);
|
||||
pos_ = aim_ - dv;
|
||||
}
|
||||
|
||||
|
||||
QVector3D Camera::pointFromViewport(int x_, int y_, double z_) {
|
||||
GLsizei mx = x_, my = viewport[3] - y_, mz = z_;
|
||||
GLdouble x,y,z;
|
||||
gluUnProject(mx, my, mz, modelview, projection, viewport, &x, &y, &z);
|
||||
return QVector3D(x,y,z);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Material::Material(): reflection(512) {
|
||||
color_diffuse = color_specular = Qt::white;
|
||||
color_self_illumination = Qt::black;
|
||||
glass = false;
|
||||
transparency = reflectivity = 0.f;
|
||||
bump_scale = relief_scale = iof = 1.f;
|
||||
dispersion = 0.05f;
|
||||
shine = shine_strength = 0.f;
|
||||
light_model = Phong;
|
||||
}
|
||||
|
||||
|
||||
void Material::apply() {
|
||||
GLfloat mat_diffuse[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
GLfloat mat_specular[4] = {0.9f, 0.9f, 0.9f, 1.0f};
|
||||
GLfloat mat_emission[4] = {0.f, 0.f, 0.f, 1.0f};
|
||||
mat_diffuse[0] = color_diffuse.redF();
|
||||
mat_diffuse[1] = color_diffuse.greenF();
|
||||
mat_diffuse[2] = color_diffuse.blueF();
|
||||
mat_diffuse[3] = color_diffuse.alphaF() * (1.f - transparency);
|
||||
mat_specular[0] = shine_strength * color_specular.redF();
|
||||
mat_specular[1] = shine_strength * color_specular.greenF();
|
||||
mat_specular[2] = shine_strength * color_specular.blueF();
|
||||
mat_emission[0] = color_self_illumination.redF();
|
||||
mat_emission[1] = color_self_illumination.greenF();
|
||||
mat_emission[2] = color_self_illumination.blueF();
|
||||
glColor4f(mat_diffuse[0], mat_diffuse[1], mat_diffuse[2], mat_diffuse[3]);
|
||||
//qDebug() << color_diffuse.alphaF() * (1.f - transparency);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, shine);
|
||||
glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_diffuse);
|
||||
}
|
||||
|
||||
|
||||
void Material::loadTextures(GLTextureManagerBase * tm) {
|
||||
if (tm == 0) tm = (GLTextureManagerBase*)currentGLTextureManager;
|
||||
if (!diffuse.bitmap_path.isEmpty()) diffuse.bitmap_id = tm->loadTexture(diffuse.bitmap_path);
|
||||
if (!bump.bitmap_path.isEmpty()) bump.bitmap_id = tm->loadTexture(bump.bitmap_path);
|
||||
if (!relief.bitmap_path.isEmpty()) relief.bitmap_id = tm->loadTexture(relief.bitmap_path);
|
||||
if (!diffuse_2.bitmap_path.isEmpty()) diffuse_2.bitmap_id = tm->loadTexture(diffuse_2.bitmap_path);
|
||||
//qDebug() << "load" << reflection.path(0);
|
||||
reflection.load();
|
||||
}
|
||||
|
||||
|
||||
QColor colorFromString(const QString & str) {
|
||||
QString s = str.trimmed();
|
||||
int i = s.indexOf("\t");
|
||||
double r, g, b;
|
||||
r = s.left(i).toFloat(); 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();
|
||||
return QColor(r * 255., g * 255., b * 255.);
|
||||
}
|
||||
|
||||
|
||||
QVector3D orthToVector(const QVector3D & v, const double & scale) {
|
||||
if (v.isNull()) return QVector3D();
|
||||
QVector3D rv, fn, sn;
|
||||
if (v.x() != 0) rv.setZ(1.);
|
||||
else if (v.y() != 0) rv.setX(1.);
|
||||
else rv.setY(1.);
|
||||
fn = QVector3D::crossProduct(v, rv).normalized();
|
||||
sn = QVector3D::crossProduct(v, fn).normalized();
|
||||
return fn * urand(scale) + sn * urand(scale);
|
||||
}
|
||||
|
||||
|
||||
QVector3D rotateVector(const QVector3D & v, const QVector3D & a) {
|
||||
QMatrix4x4 m;
|
||||
m.rotate(a.z(), 0., 0., 1.);
|
||||
m.rotate(a.y(), 0., 1., 0.);
|
||||
m.rotate(a.x(), 1., 0., 0.);
|
||||
return m * v;
|
||||
}
|
||||
|
||||
|
||||
void setVectorLength(QVector3D & v, const double & l) {
|
||||
double vl = v.length();
|
||||
if (vl == 0.) return;
|
||||
double c = l / vl;
|
||||
v *= c;
|
||||
}
|
||||
|
||||
|
||||
void lengthenVector(QVector3D & v, const double & l) {
|
||||
double vl = v.length();
|
||||
if (l == 0. || vl == 0.) return;
|
||||
double c = 1. + l / vl;
|
||||
v *= c;
|
||||
}
|
||||
|
||||
|
||||
Vector3d::Vector3d(const QString & str) {
|
||||
QString s = str.trimmed();
|
||||
int i = s.indexOf("\t");
|
||||
x = s.left(i).toFloat(); s = s.right(s.length() - i - 1); i = s.indexOf("\t");
|
||||
y = s.left(i).toFloat(); s = s.right(s.length() - i - 1);
|
||||
z = s.toFloat();
|
||||
}
|
||||
|
||||
|
||||
Vector3i::Vector3i(const QString & str) {
|
||||
QString s = str.trimmed();
|
||||
int i = s.indexOf("\t");
|
||||
p0 = s.left(i).toInt(); s = s.right(s.length() - i - 1); i = s.indexOf("\t");
|
||||
p1 = s.left(i).toInt(); s = s.right(s.length() - i - 1);
|
||||
p2 = s.toInt();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GLRendererBase::setupLight(const Light & l, int inpass_index, int gl_index) {
|
||||
QVector3D lp = l.worldPos(), ld = (l.itransform_ * QVector4D(l.direction, 0.)).toVector3D().normalized();
|
||||
GLfloat pos[] = {0.f, 0.f, 0.f, 0.f};
|
||||
GLfloat dir[] = {0.f, 0.f, 0.f};
|
||||
GLfloat col[] = {0.f, 0.f, 0.f};
|
||||
pos[0] = l.light_type == Light::Directional ? -l.direction.x() : lp.x();
|
||||
pos[1] = l.light_type == Light::Directional ? -l.direction.y() : lp.y();
|
||||
pos[2] = l.light_type == Light::Directional ? -l.direction.z() : lp.z();
|
||||
pos[3] = l.light_type == Light::Directional ? 0. : 1.;
|
||||
dir[0] = ld.x();
|
||||
dir[1] = ld.y();
|
||||
dir[2] = ld.z();
|
||||
col[0] = l.visible_ ? l.color().redF() * l.intensity : 0.;
|
||||
col[1] = l.visible_ ? l.color().greenF() * l.intensity : 0.;
|
||||
col[2] = l.visible_ ? l.color().blueF() * l.intensity : 0.;
|
||||
glEnable(gl_index);
|
||||
//glLightfv(gl_index, GL_AMBIENT, ambient);
|
||||
glLightfv(gl_index, GL_DIFFUSE, col);
|
||||
glLightfv(gl_index, GL_SPECULAR, col);
|
||||
glLightfv(gl_index, GL_POSITION, pos);
|
||||
glLightf(gl_index, GL_CONSTANT_ATTENUATION, l.decay_const);
|
||||
glLightf(gl_index, GL_LINEAR_ATTENUATION, l.decay_linear);
|
||||
glLightf(gl_index, GL_QUADRATIC_ATTENUATION, l.decay_quadratic);
|
||||
if (l.light_type == Light::Cone) {
|
||||
glLightfv(gl_index, GL_SPOT_DIRECTION, dir);
|
||||
glLightf(gl_index, GL_SPOT_CUTOFF, l.angle_spread);
|
||||
glLightf(gl_index, GL_SPOT_EXPONENT, l.angle_decay_exp);
|
||||
} else {
|
||||
glLightf(gl_index, GL_SPOT_CUTOFF, 180.);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::setupAmbientLight(const QColor & a, bool first_pass) {
|
||||
GLfloat ambient[] = {0.0f, 0.0f, 0.0f, 1.f};
|
||||
if (first_pass) {
|
||||
ambient[0] = view.ambientColor_.redF();
|
||||
ambient[1] = view.ambientColor_.greenF();
|
||||
ambient[2] = view.ambientColor_.blueF();
|
||||
}
|
||||
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::setupShadersLights(int lights_count) {
|
||||
/*foreach (QGLShaderProgram * i, view.shaders_ppl) {
|
||||
i->bind();
|
||||
i->setUniformValue("lightsCount", lights_count);
|
||||
i->setUniformValue("acc_light", lights_count > 0);
|
||||
//i->setUniformValue("mat", mvm);
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::setupTextures(GLObjectBase & o, GLRendererBase::RenderingParameters & rp, bool first_object) {
|
||||
if (first_object) {
|
||||
glReleaseTextures();
|
||||
return;
|
||||
}
|
||||
setupShadersTextures(o, rp);
|
||||
Material & mat(o.material_);
|
||||
if (rp.light) {
|
||||
if (o.accept_light) {if (!rp.prev_light) {glSetLightEnabled(true); rp.prev_light = true;}}
|
||||
else {if (rp.prev_light) {glSetLightEnabled(false); rp.prev_light = false;}}
|
||||
}
|
||||
if (rp.fog) {
|
||||
if (o.accept_fog) {if (!rp.prev_fog) {glSetFogEnabled(true); rp.prev_fog = true;}}
|
||||
else {if (rp.prev_fog) {glSetFogEnabled(false); rp.prev_fog = false;}}
|
||||
}
|
||||
if (rp.textures) {
|
||||
if (rp.prev_tex[0] != mat.diffuse.bitmap_id) {
|
||||
rp.prev_tex[0] = mat.diffuse.bitmap_id;
|
||||
glActiveTextureChannel(0); glBindTexture(GL_TEXTURE_2D, mat.diffuse.bitmap_id);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view.anisotropicLevel_);
|
||||
}
|
||||
if (rp.prev_tex[1] != mat.bump.bitmap_id) {
|
||||
rp.prev_tex[1] = mat.bump.bitmap_id;
|
||||
glActiveTextureChannel(1); glBindTexture(GL_TEXTURE_2D, mat.bump.bitmap_id);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view.anisotropicLevel_);
|
||||
}
|
||||
if (rp.prev_tex[2] != mat.relief.bitmap_id) {
|
||||
rp.prev_tex[2] = mat.relief.bitmap_id;
|
||||
glActiveTextureChannel(2); glBindTexture(GL_TEXTURE_2D, mat.relief.bitmap_id);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view.anisotropicLevel_);
|
||||
}
|
||||
glActiveTextureChannel(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::setupLights(int pass, int lights_per_pass) {
|
||||
int light_start, light_end, lmax;
|
||||
light_start = pass * lights_per_pass;
|
||||
light_end = qMin<int>((pass + 1) * lights_per_pass, view.lights_.size());
|
||||
setupAmbientLight(view.ambientColor_, pass == 0);
|
||||
if (!view.lights_.isEmpty()) {
|
||||
setupShadersLights(light_end - light_start);
|
||||
for (int i = light_start; i < light_end; ++i)
|
||||
setupLight(*view.lights_[i], i - light_start, GL_LIGHT0 + i - light_start);
|
||||
lmax = light_start + 8;
|
||||
for (int i = light_end; i < lmax; ++i)
|
||||
glDisable(GL_LIGHT0 + i - light_start);
|
||||
} else {
|
||||
setupShadersLights(0);
|
||||
for (int i = 0; i < 8; ++i)
|
||||
glDisable(GL_LIGHT0 + i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::applyFilteringParameters() {
|
||||
if (view.linearFiltering_) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view.anisotropicLevel_);
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::renderObjects(int pass, int light_pass, void * shaders, bool textures, bool light, bool fog) {
|
||||
RenderingParameters rp;
|
||||
rp.pass = pass;
|
||||
rp.light_pass = light_pass;
|
||||
rp.shaders = shaders;
|
||||
rp.textures = textures;
|
||||
rp.light = rp.prev_light = light;
|
||||
rp.fog = rp.prev_fog = fog;
|
||||
for (int i = 0; i < 32; ++i) rp.prev_tex[i] = 0;
|
||||
rp.prev_light_model = Material::Phong;
|
||||
setupTextures(view.objects_, rp, true);
|
||||
glSetLightEnabled(rp.prev_light);
|
||||
glSetFogEnabled(rp.prev_fog);
|
||||
glSetCapEnabled(GL_TEXTURE_2D, rp.textures);
|
||||
glSetCapEnabled(GL_BLEND, pass == GLObjectBase::Transparent);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_TEXTURE_CUBE_MAP);
|
||||
renderSingleObject(view.objects_, rp);
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::renderSingleObject(GLObjectBase & o, RenderingParameters & rp) {
|
||||
if (!o.isInit())
|
||||
o.init();
|
||||
if (!o.isTexturesLoaded())
|
||||
o.loadTextures();
|
||||
if (!o.visible_) return;
|
||||
Material & mat(o.material_);
|
||||
glPushMatrix();
|
||||
if (o.pos_.x() != 0. || o.pos_.y() != 0. || o.pos_.z() != 0.) qglTranslate(o.pos_);
|
||||
if (o.angles_.z() != 0.) glRotated(o.angles_.z(), 0., 0., 1.);
|
||||
if (o.angles_.y() != 0.) glRotated(o.angles_.y(), 0., 1., 0.);
|
||||
if (o.angles_.x() != 0.) glRotated(o.angles_.x(), 1., 0., 0.);
|
||||
if (o.scale_.x() != 1. || o.scale_.y() != 1. || o.scale_.z() != 1.) qglScale(o.scale_);
|
||||
if (rp.pass == o.pass_) {
|
||||
setupTextures(o, rp, false);
|
||||
mat.apply();
|
||||
glSetPolygonMode(o.render_mode != GLObjectBase::View ? o.render_mode : (view.rmode != GLObjectBase::View ? view.rmode : GL_FILL));
|
||||
glLineWidth(o.line_width > 0. ? o.line_width : view.lineWidth_);
|
||||
glPointSize(o.line_width > 0. ? o.line_width : view.lineWidth_);
|
||||
o.update();
|
||||
if (o.pass_ == GLObjectBase::Transparent) {
|
||||
glActiveTextureChannel(3);
|
||||
if (mat.reflectivity > 0.) {
|
||||
glEnable(GL_TEXTURE_CUBE_MAP);
|
||||
if (!mat.reflection.isEmpty()) mat.reflection.bind();
|
||||
else glDisable(GL_TEXTURE_CUBE_MAP);
|
||||
} else glDisable(GL_TEXTURE_CUBE_MAP);
|
||||
if (rp.light_pass > 0) glDisable(GL_TEXTURE_CUBE_MAP);
|
||||
GLfloat gm[16], bc[4] = {mat.reflectivity, mat.reflectivity, mat.reflectivity, mat.reflectivity};
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
|
||||
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, bc);
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, gm);
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadTransposeMatrixf(gm);
|
||||
glScalef(-1., -1., -1.);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glActiveTextureChannel(0);
|
||||
}
|
||||
o.draw();
|
||||
}
|
||||
foreach (GLObjectBase * i, o.children_)
|
||||
renderSingleObject(*i, rp);
|
||||
glPopMatrix();
|
||||
}
|
||||
540
qglview/gltypes.h
Normal file
@@ -0,0 +1,540 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU 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
|
||||
#ifndef WINDOWS
|
||||
# ifndef QNX
|
||||
# define LINUX
|
||||
# endif
|
||||
#endif
|
||||
#if __GNUC__
|
||||
# define CC_GCC
|
||||
#elif _MSC_VER
|
||||
# define CC_VC
|
||||
#endif
|
||||
|
||||
#ifdef WINDOWS
|
||||
# include "GLee.h"
|
||||
#else
|
||||
# include <GL/gl.h>
|
||||
# include <GL/glext.h>
|
||||
#endif
|
||||
#include <GL/glu.h>
|
||||
#include <qgl.h>
|
||||
#include <cmath>
|
||||
#include <float.h>
|
||||
#include <limits>
|
||||
#include <QMatrix4x4>
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
#include <QDataStream>
|
||||
#include <QColor>
|
||||
#include <QVector2D>
|
||||
#include <QVector3D>
|
||||
#include <QImage>
|
||||
#include <QMutex>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QGLShaderProgram>
|
||||
#ifndef QNX
|
||||
# include <cmath>
|
||||
# include <complex>
|
||||
#else
|
||||
# include <math.h>
|
||||
# include <complex.h>
|
||||
#endif
|
||||
#include <iostream>
|
||||
|
||||
#ifdef WINDOWS
|
||||
# define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
|
||||
# define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
|
||||
#endif
|
||||
|
||||
#ifdef CC_VC
|
||||
# define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
#define M_2PI 6.28318530717958647692
|
||||
#define M_PI_3 1.04719755119659774615
|
||||
|
||||
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 double deg2rad = atan(1.) / 45.;
|
||||
const double rad2deg = 45. / atan(1.);
|
||||
|
||||
# ifdef WINDOWS
|
||||
inline int random() {return rand();}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef CC_VC
|
||||
inline double round(const double & v) {return floor(v + 0.5);}
|
||||
#endif
|
||||
inline double randomu() {return double(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 Type> inline void piSwap(Type & f, Type & s) {Type 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);}
|
||||
#endif
|
||||
// return [-1, 1]
|
||||
inline double urand(const double & scale = 1.) {return ((double)rand() / RAND_MAX - .5) * (scale + scale);}
|
||||
// return [0, 1]
|
||||
inline double uprand(const double & scale = 1.) {return ((double)rand() / RAND_MAX) * scale;}
|
||||
QString readCharsUntilNull(QDataStream & s);
|
||||
inline QColor operator *(const QColor & c, double v) {return QColor(c.red() * v, c.green() * v, c.blue() * v, c.alpha() * v);}
|
||||
inline QColor operator /(const QColor & c, double v) {return QColor(c.red() / v, c.green() / v, c.blue() / v, c.alpha() / v);}
|
||||
|
||||
inline void qglColor(const QColor & c) {glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());}
|
||||
inline void glActiveTextureChannel(int channel) {glActiveTexture(GL_TEXTURE0 + channel); glClientActiveTexture(GL_TEXTURE0 + channel);}
|
||||
inline void glResetAllTransforms() {glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity();}
|
||||
inline void glClearError() {int c = 100; while (glGetError() != GL_NO_ERROR && --c > 0) glGetError();}
|
||||
inline void glClearAccumulation(const QColor & color = Qt::black) {glClearAccum(color.redF(), color.greenF(), color.blueF(), color.alphaF()); glClear(GL_ACCUM_BUFFER_BIT);}
|
||||
inline void glClearFramebuffer(const QColor & color = Qt::black, bool depth = true) {glClearColor(color.redF(), color.greenF(), color.blueF(), color.alphaF()); if (depth) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); else glClear(GL_COLOR_BUFFER_BIT);}
|
||||
inline void glReleaseTextures(int channels = 8) {for (int i = channels - 1; i >= 0; --i) {glActiveTextureChannel(i); glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_CUBE_MAP, 0);}}
|
||||
inline void glReleaseFramebuffer() {glBindFramebuffer(GL_FRAMEBUFFER, 0);}
|
||||
inline void glDisableTextures(int channels = 8) {for (int i = channels - 1; i >= 0; --i) {glActiveTextureChannel(i); glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_CUBE_MAP);}}
|
||||
inline void glReleaseShaders() {glUseProgram(0);}
|
||||
inline void glSetCapEnabled(GLenum cap, bool on = true) {if (on) glEnable(cap); else glDisable(cap);}
|
||||
inline void glSetLightEnabled(bool on) {if (on) glEnable(GL_LIGHTING); else glDisable(GL_LIGHTING);}
|
||||
inline void glSetFogEnabled(bool on) {if (on) glEnable(GL_FOG); else glDisable(GL_FOG);}
|
||||
inline void glSetPolygonMode(GLenum mode) {glPolygonMode(GL_FRONT_AND_BACK, mode);}
|
||||
void glDrawQuad(GLfloat x = -1.f, GLfloat y = -1.f, GLfloat w = 2.f, GLfloat h = 2.f);
|
||||
QMatrix4x4 getGLMatrix(GLenum matrix);
|
||||
inline void deleteGLTexture(GLuint & tex) {if (tex != 0) glDeleteTextures(1, &tex); tex = 0;}
|
||||
inline void deleteGLFramebuffer(GLuint & fbo) {if (fbo != 0) glDeleteFramebuffers(1, &fbo); fbo = 0;}
|
||||
inline void deleteGLRenderbuffer(GLuint & drbo) {if (drbo != 0) glDeleteRenderbuffers(1, &drbo); drbo = 0;}
|
||||
inline void deleteGLBuffer(GLuint & bo) {if (bo != 0) glDeleteBuffers(1, &bo); bo = 0;}
|
||||
void createGLTexture(GLuint & tex, int width, int height, const GLenum & format = GL_RGBA8, const GLenum & target = GL_TEXTURE_2D);
|
||||
void createGLTexture(GLuint & tex, const QImage & image, const GLenum & format = GL_RGBA8, const GLenum & target = GL_TEXTURE_2D);
|
||||
inline void qglTranslate(const QVector3D & v) {glTranslated(v.x(), v.y(), v.z());}
|
||||
inline void qglScale(const QVector3D & v) {glScaled(v.x(), v.y(), v.z());}
|
||||
bool loadShaders(QGLShaderProgram * prog, const QString & name, const QString & dir = QString());
|
||||
QImage rotateQImageLeft(const QImage & im);
|
||||
QImage rotateQImageRight(const QImage & im);
|
||||
inline QImage rotateQImage180(const QImage & im) {return im.mirrored(true, true);}
|
||||
//const double deg2rad = atan(1.) / 45.;
|
||||
//const double rad2deg = 45. / atan(1.);
|
||||
|
||||
extern QGLWidget * currentQGLView;
|
||||
extern QMatrix4x4 globCameraMatrix;
|
||||
extern QMutex globMutex;
|
||||
|
||||
|
||||
class GLTexture {
|
||||
public:
|
||||
GLTexture(int _width, int _height, const GLenum & _format = GL_RGBA8, const GLenum & _target = GL_TEXTURE_2D) {wid = _width; hei = _height; format_ = _format; target_ = _target; id_ = 0;}
|
||||
bool create() {destroy(); createGLTexture(id_, wid, hei, format_, target_); return id_ > 0;}
|
||||
void destroy() {if (id_ > 0) glDeleteTextures(1, &id_); id_ = 0;}
|
||||
void bind() {if (id_ > 0) glBindTexture(target_, id_);}
|
||||
void release() {glBindTexture(target_, 0);}
|
||||
int width() const {return wid;}
|
||||
int height() const {return hei;}
|
||||
GLenum format() const {return format_;}
|
||||
GLenum target() const {return target_;}
|
||||
GLuint id() const {return id_;}
|
||||
private:
|
||||
int wid, hei;
|
||||
GLenum format_, target_;
|
||||
GLuint id_;
|
||||
};
|
||||
|
||||
|
||||
class GLCubeTexture {
|
||||
public:
|
||||
GLCubeTexture(int _size, const GLenum & _format = GL_RGBA8) {size = _size; format_ = _format; id_ = 0; changed_ = false; pathes.resize(6);}
|
||||
bool create();
|
||||
void destroy() {if (id_ > 0) glDeleteTextures(1, &id_); id_ = 0;}
|
||||
void bind() {if (changed_) {changed_ = false; create();} if (id_ > 0) glBindTexture(GL_TEXTURE_CUBE_MAP, id_);}
|
||||
void release() {glBindTexture(GL_TEXTURE_CUBE_MAP, 0);}
|
||||
void resize(int _size) {size = _size; changed_ = true;}
|
||||
void loadFromDirectory(const QString & dir);
|
||||
void loadFront(const QString & path) {bind(); pathes[0] = path; createGLTexture(id_, rotateQImageLeft(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_POSITIVE_X);}
|
||||
void loadBack(const QString & path) {bind(); pathes[1] = path; createGLTexture(id_, rotateQImageRight(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_NEGATIVE_X);}
|
||||
void loadLeft(const QString & path) {bind(); pathes[2] = path; createGLTexture(id_, QImage(path).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);}
|
||||
void loadRight(const QString & path) {bind(); pathes[3] = path; createGLTexture(id_, rotateQImage180(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_POSITIVE_Y);}
|
||||
void loadTop(const QString & path) {bind(); pathes[4] = path; createGLTexture(id_, rotateQImageLeft(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);}
|
||||
void loadBottom(const QString & path) {bind(); pathes[5] = path; createGLTexture(id_, rotateQImageLeft(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_POSITIVE_Z);}
|
||||
void load();
|
||||
bool isEmpty() const {foreach (const QString & i, pathes) if (!i.isEmpty()) return false; return true;}
|
||||
GLenum format() const {return format_;}
|
||||
void setFormat(GLenum f) {format_ = f; changed_ = true;}
|
||||
GLuint id() const {return id_;}
|
||||
const QString & path(int side) const {return pathes[side];}
|
||||
void setPath(int side, const QString & p) {pathes[side] = p;}
|
||||
void loadPathesFromDirectory(const QString & dir);
|
||||
private:
|
||||
bool changed_;
|
||||
int size;
|
||||
GLenum format_;
|
||||
GLuint id_;
|
||||
QVector<QString> pathes;
|
||||
};
|
||||
|
||||
class GLTextureManager;
|
||||
|
||||
class GLTextureManagerBase {
|
||||
public:
|
||||
static GLuint loadTexture(const QString & path, bool ownership = true);
|
||||
static GLuint loadTexture(const QImage & image, bool ownership = true);
|
||||
int textureID(const QString & path) {return tex_ids[path];}
|
||||
|
||||
protected:
|
||||
QMap<QString, GLuint> tex_ids;
|
||||
|
||||
};
|
||||
|
||||
extern GLTextureManager * currentGLTextureManager;
|
||||
|
||||
class Camera
|
||||
{
|
||||
friend class QGLView;
|
||||
friend class GLParticlesSystem;
|
||||
public:
|
||||
Camera() {fov_ = 60.; angle_xy = angle_z = angle_roll = 0.; angle_limit_lower_xy = 180.; angle_limit_upper_xy = 360.; depth_start = 0.1; depth_end = 1000.; mirror_x = mirror_y = false;}
|
||||
|
||||
void setPos(const QVector3D & p) {pos_ = p; anglesFromPoints();}
|
||||
/*void setPosX(const double & o) {QVector3D dv = aim_ - pos_; pos_.setX(o); aim_ = pos_ + dv;}
|
||||
void setPosY(const double & o) {QVector3D dv = aim_ - pos_; pos_.setY(o); aim_ = pos_ + dv;}
|
||||
void setPosZ(const double & o) {QVector3D dv = aim_ - pos_; pos_.setZ(o); aim_ = pos_ + dv;}*/
|
||||
void setAim(const QVector3D & p) {aim_ = p; anglesFromPoints();}
|
||||
void move(const QVector3D & p) {pos_ += p; aim_ += p;}
|
||||
void move(const double & x, const double & y = 0., const double & z = 0.) {pos_ += QVector3D(x, y, z); aim_ += QVector3D(x, y, z);}
|
||||
void moveForward(const double & x, bool withZ = true);
|
||||
void moveBackward(const double & x, bool withZ = true) {moveForward(-x, withZ);}
|
||||
void moveLeft(const double & x, bool withZ = true);
|
||||
void moveRight(const double & x, bool withZ = true) {moveLeft(-x, withZ);}
|
||||
void moveUp(const double & x, bool onlyZ = false);
|
||||
void moveDown(const double & x, bool onlyZ = false) {moveUp(-x, onlyZ);}
|
||||
void rotateZ(const double & a);
|
||||
void rotateXY(const double & a);
|
||||
void rotateRoll(const double & a) {angle_roll += a;}
|
||||
void orbitZ(const double & a);
|
||||
void orbitXY(const double & a);
|
||||
void panZ(const double & a);
|
||||
void panXY(const double & a);
|
||||
void setFOV(const double & f) {fov_ = f;}
|
||||
void setAngles(const QVector3D & a) {angle_xy = a.x(); angle_roll = a.y(); angle_z = a.z();}
|
||||
void setAngleZ(const double & a);
|
||||
void setAngleXY(const double & a);
|
||||
void setAngleRoll(const double & a) {angle_roll = a;}
|
||||
void setAngleLowerLimitXY(const double & a) {angle_limit_lower_xy = a;}
|
||||
void setAngleUpperLimitXY(const double & a) {angle_limit_upper_xy = a;}
|
||||
void setAngleLimitsXY(const double & lower, const double & upper) {angle_limit_lower_xy = lower; angle_limit_upper_xy = upper;}
|
||||
void setDepthStart(const double & d) {depth_start = d;}
|
||||
void setDepthEnd(const double & d) {depth_end = d;}
|
||||
void setMirrorX(bool yes) {mirror_x = yes;}
|
||||
void setMirrorY(bool yes) {mirror_y = yes;}
|
||||
void flyCloser(const double & s);
|
||||
void flyFarer(const double & s);
|
||||
void flyToDistance(const double & d);
|
||||
|
||||
QVector3D pos() const {return pos_;}
|
||||
QVector3D aim() const {return aim_;}
|
||||
QVector3D angles() const {return QVector3D(angle_xy, angle_roll, angle_z);}
|
||||
QVector3D direction() const {return (aim_ - pos_).normalized();}
|
||||
QVector3D directionXY() const {QVector3D tv = aim_ - pos_; return QVector3D(tv.x(), tv.y(), 0.).normalized();}
|
||||
QVector3D pointFromViewport(int x, int y, double z = 0.);
|
||||
double FOV() const {return fov_;}
|
||||
double distance() const {return (pos_ - aim_).length();}
|
||||
double angleZ() const {return angle_z;}
|
||||
double angleXY() const {return angle_xy;}
|
||||
double angleRoll() const {return angle_roll;}
|
||||
double angleLowerLimitXY() const {return angle_limit_lower_xy;}
|
||||
double angleUpperLimitXY() const {return angle_limit_upper_xy;}
|
||||
double depthStart() const {return depth_start;}
|
||||
double depthEnd() const {return depth_end;}
|
||||
bool isMirrorX() const {return mirror_x;}
|
||||
bool isMirrorY() const {return mirror_y;}
|
||||
void anglesFromPoints();
|
||||
void apply(const GLdouble & aspect = 1.);
|
||||
void assign(const Camera & c) {pos_ = c.pos_; aim_ = c.aim_; fov_ = c.fov_; angle_z = c.angle_z; angle_xy = c.angle_xy; angle_roll = c.angle_roll; angle_limit_lower_xy = c.angle_limit_lower_xy; angle_limit_upper_xy = c.angle_limit_upper_xy;}
|
||||
|
||||
private:
|
||||
QVector3D pos_;
|
||||
QVector3D aim_;
|
||||
GLdouble fov_;
|
||||
GLdouble depth_start;
|
||||
GLdouble depth_end;
|
||||
GLdouble angle_z;
|
||||
GLdouble angle_xy;
|
||||
GLdouble angle_roll;
|
||||
GLdouble angle_limit_lower_xy;
|
||||
GLdouble angle_limit_upper_xy;
|
||||
bool mirror_x;
|
||||
bool mirror_y;
|
||||
GLint viewport[4];
|
||||
GLdouble projection[16];
|
||||
GLdouble modelview[16];
|
||||
};
|
||||
|
||||
extern Camera * currentCamera;
|
||||
|
||||
struct Map {
|
||||
Map() {bitmap_id = 0; bitmap_amount = 1.f; animation_frame_rate = -1.f;}
|
||||
QString bitmap_path;
|
||||
GLuint bitmap_id;
|
||||
QPointF bitmap_offset;
|
||||
float bitmap_amount;
|
||||
QString animation;
|
||||
float animation_frame_rate;
|
||||
};
|
||||
|
||||
struct Material {
|
||||
enum LightModel {Phong = 0, CookTorrance = 1, Minnaert = 2, Strauss = 3, OrenNayar = 4};
|
||||
Material();
|
||||
void apply();
|
||||
void loadTextures(GLTextureManagerBase * tm = 0);
|
||||
QColor color_diffuse;
|
||||
QColor color_specular;
|
||||
QColor color_self_illumination;
|
||||
LightModel light_model;
|
||||
bool glass;
|
||||
float shine;
|
||||
float shine_strength;
|
||||
float transparency;
|
||||
float reflectivity;
|
||||
float iof;
|
||||
float dispersion;
|
||||
float bump_scale;
|
||||
float relief_scale;
|
||||
Map diffuse;
|
||||
Map bump;
|
||||
Map relief;
|
||||
Map diffuse_2;
|
||||
Map diffuse_3;
|
||||
Map diffuse_4;
|
||||
GLCubeTexture reflection;
|
||||
};
|
||||
|
||||
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;}
|
||||
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. + x, width / 2. + y, height / 2. + z);}
|
||||
QVector3D angles() const {return QVector3D(angle_xy, angle_roll, angle_z);}
|
||||
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;}
|
||||
};
|
||||
|
||||
inline QDebug operator <<(QDebug d, const Box3D & v) {d << "Box3D {center (" << v.x << "," << v.y << "," << v.z << "), size (" << v.length << "," << v.width << "," << v.height << ")}"; return d;}
|
||||
|
||||
struct Vector3d;
|
||||
|
||||
GLfloat dot(const Vector3d & v0, const Vector3d & v1);
|
||||
|
||||
struct Vector3d {
|
||||
GLfloat x;
|
||||
GLfloat y;
|
||||
GLfloat z;
|
||||
Vector3d(GLfloat x_ = 0., GLfloat y_ = 0., GLfloat z_ = 0.) {x = x_; y = y_; z = z_;}
|
||||
Vector3d(const QVector3D & v) {x = v.x(); y = v.y(); z = v.z();}
|
||||
Vector3d(const QString & str);
|
||||
inline void clear() {x = y = z = 0.;}
|
||||
inline GLfloat length() const {return sqrt(x*x + y*y + z*z);}
|
||||
inline GLfloat lengthSquared() const {return x*x + y*y + z*z;}
|
||||
Vector3d & normalize() {
|
||||
GLfloat l = length();
|
||||
if (l == 0.) return *this;
|
||||
x /= l; y /= l; z /= l;
|
||||
return *this;
|
||||
};
|
||||
Vector3d normalized() {return Vector3d(*this).normalize();}
|
||||
Vector3d projectTo(Vector3d dir) {dir.normalize(); return dir * dot(dir, *this);}
|
||||
Vector3d operator *(const GLfloat v) {return Vector3d(x*v, y*v, z*v);}
|
||||
Vector3d operator /(const GLfloat v) {return Vector3d(x/v, y/v, z/v);}
|
||||
Vector3d operator +(const GLfloat v) {return Vector3d(x+v, y+v, z+v);}
|
||||
Vector3d operator -(const GLfloat v) {return Vector3d(x-v, y-v, z-v);}
|
||||
Vector3d operator +(const Vector3d & v) {return Vector3d(x + v.x, y + v.y, z + v.z);}
|
||||
Vector3d operator -(const Vector3d & v) {return Vector3d(x - v.x, y - v.y, z - v.z);}
|
||||
Vector3d operator -() {return Vector3d(-x, -y, -z);}
|
||||
Vector3d & operator *=(const GLfloat & v) {x *= v; y *= v; z *= v; return *this;}
|
||||
Vector3d & operator /=(const GLfloat & v) {x /= v; y /= v; z /= v; return *this;}
|
||||
Vector3d & operator +=(const GLfloat & v) {x += v; y += v; z += v; return *this;}
|
||||
Vector3d & operator -=(const GLfloat & v) {x -= v; y -= v; z -= v; return *this;}
|
||||
Vector3d & operator +=(const Vector3d & v) {x += v.x; y += v.y; z += v.z; return *this;}
|
||||
Vector3d & operator -=(const Vector3d & v) {x -= v.x; y -= v.y; z -= v.z; return *this;}
|
||||
bool operator ==(const Vector3d & v) {return x == v.x && y == v.y && z == v.z;}
|
||||
QVector3D toQVector3D() const {return QVector3D(x, y, z);}
|
||||
};
|
||||
|
||||
inline Vector3d operator *(const Vector3d & v0, const Vector3d & v1) {
|
||||
return Vector3d(v0.y * v1.z - v1.y * v0.z, v1.x * v0.z - v0.x * v1.z, v0.x * v1.y - v1.x * v0.y);
|
||||
}
|
||||
inline GLfloat dot(const Vector3d & v0, const Vector3d & v1) {return v0.x*v1.x + v0.y*v1.y + v0.z*v1.z;}
|
||||
|
||||
struct Vector2d {
|
||||
GLfloat x;
|
||||
GLfloat y;
|
||||
Vector2d(GLfloat x_ = 0., GLfloat y_ = 0.) {x = x_; y = y_;}
|
||||
Vector2d(const Vector3d & v3) {x = v3.x; y = v3.y;}
|
||||
Vector2d operator *(const GLfloat v) {return Vector2d(x*v, y*v);}
|
||||
Vector2d operator /(const GLfloat v) {return Vector2d(x/v, y/v);}
|
||||
Vector2d operator +(const GLfloat v) {return Vector2d(x+v, y+v);}
|
||||
Vector2d operator -(const GLfloat v) {return Vector2d(x-v, y-v);}
|
||||
Vector2d operator +(const Vector3d & v) {return Vector3d(x + v.x, y + v.y);}
|
||||
Vector2d operator -(const Vector3d & v) {return Vector3d(x - v.x, y - v.y);}
|
||||
Vector2d & operator *=(const GLfloat & v) {x *= v; y *= v; return *this;}
|
||||
Vector2d & operator /=(const GLfloat & v) {x /= v; y /= v; return *this;}
|
||||
Vector2d & operator +=(const GLfloat & v) {x += v; y += v; return *this;}
|
||||
Vector2d & operator -=(const GLfloat & v) {x -= v; y -= v; return *this;}
|
||||
Vector2d & operator +=(const Vector3d & v) {x += v.x; y += v.y;; return *this;}
|
||||
Vector2d & operator -=(const Vector3d & v) {x -= v.x; y -= v.y;; return *this;}
|
||||
};
|
||||
|
||||
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);}
|
||||
int p0;
|
||||
int p1;
|
||||
int 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;}
|
||||
QVector3D toQVector3D() const {return QVector3D(p0, p1, 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 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 * 1024 + v.p2 * 1024 * 1024;}
|
||||
inline QDebug operator <<(QDebug d, const Vector3d& v) {d.nospace() << "{" << v.x << ", " << v.y << ", " << v.z << "}"; return d.space();}
|
||||
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 Map & m) {s << m.bitmap_path << m.bitmap_amount << m.animation << m.animation_frame_rate; return s;}
|
||||
inline QDataStream & operator <<(QDataStream & s, const Vector3d & v) {s << v.x << v.y << v.z; return s;}
|
||||
inline QDataStream & operator <<(QDataStream & s, const Vector3i & v) {s << v.p0 << v.p1 << v.p2; return s;}
|
||||
inline QDataStream & operator <<(QDataStream & s, const Material & m) {s << m.color_diffuse << m.shine << m.shine_strength << m.color_specular << m.transparency << m.diffuse << m.bump; return s;}
|
||||
inline QDataStream & operator >>(QDataStream & s, Map & m) {s >> m.bitmap_path >> m.bitmap_amount >> m.animation >> m.animation_frame_rate; return s;}
|
||||
inline QDataStream & operator >>(QDataStream & s, Vector3d & v) {s >> v.x >> v.y >> v.z; return s;}
|
||||
inline QDataStream & operator >>(QDataStream & s, Vector3i & v) {s >> v.p0 >> v.p1 >> v.p2; return s;}
|
||||
inline QDataStream & operator >>(QDataStream & s, Material & m) {s >> m.color_diffuse >> m.shine >> m.shine_strength >> m.color_specular >> m.transparency >> m.diffuse >> m.bump; return s;}
|
||||
|
||||
QColor colorFromString(const QString & str);
|
||||
inline double cosABV(const QVector3D & v0, const QVector3D & v1) {
|
||||
double l = v0.length() * v1.length();
|
||||
if (l == 0.) return 0.;
|
||||
return (QVector3D::dotProduct(v0, v1)) / l;
|
||||
}
|
||||
inline QVector3D projection(const QVector3D & v, const QVector3D & to) {return to.normalized() * v.length() * cosABV(v, to);}
|
||||
QVector3D orthToVector(const QVector3D & v, const double & scale = 1.);
|
||||
QVector3D rotateVector(const QVector3D & v, const QVector3D & a);
|
||||
void setVectorLength(QVector3D & v, const double & l);
|
||||
void lengthenVector(QVector3D & v, const double & l);
|
||||
inline double 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 double frac(const double & x, const double & b) {return x - int(x / b) * b;}
|
||||
|
||||
class GLObjectBase;
|
||||
class QGLView;
|
||||
class Light;
|
||||
|
||||
class QGLViewBase
|
||||
{
|
||||
friend class GLObjectBase;
|
||||
public:
|
||||
QGLViewBase() {}
|
||||
Camera & camera() {return camera_;}
|
||||
void setCamera(const Camera &cam) {camera_ = cam;}
|
||||
protected:
|
||||
virtual void collectLights() = 0;
|
||||
Camera camera_;
|
||||
};
|
||||
|
||||
|
||||
class GLRendererBase: public QObject
|
||||
{
|
||||
friend class QGLView;
|
||||
Q_OBJECT
|
||||
public:
|
||||
GLRendererBase(QGLView * view_): view(*view_) {}
|
||||
virtual void renderScene() = 0;
|
||||
|
||||
protected:
|
||||
struct RenderingParameters {
|
||||
int pass;
|
||||
int light_pass;
|
||||
bool light;
|
||||
bool fog;
|
||||
bool textures;
|
||||
bool prev_light;
|
||||
bool prev_fog;
|
||||
Material::LightModel prev_light_model;
|
||||
GLuint prev_tex[32];
|
||||
void * shaders;
|
||||
QGLShaderProgram * cur_shader;
|
||||
};
|
||||
|
||||
virtual void setupLight(const Light & l, int inpass_index, int gl_index);
|
||||
virtual void setupAmbientLight(const QColor & a, bool first_pass);
|
||||
virtual void setupShadersLights(int lights_count);
|
||||
virtual void setupTextures(GLObjectBase & object, GLRendererBase::RenderingParameters & rp, bool first_object = false);
|
||||
virtual void setupShadersTextures(GLObjectBase & object, GLRendererBase::RenderingParameters & rp) {}
|
||||
virtual void reloadShaders() {}
|
||||
virtual void init(int width, int height) {}
|
||||
virtual void resize(int width, int height) {}
|
||||
|
||||
void setupLights(int pass, int lights_per_pass);
|
||||
inline void applyFilteringParameters();
|
||||
void renderObjects(int pass, int light_pass, void * shaders = 0, bool textures = true, bool light = true, bool fog = true);
|
||||
void renderSingleObject(GLObjectBase & o, RenderingParameters & rp);
|
||||
|
||||
QGLView & view;
|
||||
};
|
||||
|
||||
#endif // GLTYPES_H
|
||||
141
qglview/glvbo.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "glvbo.h"
|
||||
|
||||
|
||||
GLVBO::GLVBO(GLenum usage_) {
|
||||
buffer_ = 0;
|
||||
usage = usage_;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
|
||||
GLVBO::~GLVBO() {
|
||||
//destroy();
|
||||
}
|
||||
|
||||
|
||||
void GLVBO::init() {
|
||||
if (!isIinit())
|
||||
glGenBuffers(1, &buffer_);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
|
||||
bool GLVBO::rebuffer(bool clear_) {
|
||||
QVector<GLfloat> data;
|
||||
//data.clear();
|
||||
data << vertices_;
|
||||
if (!normals_.isEmpty()) {
|
||||
data << normals_;
|
||||
has_normals = true;
|
||||
} else has_normals = false;
|
||||
if (!texcoords_.isEmpty()) {
|
||||
data << texcoords_;
|
||||
has_texcoords = true;
|
||||
} else has_texcoords = false;
|
||||
if (!colors_.isEmpty()) {
|
||||
data << colors_;
|
||||
has_colors = true;
|
||||
} else has_colors = false;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer_);
|
||||
glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(GLfloat), data.constData(), usage);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
vert_count = vertices_.size() / 3;
|
||||
changed = false;
|
||||
//qDebug() << "rebuff" << buffer_ << vert_count;
|
||||
if (clear_) clear();
|
||||
return !isEmpty();
|
||||
}
|
||||
|
||||
|
||||
void GLVBO::draw(GLenum type, bool simplest) {
|
||||
if (buffer_ == 0 || vert_count == 0) return;
|
||||
if (changed) rebuffer();
|
||||
//qDebug() << "draw" << vert_count;
|
||||
void * offset = (void*)(vert_count * 3 * sizeof(GLfloat));
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer_);
|
||||
glMultiTexCoord3f(GL_TEXTURE2, 0.f, 1.f, 0.f);
|
||||
glVertexPointer(3, GL_FLOAT, 0, 0);
|
||||
if (!simplest) {
|
||||
if (has_normals) {
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glNormalPointer(GL_FLOAT, 0, offset);
|
||||
offset = (void*)(llong(offset) + vert_count * 3 * sizeof(GLfloat));
|
||||
} else glDisableClientState(GL_NORMAL_ARRAY);
|
||||
if (has_texcoords) {
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, offset);
|
||||
offset = (void*)(llong(offset) + vert_count * 2 * sizeof(GLfloat));
|
||||
} else glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
if (has_colors) {
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glColorPointer(4, GL_FLOAT, 0, offset);
|
||||
} else glDisableClientState(GL_COLOR_ARRAY);
|
||||
}/* else {
|
||||
glDisable(GL_NORMAL_ARRAY);
|
||||
glDisable(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisable(GL_COLOR_ARRAY);
|
||||
}*/
|
||||
glDrawArrays(type, 0, vert_count);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
|
||||
void GLVBO::clear() {
|
||||
vertices_.clear();
|
||||
normals_.clear();
|
||||
texcoords_.clear();
|
||||
colors_.clear();
|
||||
}
|
||||
|
||||
|
||||
bool GLVBO::saveToFile(const QString & filename) {
|
||||
if (filename.isEmpty()) return false;
|
||||
QFile f(filename);
|
||||
QByteArray ba;
|
||||
if (f.open(QFile::WriteOnly)) {
|
||||
QDataStream out(&ba, QFile::WriteOnly);
|
||||
out << vertices_ << normals_ << texcoords_ << colors_;
|
||||
ba = qCompress(ba);
|
||||
f.resize(0);
|
||||
f.write(ba);
|
||||
f.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool GLVBO::loadFromFile(const QString & filename) {
|
||||
if (filename.isEmpty()) return false;
|
||||
QFile f(filename);
|
||||
QByteArray ba;
|
||||
if (f.open(QFile::ReadOnly)) {
|
||||
ba = f.readAll();
|
||||
if (ba.isEmpty()) return false;
|
||||
ba = qUncompress(ba);
|
||||
QDataStream in(ba);
|
||||
in >> vertices_ >> normals_ >> texcoords_ >> colors_;
|
||||
changed = true;
|
||||
f.close();
|
||||
return !isEmpty();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
61
qglview/glvbo.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GLVBO_H
|
||||
#define GLVBO_H
|
||||
|
||||
#include "gltypes.h"
|
||||
|
||||
class GLVBO
|
||||
{
|
||||
friend class GLObjectBase;
|
||||
public:
|
||||
GLVBO(GLenum usage = GL_DYNAMIC_DRAW);
|
||||
~GLVBO();
|
||||
|
||||
//GLVBO & operator =(const GLVBO & o) {return *this;}
|
||||
|
||||
void init();
|
||||
void destroy() {deleteGLBuffer(buffer_);}
|
||||
bool rebuffer(bool clear_ = false);
|
||||
void draw(GLenum type, bool simplest = false);
|
||||
void clear();
|
||||
|
||||
GLuint buffer() const {return buffer_;}
|
||||
int verticesCount() const {return vert_count;}
|
||||
bool isIinit() const {return buffer_ != 0;}
|
||||
bool isEmpty() const {return vert_count == 0;}
|
||||
|
||||
QVector<GLfloat> & vertices() {changed = true; return vertices_;}
|
||||
QVector<GLfloat> & normals() {changed = true; return normals_;}
|
||||
QVector<GLfloat> & texcoords() {changed = true; return texcoords_;}
|
||||
QVector<GLfloat> & colors() {changed = true; return colors_;}
|
||||
|
||||
bool saveToFile(const QString & filename);
|
||||
bool loadFromFile(const QString & filename);
|
||||
|
||||
private:
|
||||
QVector<GLfloat> vertices_, normals_, texcoords_, colors_;
|
||||
GLenum usage;
|
||||
GLuint buffer_;
|
||||
int vert_count;
|
||||
bool changed, has_normals, has_texcoords, has_colors;
|
||||
|
||||
};
|
||||
|
||||
#endif // GLVBO_H
|
||||
BIN
qglview/icons/alpha.png
Normal file
|
After Width: | Height: | Size: 158 B |
BIN
qglview/icons/configure.png
Normal file
|
After Width: | Height: | Size: 717 B |
BIN
qglview/icons/dialog-close.png
Normal file
|
After Width: | Height: | Size: 813 B |
BIN
qglview/icons/document-save.png
Normal file
|
After Width: | Height: | Size: 563 B |
BIN
qglview/icons/edit-clear-locationbar-rtl.png
Normal file
|
After Width: | Height: | Size: 644 B |
BIN
qglview/icons/edit-clear.png
Normal file
|
After Width: | Height: | Size: 802 B |
BIN
qglview/icons/edit-copy.png
Normal file
|
After Width: | Height: | Size: 485 B |
BIN
qglview/icons/edit-delete.png
Normal file
|
After Width: | Height: | Size: 640 B |
BIN
qglview/icons/edit-find.png
Normal file
|
After Width: | Height: | Size: 634 B |
BIN
qglview/icons/edit-guides.png
Normal file
|
After Width: | Height: | Size: 544 B |
BIN
qglview/icons/edit-paste.png
Normal file
|
After Width: | Height: | Size: 529 B |
BIN
qglview/icons/item-add.png
Normal file
|
After Width: | Height: | Size: 639 B |
BIN
qglview/icons/item.png
Normal file
|
After Width: | Height: | Size: 448 B |
BIN
qglview/icons/list-add.png
Normal file
|
After Width: | Height: | Size: 564 B |
BIN
qglview/icons/node-add.png
Normal file
|
After Width: | Height: | Size: 694 B |
BIN
qglview/icons/node.png
Normal file
|
After Width: | Height: | Size: 658 B |
BIN
qglview/icons/view-grid.png
Normal file
|
After Width: | Height: | Size: 691 B |
BIN
qglview/icons/zoom-fit-best.png
Normal file
|
After Width: | Height: | Size: 539 B |
276
qglview/loader_3ds.cpp
Normal file
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "loader_3ds.h"
|
||||
|
||||
|
||||
void Loader3DS::init3DSMesh(GLObjectBase * o, const QVector<uint> & smooth) {
|
||||
QVector<GLfloat> & vertices(o->VBO().vertices()), & normals(o->VBO().normals()), & uvs(o->VBO().texcoords());
|
||||
QVector<Vector3d> & points(o->points), & puvws(o->puvws), fnormals;
|
||||
QVector<Vector3i> & faces(o->faces);
|
||||
Vector3d pos = Vector3d(o->pos());
|
||||
bool has_uv = !puvws.isEmpty();
|
||||
Vector3i cf;
|
||||
Vector3d v0, v1, v2, cn0, cn1, cn2;
|
||||
fnormals.resize(faces.size());
|
||||
for (int i = 0; i < points.size(); ++i)
|
||||
points[i] -= pos;
|
||||
for (int i = 0; i < fnormals.size(); ++i) {
|
||||
cf = faces[i];
|
||||
v0 = points[cf.p0];
|
||||
v1 = points[cf.p1];
|
||||
v2 = points[cf.p2];
|
||||
fnormals[i] = ((v1 - v0) * (v2 - v0)).normalized();
|
||||
}
|
||||
uint fcnt = faces.size() * 3;
|
||||
vertices.resize(fcnt * 3);
|
||||
normals.resize(vertices.size());
|
||||
if (has_uv) uvs.resize(fcnt * 2);
|
||||
uint ind = 0, induv = 0, ncnt0, ncnt1, ncnt2, csg;
|
||||
//qDebug() << faces.size();
|
||||
if (smooth.isEmpty()) {
|
||||
for (int i = 0; i < faces.size(); ++i) {
|
||||
cf = faces[i];
|
||||
cn0 = fnormals[i];
|
||||
v0 = points[cf.p0];
|
||||
v1 = points[cf.p1];
|
||||
v2 = points[cf.p2];
|
||||
vertices[ind] = v0.x; normals[ind] = cn0.x; ++ind;
|
||||
vertices[ind] = v0.y; normals[ind] = cn0.y; ++ind;
|
||||
vertices[ind] = v0.z; normals[ind] = cn0.z; ++ind;
|
||||
vertices[ind] = v1.x; normals[ind] = cn0.x; ++ind;
|
||||
vertices[ind] = v1.y; normals[ind] = cn0.y; ++ind;
|
||||
vertices[ind] = v1.z; normals[ind] = cn0.z; ++ind;
|
||||
vertices[ind] = v2.x; normals[ind] = cn0.x; ++ind;
|
||||
vertices[ind] = v2.y; normals[ind] = cn0.y; ++ind;
|
||||
vertices[ind] = v2.z; normals[ind] = cn0.z; ++ind;
|
||||
if (has_uv) {
|
||||
uvs[induv] = puvws[cf.p0].x; ++induv;
|
||||
uvs[induv] = puvws[cf.p0].y; ++induv;
|
||||
uvs[induv] = puvws[cf.p1].x; ++induv;
|
||||
uvs[induv] = puvws[cf.p1].y; ++induv;
|
||||
uvs[induv] = puvws[cf.p2].x; ++induv;
|
||||
uvs[induv] = puvws[cf.p2].y; ++induv;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < faces.size(); ++i) {
|
||||
cf = faces[i];
|
||||
csg = smooth[i];
|
||||
v0 = points[cf.p0];
|
||||
v1 = points[cf.p1];
|
||||
v2 = points[cf.p2];
|
||||
|
||||
cn0 = cn1 = cn2 = fnormals[i];
|
||||
ncnt0 = ncnt1 = ncnt2 = 1;
|
||||
for (int j = 0; j < faces.size(); ++j) {
|
||||
if (csg != smooth[j] || j == i) continue;
|
||||
if (faces[j].p0 == cf.p0 || faces[j].p1 == cf.p0 || faces[j].p2 == cf.p0 ||
|
||||
points[faces[j].p0] == v0 || points[faces[j].p1] == v0 || points[faces[j].p2] == v0) {
|
||||
cn0 += fnormals[j];
|
||||
++ncnt0;
|
||||
}
|
||||
if (faces[j].p0 == cf.p1 || faces[j].p1 == cf.p1 || faces[j].p2 == cf.p1 ||
|
||||
points[faces[j].p0] == v1 || points[faces[j].p1] == v1 || points[faces[j].p2] == v1) {
|
||||
cn1 += fnormals[j];
|
||||
++ncnt1;
|
||||
}
|
||||
if (faces[j].p0 == cf.p2 || faces[j].p1 == cf.p2 || faces[j].p2 == cf.p2 ||
|
||||
points[faces[j].p0] == v2 || points[faces[j].p1] == v2 || points[faces[j].p2] == v2) {
|
||||
cn2 += fnormals[j];
|
||||
++ncnt2;
|
||||
}
|
||||
}
|
||||
cn0 /= ncnt0;
|
||||
cn1 /= ncnt1;
|
||||
cn2 /= ncnt2;
|
||||
vertices[ind] = v0.x; normals[ind] = cn0.x; ++ind;
|
||||
vertices[ind] = v0.y; normals[ind] = cn0.y; ++ind;
|
||||
vertices[ind] = v0.z; normals[ind] = cn0.z; ++ind;
|
||||
vertices[ind] = v1.x; normals[ind] = cn1.x; ++ind;
|
||||
vertices[ind] = v1.y; normals[ind] = cn1.y; ++ind;
|
||||
vertices[ind] = v1.z; normals[ind] = cn1.z; ++ind;
|
||||
vertices[ind] = v2.x; normals[ind] = cn2.x; ++ind;
|
||||
vertices[ind] = v2.y; normals[ind] = cn2.y; ++ind;
|
||||
vertices[ind] = v2.z; normals[ind] = cn2.z; ++ind;
|
||||
if (has_uv) {
|
||||
uvs[induv] = puvws[cf.p0].x; ++induv;
|
||||
uvs[induv] = puvws[cf.p0].y; ++induv;
|
||||
uvs[induv] = puvws[cf.p1].x; ++induv;
|
||||
uvs[induv] = puvws[cf.p1].y; ++induv;
|
||||
uvs[induv] = puvws[cf.p2].x; ++induv;
|
||||
uvs[induv] = puvws[cf.p2].y; ++induv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GLObjectBase * loadFrom3DSFile(const QString & filepath, double scale) {
|
||||
QFile f(filepath);
|
||||
if (!f.exists()) {
|
||||
qDebug() << "[Loader 3DS] Error: can`t open \"" + filepath + "\"";
|
||||
return 0;
|
||||
}
|
||||
f.open(QIODevice::ReadOnly);
|
||||
QDataStream stream(&f);
|
||||
//QVector<Material> materials;
|
||||
QVector<uint> smooth;
|
||||
GLObjectBase * root = new GLObjectBase(), * co = 0;
|
||||
Loader3DS::Chunk cc;
|
||||
Loader3DS::Face face;
|
||||
Vector3d pos;
|
||||
QString str;
|
||||
ushort cnt;
|
||||
float fl, fl1, matrix[3][3];
|
||||
uint col;
|
||||
root->setName(QFileInfo(f).baseName());
|
||||
while (!stream.atEnd()) {
|
||||
stream.readRawData((char * )&cc, sizeof(cc));
|
||||
switch (cc.id) {
|
||||
case LOADER_3DS_CHUNK_MAIN: /*qDebug() << "main" << cc.size;*/ break;
|
||||
case LOADER_3DS_CHUNK_OBJECTS: /*qDebug() << " objects" << cc.size;*/ break;
|
||||
case LOADER_3DS_CHUNK_OBJECT:
|
||||
if (co != 0) {
|
||||
Loader3DS::init3DSMesh(co, smooth);
|
||||
root->addChild(co);
|
||||
}
|
||||
co = new GLObjectBase();
|
||||
co->setName(readCharsUntilNull(stream));
|
||||
smooth.clear();
|
||||
//qDebug() << " object" << co->name();
|
||||
break;
|
||||
case LOADER_3DS_CHUNK_MESH: /*qDebug() << " mesh" << cc.size;*/ break;
|
||||
case LOADER_3DS_CHUNK_VERTLIST:
|
||||
stream.readRawData((char * )&cnt, sizeof(ushort));
|
||||
co->points.resize(cnt);
|
||||
//qDebug() << " vertices" << cnt;
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
stream.readRawData((char * )&co->points[i].x, sizeof(float));
|
||||
stream.readRawData((char * )&co->points[i].y, sizeof(float));
|
||||
stream.readRawData((char * )&co->points[i].z, sizeof(float));
|
||||
co->points[i] *= scale;
|
||||
}
|
||||
break;
|
||||
case LOADER_3DS_CHUNK_FACELIST:
|
||||
stream.readRawData((char * )&cnt, sizeof(ushort));
|
||||
co->faces.resize(cnt);
|
||||
//qDebug() << " faces" << cnt;
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
stream.readRawData((char * )&face, sizeof(Loader3DS::Face));
|
||||
co->faces[i].p0 = face.v0;
|
||||
co->faces[i].p1 = face.v1;
|
||||
co->faces[i].p2 = face.v2;
|
||||
}
|
||||
break;
|
||||
case LOADER_3DS_CHUNK_MAPLIST:
|
||||
stream.readRawData((char * )&cnt, sizeof(ushort));
|
||||
co->puvws.resize(cnt);
|
||||
//qDebug() << " texcoords" << cnt;
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
stream.readRawData((char * )&co->puvws[i].x, sizeof(float));
|
||||
stream.readRawData((char * )&co->puvws[i].y, sizeof(float));
|
||||
}
|
||||
break;
|
||||
case LOADER_3DS_CHUNK_SMOOTH:
|
||||
cnt = co->faces.size();
|
||||
smooth.resize(cnt);
|
||||
//qDebug() << " smooth" << cnt;
|
||||
for (int i = 0; i < cnt; ++i)
|
||||
stream.readRawData((char * )&smooth[i], sizeof(uint));
|
||||
break;
|
||||
case LOADER_3DS_CHUNK_TRMATRIX:
|
||||
//qDebug() << co->name();
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int j = 0; j < 3; ++j)
|
||||
stream.readRawData((char * )&(matrix[i][j]), sizeof(float));
|
||||
//qDebug() << matrix[i][0] << matrix[i][1] << matrix[i][2];
|
||||
}
|
||||
stream.readRawData((char * )&pos, sizeof(Vector3d));
|
||||
pos *= scale;
|
||||
//qDebug() << "pos =" << pos;
|
||||
co->setPos(pos.toQVector3D());
|
||||
break;
|
||||
case LOADER_3DS_CHUNK_LIGHT:
|
||||
//qDebug() << " light" << cc.size;
|
||||
str = co->name();
|
||||
delete co;
|
||||
co = new Light();
|
||||
co->setName(str);
|
||||
stream.readRawData((char * )&pos, sizeof(Vector3d));
|
||||
pos *= scale;
|
||||
co->setPos(pos.toQVector3D());
|
||||
break;
|
||||
case LOADER_3DS_CHUNK_SPOTLIGHT:
|
||||
stream.readRawData((char * )&pos, sizeof(Vector3d));
|
||||
pos *= scale;
|
||||
globject_cast<Light * >(co)->light_type = Light::Cone;
|
||||
globject_cast<Light * >(co)->direction = (pos.toQVector3D() - co->pos()).normalized();
|
||||
stream.readRawData((char * )&fl1, sizeof(float));
|
||||
stream.readRawData((char * )&fl, sizeof(float));
|
||||
fl1 /= 2.f; fl /= 2.f;
|
||||
globject_cast<Light * >(co)->angle_spread = fl;
|
||||
globject_cast<Light * >(co)->angle_decay_exp = (fl - fl1) / fl * 16.;
|
||||
//qDebug() << "spotlight" << globject_cast<Light * >(co)->direction << globject_cast<Light * >(co)->angle_spread;
|
||||
break;
|
||||
case LOADER_3DS_CHUNK_LIGHT_OFF:
|
||||
stream.skipRawData(cc.size - 6);
|
||||
co->hide();
|
||||
break;
|
||||
case LOADER_3DS_CHUNK_ATTENUATION_ON:
|
||||
stream.skipRawData(cc.size - 6);
|
||||
fl = globject_cast<Light * >(co)->decay_end;
|
||||
//fl1 = globject_cast<Light * >(co)->decay_start;
|
||||
globject_cast<Light * >(co)->decay_quadratic = 4. / fl;
|
||||
//qDebug() << "decay" << globject_cast<Light * >(co)->decay_quadratic;
|
||||
break;
|
||||
case LOADER_3DS_CHUNK_COLOR_F:
|
||||
stream.readRawData((char * )&pos, sizeof(Vector3d));
|
||||
co->setColor(QColor::fromRgbF(pos.x, pos.y, pos.z));
|
||||
//qDebug() << " color_f" << co->color();
|
||||
break;
|
||||
case LOADER_3DS_CHUNK_COLOR_B:
|
||||
stream.readRawData((char * )&col, 3);
|
||||
co->setColor(QColor::fromRgb(((uchar * )&col)[0], ((uchar * )&col)[1], ((uchar * )&col)[2]));
|
||||
//qDebug() << " color_b" << co->color();
|
||||
break;
|
||||
case LOADER_3DS_CHUNK_MULTIPLIER:
|
||||
stream.readRawData((char * )&fl, sizeof(float));
|
||||
globject_cast<Light * >(co)->intensity = fl;
|
||||
//qDebug() << " multiplier" << fl;
|
||||
break;
|
||||
case LOADER_3DS_CHUNK_RANGE_START:
|
||||
stream.readRawData((char * )&fl, sizeof(float));
|
||||
globject_cast<Light * >(co)->decay_start = fl;
|
||||
//qDebug() << " range start" << fl;
|
||||
break;
|
||||
case LOADER_3DS_CHUNK_RANGE_END:
|
||||
stream.readRawData((char * )&fl, sizeof(float));
|
||||
globject_cast<Light * >(co)->decay_end = fl;
|
||||
//qDebug() << " range end" << fl;
|
||||
break;
|
||||
default: /*qDebug() << "???" << QString::number(cc.id, 16).rightJustified(4, '0') << cc.size;*/ stream.skipRawData(cc.size - 6);
|
||||
}
|
||||
}
|
||||
if (co != 0) {
|
||||
Loader3DS::init3DSMesh(co, smooth);
|
||||
root->addChild(co);
|
||||
}
|
||||
qDebug() << "[Loader 3DS] Loaded" << root->childCount() << "objects from" << filepath;
|
||||
return root;
|
||||
}
|
||||
72
qglview/loader_3ds.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOADER_3DS_H
|
||||
#define LOADER_3DS_H
|
||||
|
||||
#include "gltexture_manager.h"
|
||||
#include "globject.h"
|
||||
#include <QGLWidget>
|
||||
#include <QFileInfo>
|
||||
#include <QDateTime>
|
||||
|
||||
#define LOADER_3DS_CHUNK_MAIN 0x4D4D // [-] сцена
|
||||
#define LOADER_3DS_CHUNK_COLOR_F 0x0010 // [+] цвет во float
|
||||
#define LOADER_3DS_CHUNK_COLOR_B 0x0011 // [+] цвет в byte
|
||||
#define LOADER_3DS_CHUNK_OBJECTS 0x3D3D // [-] всяческие объекты
|
||||
#define LOADER_3DS_CHUNK_OBJECT 0x4000 // [+] объект
|
||||
#define LOADER_3DS_CHUNK_MESH 0x4100 // [-] mesh-объект
|
||||
#define LOADER_3DS_CHUNK_VERTLIST 0x4110 // [+] список вершин
|
||||
#define LOADER_3DS_CHUNK_FACELIST 0x4120 // [+] список граней
|
||||
#define LOADER_3DS_CHUNK_FACEMAT 0x4130 // [+] материалы граней
|
||||
#define LOADER_3DS_CHUNK_MAPLIST 0x4140 // [+] текстурные координаты
|
||||
#define LOADER_3DS_CHUNK_SMOOTH 0x4150 // [+] группы сглаживания
|
||||
#define LOADER_3DS_CHUNK_TRMATRIX 0x4160 // [+] матрица перевода
|
||||
#define LOADER_3DS_CHUNK_LIGHT 0x4600 // [+] источник света
|
||||
#define LOADER_3DS_CHUNK_SPOTLIGHT 0x4610 // [+]
|
||||
#define LOADER_3DS_CHUNK_LIGHT_OFF 0x4620 // [+]
|
||||
#define LOADER_3DS_CHUNK_ATTENUATION_ON 0x4625 // [+]
|
||||
#define LOADER_3DS_CHUNK_RANGE_START 0x4659 // [+]
|
||||
#define LOADER_3DS_CHUNK_RANGE_END 0x465A // [+]
|
||||
#define LOADER_3DS_CHUNK_MULTIPLIER 0x465B // [+]
|
||||
#define LOADER_3DS_CHUNK_CAMERA 0x4700 // [+] объект-камера
|
||||
#define LOADER_3DS_CHUNK_MATERIAL 0xAFFF // [-] материал
|
||||
#define LOADER_3DS_CHUNK_MATNAME 0xA000 // [+] название материала
|
||||
#define LOADER_3DS_CHUNK_TEXTURE 0xA200 // [-] текстура материала
|
||||
#define LOADER_3DS_CHUNK_MAPFILE 0xA300 // [+] имя файла текстуры
|
||||
|
||||
|
||||
namespace Loader3DS {
|
||||
#pragma pack(push, 1)
|
||||
struct Chunk {
|
||||
ushort id;
|
||||
uint size;
|
||||
};
|
||||
struct Face {
|
||||
ushort v0;
|
||||
ushort v1;
|
||||
ushort v2;
|
||||
ushort flags;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
void init3DSMesh(GLObjectBase * o, const QVector<uint> & smooth);
|
||||
}
|
||||
|
||||
GLObjectBase * loadFrom3DSFile(const QString & filepath, double scale = 1.0);
|
||||
|
||||
#endif // LOADER_3DS_H
|
||||
385
qglview/loader_ase.cpp
Normal file
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "loader_ase.h"
|
||||
|
||||
|
||||
void LoaderASE::initASEMesh(GLObjectBase * o) {
|
||||
QVector<GLfloat> & vertices(o->VBO().vertices()), & normals(o->VBO().normals()), & uvs(o->VBO().texcoords());
|
||||
QVector<Vector3d> & points(o->points), & puvws(o->puvws), & fnormals(o->normals);
|
||||
QVector<Vector3i> & faces(o->faces);
|
||||
Vector3d pos = Vector3d(o->pos());
|
||||
bool has_uv = !puvws.isEmpty(), has_norms = !fnormals.isEmpty();
|
||||
Vector3i cf;
|
||||
Vector3d v0, v1, v2, cn0, cn1, cn2;
|
||||
uint ni = 0;
|
||||
for (int i = 0; i < points.size(); ++i)
|
||||
points[i] -= pos;
|
||||
if (!has_norms) {
|
||||
fnormals.resize(faces.size() * 3);
|
||||
for (int i = 0; i < faces.size(); ++i) {
|
||||
cf = faces[i];
|
||||
v0 = points[cf.p0];
|
||||
v1 = points[cf.p1];
|
||||
v2 = points[cf.p2];
|
||||
cn0 = ((v1 - v0) * (v2 - v0)).normalized();
|
||||
fnormals[ni] = cn0; ++ni;
|
||||
fnormals[ni] = cn0; ++ni;
|
||||
fnormals[ni] = cn0; ++ni;
|
||||
}
|
||||
}
|
||||
uint fcnt = faces.size() * 3;
|
||||
vertices.resize(fcnt * 3);
|
||||
normals.resize(vertices.size());
|
||||
if (has_uv) uvs.resize(fcnt * 2);
|
||||
uint ind = 0, induv = 0;
|
||||
qDebug() << "init ase" << faces.size() << "faces";
|
||||
ni = 0;
|
||||
for (int i = 0; i < faces.size(); ++i) {
|
||||
cf = faces[i];
|
||||
v0 = points[cf.p0];
|
||||
v1 = points[cf.p1];
|
||||
v2 = points[cf.p2];
|
||||
cn0 = fnormals[ni]; ++ni;
|
||||
cn1 = fnormals[ni]; ++ni;
|
||||
cn2 = fnormals[ni]; ++ni;
|
||||
vertices[ind] = v0.x; normals[ind] = cn0.x; ++ind;
|
||||
vertices[ind] = v0.y; normals[ind] = cn0.y; ++ind;
|
||||
vertices[ind] = v0.z; normals[ind] = cn0.z; ++ind;
|
||||
vertices[ind] = v1.x; normals[ind] = cn1.x; ++ind;
|
||||
vertices[ind] = v1.y; normals[ind] = cn1.y; ++ind;
|
||||
vertices[ind] = v1.z; normals[ind] = cn1.z; ++ind;
|
||||
vertices[ind] = v2.x; normals[ind] = cn2.x; ++ind;
|
||||
vertices[ind] = v2.y; normals[ind] = cn2.y; ++ind;
|
||||
vertices[ind] = v2.z; normals[ind] = cn2.z; ++ind;
|
||||
if (has_uv) {
|
||||
uvs[induv] = puvws[cf.p0].x; ++induv;
|
||||
uvs[induv] = puvws[cf.p0].y; ++induv;
|
||||
uvs[induv] = puvws[cf.p1].x; ++induv;
|
||||
uvs[induv] = puvws[cf.p1].y; ++induv;
|
||||
uvs[induv] = puvws[cf.p2].x; ++induv;
|
||||
uvs[induv] = puvws[cf.p2].y; ++induv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GLObjectBase * loadFromASEFile(const QString & filepath, double scale) {
|
||||
QFile f(filepath);
|
||||
if (!f.exists()) {
|
||||
qDebug() << "[Loader ASE] Error: can`t open" << filepath;
|
||||
return 0;
|
||||
}
|
||||
f.open(QIODevice::ReadOnly);
|
||||
//QVector<Material> materials;
|
||||
GLObjectBase * root = new GLObjectBase(), * co = 0;
|
||||
root->setName(QFileInfo(f).baseName());
|
||||
QTextStream stream(&f);
|
||||
QVector<Material> materials;
|
||||
QVector<Vector3d> points, puvws;
|
||||
QVector<Vector3i> faces, uvws;
|
||||
QVector<Vector3d> normals;
|
||||
Vector3d cv;
|
||||
int mst = -1, pst;//, mat_ind;
|
||||
QString line, cname;
|
||||
|
||||
|
||||
/// Parse materials
|
||||
while (mst < 0 && !stream.atEnd()) {
|
||||
line = stream.readLine();
|
||||
mst = line.indexOf("MATERIAL_LIST {");
|
||||
}
|
||||
line = stream.readLine().trimmed();
|
||||
mst = line.indexOf("MATERIAL_COUNT");
|
||||
materials.resize(line.right(line.length() - mst - 14).toInt());
|
||||
//qDebug() << materials.size() << "materials";
|
||||
for (int i = 0; i < materials.size(); ++i) {
|
||||
materials[i].diffuse.bitmap_id = 0;
|
||||
mst = -1;
|
||||
while (mst < 0 && !stream.atEnd()) {
|
||||
line = stream.readLine();
|
||||
mst = line.indexOf("MATERIAL " + QString::number(i) + " {");
|
||||
}
|
||||
/// Parse material i
|
||||
while (line != "}" && !stream.atEnd()) {
|
||||
line = stream.readLine().trimmed();
|
||||
if (line.left(17) == "*MATERIAL_DIFFUSE") {materials[i].color_diffuse = colorFromString(line.right(line.length() - 18)); continue;} //qDebug() << "diffuse " << i << " = " << colorFromString(line.right(line.length() - 18));
|
||||
if (line.left(18) == "*MATERIAL_SPECULAR") {materials[i].color_specular = colorFromString(line.right(line.length() - 19)); continue;} //qDebug() << "specular " << i << " = " << colorFromString(line.right(line.length() - 19));
|
||||
if (line.left(23) == "*MATERIAL_SHINESTRENGTH") {materials[i].shine_strength = line.right(line.length() - 24).toFloat(); continue;}
|
||||
if (line.left(15) == "*MATERIAL_SHINE") {materials[i].shine = line.right(line.length() - 16).toFloat() * 100.; continue;}
|
||||
if (line.left(22) == "*MATERIAL_TRANSPARENCY") {materials[i].transparency = line.right(line.length() - 23).toFloat(); continue;}
|
||||
if (line.left(12) == "*MAP_DIFFUSE") {
|
||||
line = stream.readLine().trimmed();
|
||||
while (line.left(11) != "*MAP_AMOUNT" && !stream.atEnd()) line = stream.readLine().trimmed();
|
||||
materials[i].bump.bitmap_amount = line.right(line.length() - 12).toFloat();
|
||||
while (line.left(7) != "*BITMAP" && !stream.atEnd()) line = stream.readLine().trimmed();
|
||||
materials[i].diffuse.bitmap_path = line.mid(9, line.length() - 10);
|
||||
/*if (!materials[i].diffuse.bitmap_path.isEmpty()) {
|
||||
materials[i].diffuse.bitmap_id = currentQGLView->bindTexture(QImage(materials[i].diffuse.bitmap_path));
|
||||
parent->textures << materials[i].diffuse.bitmap_id;
|
||||
}
|
||||
qDebug() << materials[i].diffuse.bitmap_path << ", bind to" << materials[i].diffuse.bitmap_id;*/
|
||||
while (line != "}" && !stream.atEnd()) line = stream.readLine().trimmed();
|
||||
line = "";
|
||||
continue;
|
||||
}
|
||||
if (line.left(9) == "*MAP_BUMP") {
|
||||
line = stream.readLine().trimmed();
|
||||
while (line.left(11) != "*MAP_AMOUNT" && !stream.atEnd()) line = stream.readLine().trimmed();
|
||||
materials[i].bump.bitmap_amount = line.right(line.length() - 12).toFloat();
|
||||
//qDebug() << "bump amount" << materials[i].bump.bitmap_amount;
|
||||
while (line.left(7) != "*BITMAP" && !stream.atEnd()) line = stream.readLine().trimmed();
|
||||
materials[i].bump.bitmap_path = line.mid(9, line.length() - 10);
|
||||
/*if (!materials[i].bump.bitmap_path.isEmpty()) {
|
||||
materials[i].bump.bitmap_id = currentQGLView->bindTexture(QImage(materials[i].bump.bitmap_path));
|
||||
parent->textures << materials[i].bump.bitmap_id;
|
||||
}
|
||||
qDebug() << materials[i].bump.bitmap_path << ", bind to" << materials[i].bump.bitmap_id;*/
|
||||
while (line != "}" && !stream.atEnd()) line = stream.readLine().trimmed();
|
||||
line = "";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//bs << materials;
|
||||
/// Geometry objects
|
||||
int cotype = 0;
|
||||
mst = -1;
|
||||
while (mst < 0 && !stream.atEnd()) {
|
||||
line = stream.readLine();
|
||||
if (line.indexOf("GEOMOBJECT {") >= 0 || line.indexOf("LIGHTOBJECT {") >= 0) {
|
||||
if (line.indexOf("GEOMOBJECT {") >= 0) cotype = 0;
|
||||
if (line.indexOf("LIGHTOBJECT {") >= 0) cotype = 1;
|
||||
mst = -1;
|
||||
if (co != 0) {
|
||||
co->points = points;
|
||||
co->faces = faces;
|
||||
co->normals = normals;
|
||||
co->uvws = uvws;
|
||||
LoaderASE::initASEMesh(co);
|
||||
root->addChild(co);
|
||||
}
|
||||
co = new GLObjectBase();
|
||||
while (mst < 0 && !stream.atEnd()) {
|
||||
line = stream.readLine();
|
||||
mst = line.indexOf("NODE_NAME");
|
||||
}
|
||||
cname = line.right(line.length() - mst - 10);
|
||||
co->setName(cname.mid(1, cname.length() - 2));
|
||||
qDebug() << co->name();
|
||||
}
|
||||
mst = -1;
|
||||
switch (cotype) {
|
||||
case 0:
|
||||
//qDebug() << "object";
|
||||
while (mst < 0 && !stream.atEnd()) {
|
||||
line = stream.readLine();
|
||||
mst = line.indexOf("MESH {");
|
||||
}
|
||||
mst = -1;
|
||||
while (mst < 0 && !stream.atEnd()) {
|
||||
line = stream.readLine();
|
||||
mst = line.indexOf("MESH_NUMVERTEX ");
|
||||
}
|
||||
points.resize(line.right(line.length() - mst - 15).toInt());
|
||||
//qDebug() << points.size() << "vertices";
|
||||
mst = -1;
|
||||
while (mst < 0 && !stream.atEnd()) {
|
||||
line = stream.readLine();
|
||||
mst = line.indexOf("MESH_NUMFACES ");
|
||||
}
|
||||
faces.resize(line.right(line.length() - mst - 14).toInt());
|
||||
normals.resize(faces.size() * 3);
|
||||
//qDebug() << faces.size() << "faces";
|
||||
//uvws.resize(faces.size());
|
||||
/// Points
|
||||
mst = -1;
|
||||
while (mst < 0 && !stream.atEnd()) {
|
||||
line = stream.readLine();
|
||||
mst = line.indexOf("MESH_VERTEX_LIST {");
|
||||
}
|
||||
for (int i = 0; i < points.size(); ++i) {
|
||||
line = stream.readLine().trimmed();
|
||||
mst = line.indexOf("MESH_VERTEX");
|
||||
points[i] = Vector3d(line.right(line.length() - mst - 17)) * scale;
|
||||
//qDebug() << points[i];
|
||||
}
|
||||
/// Faces
|
||||
mst = -1;
|
||||
while (mst < 0 && !stream.atEnd()) {
|
||||
line = stream.readLine();
|
||||
mst = line.indexOf("MESH_FACE_LIST {");
|
||||
}
|
||||
for (int i = 0; i < faces.size(); ++i) {
|
||||
line = stream.readLine().trimmed();
|
||||
mst = line.indexOf("MESH_FACE");
|
||||
line = line.right(line.length() - mst - 15);
|
||||
mst = line.indexOf("A:"); line = line.right(line.length() - mst - 2);
|
||||
mst = line.indexOf("B:");
|
||||
faces[i].p0 = line.left(mst).toInt(); line = line.right(line.length() - mst - 2);
|
||||
mst = line.indexOf("C:");
|
||||
faces[i].p1 = line.left(mst).toInt(); line = line.right(line.length() - mst - 2);
|
||||
mst = line.indexOf("AB");
|
||||
faces[i].p2 = line.left(mst).toInt();
|
||||
//qDebug() << faces[i];
|
||||
}
|
||||
/// Texture coordinates
|
||||
mst = -1;
|
||||
pst = stream.pos();
|
||||
while (mst < 0 && !stream.atEnd()) {
|
||||
line = stream.readLine();
|
||||
mst = line.indexOf("MESH_NUMTVERTEX ");
|
||||
}
|
||||
if (mst >= 0) {
|
||||
puvws.resize(line.right(line.length() - mst - 16).toInt());
|
||||
//qDebug() << puvws.size() << "tvertices";
|
||||
mst = -1;
|
||||
while (mst < 0 && !stream.atEnd()) {
|
||||
line = stream.readLine();
|
||||
mst = line.indexOf("MESH_TVERTLIST {");
|
||||
}
|
||||
for (int i = 0; i < puvws.size(); ++i) {
|
||||
line = stream.readLine().trimmed();
|
||||
mst = line.indexOf("MESH_TVERT"); line = line.right(line.length() - mst - 10);
|
||||
mst = line.indexOf("\t"); line = line.right(line.length() - mst - 1);
|
||||
puvws[i] = Vector3d(line);
|
||||
}
|
||||
mst = -1;
|
||||
while (mst < 0 && !stream.atEnd()) {
|
||||
line = stream.readLine();
|
||||
mst = line.indexOf("MESH_NUMTVFACES ");
|
||||
}
|
||||
uvws.resize(line.right(line.length() - mst - 16).toInt());
|
||||
mst = -1;
|
||||
while (mst < 0 && !stream.atEnd()) {
|
||||
line = stream.readLine();
|
||||
mst = line.indexOf("MESH_TFACELIST {");
|
||||
}
|
||||
for (int i = 0; i < uvws.size(); ++i) {
|
||||
line = stream.readLine().trimmed();
|
||||
mst = line.indexOf("MESH_TFACE"); line = line.right(line.length() - mst - 10);
|
||||
mst = line.indexOf("\t"); line = line.right(line.length() - mst - 1);
|
||||
uvws[i] = Vector3i(line);
|
||||
}
|
||||
} else {
|
||||
uvws.clear();
|
||||
uvws.resize(faces.size());
|
||||
stream.seek(pst);
|
||||
}
|
||||
if (puvws.size() <= 0) puvws.resize(1);
|
||||
/// Normals
|
||||
mst = -1;
|
||||
while (mst < 0 && !stream.atEnd()) {
|
||||
line = stream.readLine();
|
||||
mst = line.indexOf("MESH_NORMALS {");
|
||||
}
|
||||
for (int i = 0; i < faces.size(); ++i) {
|
||||
line = stream.readLine();
|
||||
line = stream.readLine().trimmed(); mst = line.indexOf(" ");
|
||||
line = line.right(line.length() - mst - 1); normals[i * 3] = Vector3d(line);
|
||||
line = stream.readLine().trimmed(); mst = line.indexOf(" ");
|
||||
line = line.right(line.length() - mst - 1); normals[i * 3 + 1] = Vector3d(line);
|
||||
line = stream.readLine().trimmed(); mst = line.indexOf(" ");
|
||||
line = line.right(line.length() - mst - 1); normals[i * 3 + 2] = Vector3d(line);
|
||||
//qDebug() << normals[i][0] << normals[i][1] << normals[i][2];
|
||||
}
|
||||
/// Material index
|
||||
mst = -1;
|
||||
while (mst < 0 && !stream.atEnd()) {
|
||||
line = stream.readLine();
|
||||
mst = line.indexOf("MATERIAL_REF ");
|
||||
}
|
||||
//mat_ind = line.right(line.length() - mst - 13).toInt();
|
||||
//qDebug() << mat_ind.back();
|
||||
if (points.size() == 0 || faces.size() == 0) {
|
||||
mst = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/// Compiling into GLList
|
||||
/*glNewList(model, GL_COMPILE);
|
||||
if (mat_ind < 0 || mat_ind >= materials.size()) {
|
||||
mat_diffuse[0] = cfr;
|
||||
mat_diffuse[1] = cfg;
|
||||
mat_diffuse[2] = cfb;
|
||||
glColor3f(cfr, cfg, cfb);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_none);
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, 0.);
|
||||
} else {
|
||||
materials[mat_ind].apply();
|
||||
//parent->material_ = materials[mat_ind];
|
||||
}
|
||||
glBegin(GL_TRIANGLES);
|
||||
if (normals_) {
|
||||
for (int i = 0; i < faces.size(); ++i) {
|
||||
glNormal3d(normals[i][0].x, normals[i][0].y, normals[i][0].z);
|
||||
glTexCoord3d(puvws[uvws[i].p0].x, puvws[uvws[i].p0].y, puvws[uvws[i].p0].z);
|
||||
cv = points[faces[i].p0] * scale; glVertex3d(cv.x, cv.y, cv.z);
|
||||
glNormal3d(normals[i][1].x, normals[i][1].y, normals[i][1].z);
|
||||
glTexCoord3d(puvws[uvws[i].p1].x, puvws[uvws[i].p1].y, puvws[uvws[i].p1].z);
|
||||
cv = points[faces[i].p1] * scale; glVertex3d(cv.x, cv.y, cv.z);
|
||||
glNormal3d(normals[i][2].x, normals[i][2].y, normals[i][2].z);
|
||||
glTexCoord3d(puvws[uvws[i].p2].x, puvws[uvws[i].p2].y, puvws[uvws[i].p2].z);
|
||||
cv = points[faces[i].p2] * scale; glVertex3d(cv.x, cv.y, cv.z);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < faces.size(); ++i) {
|
||||
glTexCoord3d(puvws[uvws[i].p0].x, puvws[uvws[i].p0].y, puvws[uvws[i].p0].z);
|
||||
cv = points[faces[i].p0] * scale; glVertex3d(cv.x, cv.y, cv.z);
|
||||
glTexCoord3d(puvws[uvws[i].p1].x, puvws[uvws[i].p1].y, puvws[uvws[i].p1].z);
|
||||
cv = points[faces[i].p1] * scale; glVertex3d(cv.x, cv.y, cv.z);
|
||||
glTexCoord3d(puvws[uvws[i].p2].x, puvws[uvws[i].p2].y, puvws[uvws[i].p2].z);
|
||||
cv = points[faces[i].p2] * scale; glVertex3d(cv.x, cv.y, cv.z);
|
||||
}
|
||||
}
|
||||
glEnd();*/
|
||||
|
||||
///// Save binary
|
||||
//bs << mat_ind << points << faces << puvws << uvws << normals;
|
||||
break;
|
||||
case 1:
|
||||
qDebug() << "light";
|
||||
mst = -1;
|
||||
while (mst < 0 && !stream.atEnd()) {
|
||||
line = stream.readLine();
|
||||
mst = line.indexOf("MESH_NORMALS {");
|
||||
}
|
||||
break;
|
||||
}
|
||||
/// Continue
|
||||
mst = -1;
|
||||
}
|
||||
f.close();
|
||||
if (co != 0) {
|
||||
co->points = points;
|
||||
co->faces = faces;
|
||||
co->normals = normals;
|
||||
co->uvws = uvws;
|
||||
LoaderASE::initASEMesh(co);
|
||||
root->addChild(co);
|
||||
}
|
||||
/*parent->points = points;
|
||||
parent->puvws = puvws;
|
||||
parent->faces = faces;
|
||||
parent->uvws = uvws;
|
||||
parent->normals = normals;
|
||||
return model;*/
|
||||
return root;
|
||||
}
|
||||
33
qglview/loader_ase.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOADER_ASE_H
|
||||
#define LOADER_ASE_H
|
||||
|
||||
#include "globject.h"
|
||||
#include <QGLWidget>
|
||||
#include <QFileInfo>
|
||||
#include <QDateTime>
|
||||
|
||||
namespace LoaderASE {
|
||||
void initASEMesh(GLObjectBase * o);
|
||||
}
|
||||
|
||||
GLObjectBase * loadFromASEFile(const QString & filepath, double scale = 1.0);
|
||||
|
||||
#endif // LOADER_ASE_H
|
||||
32
qglview/main.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Stanley Designer
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCleanlooksStyle>
|
||||
#include <QDir>
|
||||
#include "mainwindow.h"
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
QApplication a(argc, argv);
|
||||
//QApplication::setStyle(new QCleanlooksStyle());
|
||||
QDir::setCurrent(a.applicationDirPath());
|
||||
//a.setWindowIcon(QIcon(":/icons/peri4_paint.png"));
|
||||
MainWindow w;
|
||||
w.show();
|
||||
return a.exec();
|
||||
}
|
||||
225
qglview/mainwindow.cpp
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
Stanley Designer
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include <QGraphicsRectItem>
|
||||
|
||||
|
||||
MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow() {
|
||||
setupUi(this);
|
||||
colorHalo->setColor(view->selectionHaloColor());
|
||||
sel_obj = 0;
|
||||
treeProperties->assignObject(view);
|
||||
//spinSliderShine->setDecimals(2);
|
||||
view->setFrameShape(QFrame::NoFrame);
|
||||
view->setRenderer(new RendererDeferredShading(view));
|
||||
view->setMouseSelectionEnabled(true);
|
||||
view->setMouseRotateEnabled(true);
|
||||
view->setBackColor(Qt::lightGray);
|
||||
//view->setLightingMode(QGLView::PerPixel);
|
||||
/*MaterialEditor * o = new MaterialEditor();
|
||||
o->setWindowOpacity(.666);
|
||||
view->addObject(o, Qt::Window);*/
|
||||
view->start(-1);
|
||||
obj = loadFrom3DSFile("data/test.3DS", 0.15);
|
||||
m.reflectivity = 1;
|
||||
m.reflection.loadPathesFromDirectory("data/e");
|
||||
obj->child("sphere001")->setMaterial(m);
|
||||
|
||||
|
||||
//m.shine = 40;
|
||||
//m.shine_strength = 1;
|
||||
//m.diffuse.bitmap_path = "celtic_010.jpg";
|
||||
//m.bump.bitmap_path = "celtic_010n.jpg";
|
||||
/*obj->child("cone")->setMaterial(m);
|
||||
m.diffuse.bitmap_path = "proj_plane_d.tga";
|
||||
m.bump.bitmap_path = "proj_plane_n.tga";
|
||||
obj->child("tor")->setMaterial(m);
|
||||
m.reflectivity = 1.;
|
||||
obj->child("sphere")->setMaterial(m);*/
|
||||
//obj->child("teapot")->setRenderMode(GLObjectBase::Point);
|
||||
//obj->child("teapot")->setLineWidth(2.);
|
||||
//obj->child("cone")->setRenderMode(GLObjectBase::Line);
|
||||
view->addObject(obj);
|
||||
view->camera().setAim(obj->child("sphere001")->pos());
|
||||
view->camera().setPos(QVector3D(10, -20, 20));
|
||||
view->camera().flyToDistance(10);
|
||||
//view->light(0)->light_type = Light::Omni;
|
||||
//obj = loadFrom3DSFile("34.3DS", 0.03);
|
||||
//view->addObject(obj);
|
||||
//view->camera().moveUp(5, true);
|
||||
|
||||
ps = new GLParticlesSystem(QVector3D(0,0,5));
|
||||
ps->setEmitterType(GLParticlesSystem::Box);
|
||||
ps->setBirthRate(5);
|
||||
ps->setSize(1.);
|
||||
ps->setLifeDuration(5.);
|
||||
ps->setInitialSpeed(.5);
|
||||
ps->setFadeTime(1.);
|
||||
ps->setSpeedDirectionJitter(1);
|
||||
//ps->setTextureScale(2, 2);
|
||||
ps->setAddVerticalFaceEnabled(true);
|
||||
ps->addForce(QVector3D(0,0,-0.98/20));
|
||||
//ps->material().diffuse.bitmap_path = "expl_07.png";
|
||||
//view->addObject(ps);
|
||||
|
||||
box = new GLPrimitiveCube();
|
||||
box->setSelectable(false);
|
||||
box->setRenderMode(GLObjectBase::Line);
|
||||
box->setLineWidth(2.);
|
||||
view->addObject(box);
|
||||
box->hide();
|
||||
while (view->lightsCount() >= 3) view->removeLight(view->lightsCount() - 1);
|
||||
//view->addObject(box);
|
||||
|
||||
//obj = obj->clone(true);
|
||||
//obj->move(QVector3D(10,10,0));
|
||||
//view->addObject(obj);
|
||||
|
||||
//view->addObject(obj);
|
||||
//obj = obj->clone(true);
|
||||
//obj->move(QVector3D(10,10,0));
|
||||
//view->addObject(obj);
|
||||
/*int h = 0, dh = 360 / view->lights().size();
|
||||
foreach (Light * i, view->lights()) {
|
||||
i->setColor(QColor::fromHsv(h, 255, 255));
|
||||
i->intensity *= 2;
|
||||
h += dh;
|
||||
}*/
|
||||
startTimer(1000/60);
|
||||
|
||||
connect(view, SIGNAL(hoverChanged(GLObjectBase*,GLObjectBase*)), this, SLOT(hoverChanged(GLObjectBase*,GLObjectBase*)));
|
||||
connect(view, SIGNAL(selectionChanged(GLObjectBase*,GLObjectBase*)), this, SLOT(selectionChanged(GLObjectBase*,GLObjectBase*)));
|
||||
connect(view, SIGNAL(glInitializeDone()), this, SLOT(glInit()));
|
||||
connect(matEditor, SIGNAL(changed()), this, SLOT(materialChanged()));
|
||||
//view->addObject(new Light(view->camera().pos()));
|
||||
|
||||
//show();
|
||||
}
|
||||
|
||||
|
||||
MainWindow::~MainWindow() {
|
||||
delete ps;
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::changeEvent(QEvent * e) {
|
||||
QMainWindow::changeEvent(e);
|
||||
/*if (e->type() == QEvent::LanguageChange) {
|
||||
retranslateUi(this);
|
||||
return;
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::timerEvent(QTimerEvent * ) {
|
||||
static double t = 0.;
|
||||
/*obj->child("tor")->rotateX(0.5);
|
||||
obj->child("tor")->rotateZ(0.1);
|
||||
obj->child("cone")->rotateZ(1);
|
||||
obj->child("teapot")->rotateY(sin(t));
|
||||
obj->child("sphere")->setPosZ(fabs(sin(t)*5)-0.75);*/
|
||||
t += 0.1;
|
||||
setWindowTitle(QString::number(view->currentFPS(), 'f', 2));
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_view_glKeyPressEvent(QKeyEvent * e) {
|
||||
if (e->key() != Qt::Key_F11) return;
|
||||
if (view->windowState().testFlag(Qt::WindowFullScreen)) {
|
||||
centralwidget->layout()->addWidget(view);
|
||||
} else {
|
||||
view->setParent(0);
|
||||
view->showFullScreen();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::glInit() {
|
||||
//view->bindTexture(QImage("e/bottom.jpg"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::loadFile(const QString & path) {
|
||||
prev_path = path;
|
||||
QCursor pcur = cursor();
|
||||
setCursor(Qt::WaitCursor);
|
||||
|
||||
setCursor(pcur);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::selectionChanged(GLObjectBase * cur, GLObjectBase * prev) {
|
||||
sel_obj = cur;
|
||||
//qDebug() << "selected" << (cur != 0 ? cur->name() : "0");
|
||||
labelName->setText(cur != 0 ? cur->name() : "");
|
||||
if (cur == 0) box->hide();
|
||||
else {
|
||||
box->setScale(cur->boundingBox().size());
|
||||
box->setPos(cur->boundingBox().pos());
|
||||
Box3D b = cur->boundingBox().movedTo(-cur->boundingBox().center());
|
||||
b.z = -b.z - b.height;
|
||||
ps->setEmitterRect(b);
|
||||
cur->addChild(box);
|
||||
box->show();
|
||||
}
|
||||
objectEditor->setObject(sel_obj);
|
||||
if (sel_obj == 0) return;
|
||||
matEditor->setMaterial(sel_obj->material());
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::materialChanged() {
|
||||
if (sel_obj == 0) return;
|
||||
sel_obj->setMaterial(matEditor->material());
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_pushButton_3_clicked() {
|
||||
QList<GLObjectBase * > ol = view->objects(true);
|
||||
qDebug() << ol.size();
|
||||
foreach (GLObjectBase * i, ol) {
|
||||
i->VBO().rebuffer();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_comboBox_currentIndexChanged(int val) {
|
||||
GLRendererBase * pr = 0;
|
||||
switch (val) {
|
||||
case 0: view->setRenderer(new RendererSimple(view), &pr); break;
|
||||
case 2: view->setRenderer(new RendererDeferredShading(view), &pr); break;
|
||||
}
|
||||
if (pr != 0) delete pr;
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_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->camera().moveForward(spd); break;
|
||||
case Qt::Key_S: view->camera().moveBackward(spd); break;
|
||||
case Qt::Key_A: view->camera().moveLeft(spd); break;
|
||||
case Qt::Key_D: view->camera().moveRight(spd); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
110
qglview/mainwindow.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
Stanley Designer
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_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_mainwindow.h"
|
||||
#include "loader_3ds.h"
|
||||
#include "loader_ase.h"
|
||||
#include "renderer_simple.h"
|
||||
#include "renderer_deferred_shading.h"
|
||||
#include "water_system.h"
|
||||
#include "rope_system.h"
|
||||
|
||||
|
||||
class MainWindow: public QMainWindow, public Ui::MainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MainWindow(QWidget * parent = 0);
|
||||
~MainWindow();
|
||||
|
||||
private:
|
||||
// Qt`s overloaded
|
||||
void changeEvent(QEvent * e);
|
||||
void timerEvent(QTimerEvent * );
|
||||
|
||||
void loadFile(const QString & path);
|
||||
|
||||
QTranslator translator;
|
||||
QString prev_path, dstyle;
|
||||
bool isChanged;
|
||||
|
||||
GLObjectBase * obj, * sel_obj;
|
||||
GLPrimitiveCube * box;
|
||||
GLParticlesSystem * ps;
|
||||
WaterSystem * ws;
|
||||
RopeSystem * rs;
|
||||
Material m;
|
||||
|
||||
private slots:
|
||||
void glInit();
|
||||
void on_actionExit_triggered() {close();}
|
||||
|
||||
void on_spinFOV_valueChanged(double val) {view->setFOV(val);}
|
||||
void on_spinAccom_valueChanged(double val) {view->setAccomodationTime(val);}
|
||||
void on_spinAccomMS_valueChanged(double val) {view->setAccomodationMaxSpeed(val);}
|
||||
void on_spinCubemapSize_valueChanged(double val) {view->setDynamicReflectionsMapSize(val);}
|
||||
void on_spinShadowmapSize_valueChanged(double val) {view->setShadowMapSize(val);}
|
||||
void on_spinHaloFillAlpha_valueChanged(double val) {view->setSelectionHaloFillAlpha(val);}
|
||||
//void on_spinSliderShine_valueChanged(double val) {obj->material().shine_strength = val; obj->setMaterial(obj->material(), true);}
|
||||
//void on_spinSliderRough_valueChanged(double val) {obj->material().shine = val; obj->setMaterial(obj->material(), true);}
|
||||
void on_pushButton_clicked() {view->removeLight(view->lightsCount() - 1); setWindowTitle(QString::number(view->lightsCount()));}
|
||||
void on_pushButton_2_clicked() {view->reloadShaders();}
|
||||
void on_pushButton_3_clicked();
|
||||
void on_comboBox_currentIndexChanged(int val);
|
||||
void on_comboViewRenderMode_currentIndexChanged(int val) {static int modes[] = {GL_POINT, GL_LINE, GL_FILL}; view->setRenderMode((GLObjectBase::RenderMode)modes[val]);}
|
||||
//void on_comboLight_currentIndexChanged(int val) {obj->material().light_model = (Material::LightModel)val; obj->setMaterial(obj->material(), true);}
|
||||
void on_checkSelectionHalo_toggled(bool val) {view->setSelectionHaloEnabled(val);}
|
||||
void on_checkDynamicReflections_toggled(bool val) {view->setDynamicReflectionsEnabled(val);}
|
||||
void on_checkHDR_toggled(bool val) {view->setHDREnabled(val);}
|
||||
void on_checkAccomodation_toggled(bool val) {view->setAccomodationEnabled(val);}
|
||||
void on_checkBloom_toggled(bool val) {view->setBloomEnabled(val);}
|
||||
void on_checkFXAA_toggled(bool val) {view->setFXAAEnabled(val);}
|
||||
void on_checkMSAA_toggled(bool val) {view->setMultisamplingEnabled(val);}
|
||||
void on_checkShadows_toggled(bool val) {view->setShadowsEnabled(val);}
|
||||
void on_checkSoftShadows_toggled(bool val) {view->setSoftShadowsEnabled(val);}
|
||||
void on_checkCameraOrbit_toggled(bool val) {view->setCameraOrbit(val);}
|
||||
void on_colorAmbient_colorChanged(QColor color) {view->setAmbientColor(color);}
|
||||
void on_colorHalo_colorChanged(QColor color) {view->setSelectionHaloColor(color);}
|
||||
void on_view_glKeyPressEvent(QKeyEvent * e);
|
||||
void on_view_keyEvent(Qt::Key k, Qt::KeyboardModifiers m);
|
||||
|
||||
void hoverChanged(GLObjectBase * cur, GLObjectBase * prev) {/*qDebug() << "hovered" << (cur != 0 ? cur->name() : "0") << ", previous" << (prev != 0 ? prev->name() : "0");*/}
|
||||
void selectionChanged(GLObjectBase * cur, GLObjectBase * prev); /*{qDebug() << "selected" << (cur != 0 ? cur->name() : "0") << ", previous" << (prev != 0 ? prev->name() : "0");}*/
|
||||
void materialChanged();
|
||||
|
||||
public slots:
|
||||
|
||||
signals:
|
||||
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
606
qglview/mainwindow.ui
Normal file
@@ -0,0 +1,606 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1246</width>
|
||||
<height>844</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Stanley designer</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset>
|
||||
<normaloff>:/icons/stanley_128.png</normaloff>:/icons/stanley_128.png</iconset>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1">
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_2" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelName">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>View</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>FOV</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="SpinSlider" name="spinFOV">
|
||||
<property name="minimum">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>179.900000000000006</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>60.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>accomodation time</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="SpinSlider" name="spinAccom">
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>256.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>32.000000000000000</double>
|
||||
</property>
|
||||
<property name="squareScale">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>accomodation max speed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="SpinSlider" name="spinAccomMS">
|
||||
<property name="minimum">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="squareScale">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>dynamic cubemap size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="SpinSlider" name="spinCubemapSize">
|
||||
<property name="minimum">
|
||||
<double>16.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>2048.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>512.000000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>16.000000000000000</double>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<double>512.000000000000000</double>
|
||||
</property>
|
||||
<property name="squareScale">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>shadowmap size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="SpinSlider" name="spinShadowmapSize">
|
||||
<property name="minimum">
|
||||
<double>16.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>2048.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>512.000000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>16.000000000000000</double>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<double>512.000000000000000</double>
|
||||
</property>
|
||||
<property name="squareScale">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>remove light</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_2">
|
||||
<property name="text">
|
||||
<string>reload shaders</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_3">
|
||||
<property name="text">
|
||||
<string>rebuff all</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboViewRenderMode">
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>point</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>wireframe</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>solid</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>simple</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>per-pixel</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>deferred shading</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ColorButton" name="colorHalo">
|
||||
<property name="color">
|
||||
<color>
|
||||
<red>10</red>
|
||||
<green>10</green>
|
||||
<blue>10</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="useAlphaChannel">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>halo fill alpha</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="SpinSlider" name="spinHaloFillAlpha">
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.300000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkCameraOrbit">
|
||||
<property name="text">
|
||||
<string>orbit camera</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkSelectionHalo">
|
||||
<property name="text">
|
||||
<string>selection halo</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBadAccum">
|
||||
<property name="text">
|
||||
<string>bad accumulation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkDynamicReflections">
|
||||
<property name="text">
|
||||
<string>dynamic reflections</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkHDR">
|
||||
<property name="text">
|
||||
<string>HDR</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkAccomodation">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>accomodation</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBloom">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>bloom</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkFXAA">
|
||||
<property name="text">
|
||||
<string>FXAA</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkMSAA">
|
||||
<property name="text">
|
||||
<string>MSAA</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkShadows">
|
||||
<property name="text">
|
||||
<string>shadows</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkSoftShadows">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>soft shadows</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>ambient</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ColorButton" name="colorAmbient">
|
||||
<property name="color">
|
||||
<color>
|
||||
<red>10</red>
|
||||
<green>10</green>
|
||||
<blue>10</blue>
|
||||
</color>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>107</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Object</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="GLObjectEditor" name="objectEditor" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_3">
|
||||
<attribute name="title">
|
||||
<string>Material</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="MaterialEditor" name="matEditor" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_4">
|
||||
<attribute name="title">
|
||||
<string>Страница</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="PropertyEditor" name="treeProperties">
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGLView" name="view" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<action name="actionExit">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/icons/application-exit.png</normaloff>:/icons/application-exit.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Exit</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SpinSlider</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>spinslider.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ColorButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>colorbutton.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QGLView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>qglview.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>MaterialEditor</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>material_editor.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>GLObjectEditor</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>globject_editor.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>PropertyEditor</class>
|
||||
<extends>QTreeWidget</extends>
|
||||
<header>propertyeditor.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>checkHDR</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>checkAccomodation</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>92</x>
|
||||
<y>580</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>91</x>
|
||||
<y>605</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>checkHDR</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>checkBloom</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>147</x>
|
||||
<y>580</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>143</x>
|
||||
<y>630</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>checkShadows</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>checkSoftShadows</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>106</x>
|
||||
<y>705</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>108</x>
|
||||
<y>730</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
5
qglview/make_install.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#! /bin/bash
|
||||
cmake .
|
||||
make $@
|
||||
cp -vf *.h /usr/include/
|
||||
cp -vf lib*.so /usr/lib/
|
||||
1
qglview/make_lib.bat
Normal file
@@ -0,0 +1 @@
|
||||
cmake_mgw -DLIB= && make install && qmake && make install
|
||||
192
qglview/material_editor.cpp
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "material_editor.h"
|
||||
|
||||
|
||||
MaterialEditor::MaterialEditor(QWidget * parent): QWidget(parent) {
|
||||
setupUi(this);
|
||||
active = true;
|
||||
}
|
||||
|
||||
|
||||
void MaterialEditor::changeEvent(QEvent * e) {
|
||||
return;
|
||||
QWidget::changeEvent(e);
|
||||
switch (e->type()) {
|
||||
case QEvent::LanguageChange:
|
||||
retranslateUi(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MaterialEditor::setMaterial(const Material & m) {
|
||||
active = false;
|
||||
colorDiffuse->setColor(m.color_diffuse);
|
||||
colorSpecular->setColor(m.color_specular);
|
||||
colorSelfIllum->setColor(m.color_self_illumination);
|
||||
checkGlass->setChecked(m.glass);
|
||||
comboModel->setCurrentIndex((int)m.light_model);
|
||||
spinShine->setValue(m.shine);
|
||||
spinShineStrength->setValue(m.shine_strength);
|
||||
spinTransparent->setValue(m.transparency);
|
||||
spinReflect->setValue(m.reflectivity);
|
||||
spinBump->setValue(m.bump_scale);
|
||||
spinRelief->setValue(m.relief_scale);
|
||||
spinIOF->setValue(m.iof);
|
||||
spinDispersion->setValue(m.dispersion);
|
||||
lineDiffuse->setProperty("GLpath", m.diffuse.bitmap_path); lineDiffuse->setText(QFileInfo(m.diffuse.bitmap_path).fileName());
|
||||
lineBump->setProperty("GLpath", m.bump.bitmap_path); lineBump->setText(QFileInfo(m.bump.bitmap_path).fileName());
|
||||
lineRelief->setProperty("GLpath", m.relief.bitmap_path); lineRelief->setText(QFileInfo(m.relief.bitmap_path).fileName());
|
||||
lineReflFront->setProperty("GLpath", m.reflection.path(0)); lineReflFront->setText(QFileInfo(m.reflection.path(0)).fileName());
|
||||
lineReflBack->setProperty("GLpath", m.reflection.path(1)); lineReflBack->setText(QFileInfo(m.reflection.path(1)).fileName());
|
||||
lineReflLeft->setProperty("GLpath", m.reflection.path(2)); lineReflLeft->setText(QFileInfo(m.reflection.path(2)).fileName());
|
||||
lineReflRight->setProperty("GLpath", m.reflection.path(3)); lineReflRight->setText(QFileInfo(m.reflection.path(3)).fileName());
|
||||
lineReflTop->setProperty("GLpath", m.reflection.path(4)); lineReflTop->setText(QFileInfo(m.reflection.path(4)).fileName());
|
||||
lineReflBottom->setProperty("GLpath", m.reflection.path(5)); lineReflBottom->setText(QFileInfo(m.reflection.path(5)).fileName());
|
||||
active = true;
|
||||
}
|
||||
|
||||
|
||||
Material MaterialEditor::material() {
|
||||
Material m;
|
||||
m.color_diffuse = colorDiffuse->color();
|
||||
m.color_specular = colorSpecular->color();
|
||||
m.color_self_illumination = colorSelfIllum->color();
|
||||
m.glass = checkGlass->isChecked();
|
||||
m.light_model = (Material::LightModel)comboModel->currentIndex();
|
||||
m.shine = spinShine->value();
|
||||
m.shine_strength = spinShineStrength->value();
|
||||
m.transparency = spinTransparent->value();
|
||||
m.reflectivity = spinReflect->value();
|
||||
m.bump_scale = spinBump->value();
|
||||
m.relief_scale = spinRelief->value();
|
||||
m.iof = spinIOF->value();
|
||||
m.dispersion = spinDispersion->value();
|
||||
m.diffuse.bitmap_path = lineDiffuse->property("GLpath").toString();
|
||||
m.bump.bitmap_path = lineBump->property("GLpath").toString();
|
||||
m.relief.bitmap_path = lineRelief->property("GLpath").toString();
|
||||
m.reflection.setPath(0, lineReflFront->property("GLpath").toString());
|
||||
m.reflection.setPath(1, lineReflBack->property("GLpath").toString());
|
||||
m.reflection.setPath(2, lineReflLeft->property("GLpath").toString());
|
||||
m.reflection.setPath(3, lineReflRight->property("GLpath").toString());
|
||||
m.reflection.setPath(4, lineReflTop->property("GLpath").toString());
|
||||
m.reflection.setPath(5, lineReflBottom->property("GLpath").toString());
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
void MaterialEditor::on_buttonDiffuseSelect_clicked() {
|
||||
QString str = QFileDialog::getOpenFileName(this, "Select image", lineDiffuse->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)");
|
||||
if (str.isEmpty()) return;
|
||||
lineDiffuse->setProperty("GLpath", str);
|
||||
lineDiffuse->setText(QFileInfo(str).fileName());
|
||||
materialChanged();
|
||||
}
|
||||
|
||||
|
||||
void MaterialEditor::on_buttonBumpSelect_clicked() {
|
||||
QString str = QFileDialog::getOpenFileName(this, "Select image", lineBump->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)");
|
||||
if (str.isEmpty()) return;
|
||||
lineBump->setProperty("GLpath", str);
|
||||
lineBump->setText(QFileInfo(str).fileName());
|
||||
materialChanged();
|
||||
}
|
||||
|
||||
|
||||
void MaterialEditor::on_buttonReliefSelect_clicked() {
|
||||
QString str = QFileDialog::getOpenFileName(this, "Select image", lineRelief->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)");
|
||||
if (str.isEmpty()) return;
|
||||
lineRelief->setProperty("GLpath", str);
|
||||
lineRelief->setText(QFileInfo(str).fileName());
|
||||
materialChanged();
|
||||
}
|
||||
|
||||
|
||||
void MaterialEditor::on_buttonReflFrontSelect_clicked() {
|
||||
QString str = QFileDialog::getOpenFileName(this, "Select image", lineReflFront->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)");
|
||||
if (str.isEmpty()) return;
|
||||
lineReflFront->setProperty("GLpath", str);
|
||||
lineReflFront->setText(QFileInfo(str).fileName());
|
||||
materialChanged();
|
||||
}
|
||||
|
||||
|
||||
void MaterialEditor::on_buttonReflBackSelect_clicked() {
|
||||
QString str = QFileDialog::getOpenFileName(this, "Select image", lineReflBack->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)");
|
||||
if (str.isEmpty()) return;
|
||||
lineReflBack->setProperty("GLpath", str);
|
||||
lineReflBack->setText(QFileInfo(str).fileName());
|
||||
materialChanged();
|
||||
}
|
||||
|
||||
|
||||
void MaterialEditor::on_buttonReflLeftSelect_clicked() {
|
||||
QString str = QFileDialog::getOpenFileName(this, "Select image", lineReflLeft->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)");
|
||||
if (str.isEmpty()) return;
|
||||
lineReflLeft->setProperty("GLpath", str);
|
||||
lineReflLeft->setText(QFileInfo(str).fileName());
|
||||
materialChanged();
|
||||
}
|
||||
|
||||
|
||||
void MaterialEditor::on_buttonReflRightSelect_clicked() {
|
||||
QString str = QFileDialog::getOpenFileName(this, "Select image", lineReflRight->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)");
|
||||
if (str.isEmpty()) return;
|
||||
lineReflRight->setProperty("GLpath", str);
|
||||
lineReflRight->setText(QFileInfo(str).fileName());
|
||||
materialChanged();
|
||||
}
|
||||
|
||||
|
||||
void MaterialEditor::on_buttonReflTopSelect_clicked() {
|
||||
QString str = QFileDialog::getOpenFileName(this, "Select image", lineReflTop->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)");
|
||||
if (str.isEmpty()) return;
|
||||
lineReflTop->setProperty("GLpath", str);
|
||||
lineReflTop->setText(QFileInfo(str).fileName());
|
||||
materialChanged();
|
||||
}
|
||||
|
||||
|
||||
void MaterialEditor::on_buttonReflBottomSelect_clicked() {
|
||||
QString str = QFileDialog::getOpenFileName(this, "Select image", lineReflBottom->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)");
|
||||
if (str.isEmpty()) return;
|
||||
lineReflBottom->setProperty("GLpath", str);
|
||||
lineReflBottom->setText(QFileInfo(str).fileName());
|
||||
materialChanged();
|
||||
}
|
||||
|
||||
|
||||
void MaterialEditor::on_buttonLoadCubeDir_clicked() {
|
||||
QString dir = QFileDialog::getExistingDirectory(this, "Select directory", lineReflFront->property("GLpath").toString());
|
||||
if (dir.isEmpty()) return;
|
||||
GLCubeTexture cb(0);
|
||||
cb.loadPathesFromDirectory(dir);
|
||||
active = false;
|
||||
lineReflFront->setProperty("GLpath", cb.path(0)); lineReflFront->setText(QFileInfo(cb.path(0)).fileName());
|
||||
lineReflBack->setProperty("GLpath", cb.path(1)); lineReflBack->setText(QFileInfo(cb.path(1)).fileName());
|
||||
lineReflLeft->setProperty("GLpath", cb.path(2)); lineReflLeft->setText(QFileInfo(cb.path(2)).fileName());
|
||||
lineReflRight->setProperty("GLpath", cb.path(3)); lineReflRight->setText(QFileInfo(cb.path(3)).fileName());
|
||||
lineReflTop->setProperty("GLpath", cb.path(4)); lineReflTop->setText(QFileInfo(cb.path(4)).fileName());
|
||||
lineReflBottom->setProperty("GLpath", cb.path(5)); lineReflBottom->setText(QFileInfo(cb.path(5)).fileName());
|
||||
active = true;
|
||||
materialChanged();
|
||||
}
|
||||
67
qglview/material_editor.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MATERIAL_EDITOR_H
|
||||
#define MATERIAL_EDITOR_H
|
||||
|
||||
#include <QFileDialog>
|
||||
#include "gltypes.h"
|
||||
#include "ui_material_editor.h"
|
||||
|
||||
class MaterialEditor: public QWidget, private Ui::MaterialEditor
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MaterialEditor(QWidget * parent = 0);
|
||||
|
||||
void setMaterial(const Material & m);
|
||||
Material material();
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent * e);
|
||||
|
||||
bool active;
|
||||
|
||||
private slots:
|
||||
void materialChanged() {if (active) emit changed();}
|
||||
void on_buttonDiffuseSelect_clicked();
|
||||
void on_buttonDiffuseClear_clicked() {lineDiffuse->setText(""); lineDiffuse->setProperty("GLpath", ""); materialChanged();}
|
||||
void on_buttonBumpSelect_clicked();
|
||||
void on_buttonBumpClear_clicked() {lineBump->setText(""); lineBump->setProperty("GLpath", ""); materialChanged();}
|
||||
void on_buttonReliefSelect_clicked();
|
||||
void on_buttonReliefClear_clicked() {lineRelief->setText(""); lineRelief->setProperty("GLpath", ""); materialChanged();}
|
||||
void on_buttonReflFrontSelect_clicked();
|
||||
void on_buttonReflFrontClear_clicked() {lineReflFront->setText(""); lineReflFront->setProperty("GLpath", ""); materialChanged();}
|
||||
void on_buttonReflBackSelect_clicked();
|
||||
void on_buttonReflBackClear_clicked() {lineReflBack->setText(""); lineReflBack->setProperty("GLpath", ""); materialChanged();}
|
||||
void on_buttonReflLeftSelect_clicked();
|
||||
void on_buttonReflLeftClear_clicked() {lineReflLeft->setText(""); lineReflLeft->setProperty("GLpath", ""); materialChanged();}
|
||||
void on_buttonReflRightSelect_clicked();
|
||||
void on_buttonReflRightClear_clicked() {lineReflRight->setText(""); lineReflRight->setProperty("GLpath", ""); materialChanged();}
|
||||
void on_buttonReflTopSelect_clicked();
|
||||
void on_buttonReflTopClear_clicked() {lineReflTop->setText(""); lineReflTop->setProperty("GLpath", ""); materialChanged();}
|
||||
void on_buttonReflBottomSelect_clicked();
|
||||
void on_buttonReflBottomClear_clicked() {lineReflBottom->setText(""); lineReflBottom->setProperty("GLpath", ""); materialChanged();}
|
||||
void on_buttonLoadCubeDir_clicked();
|
||||
|
||||
signals:
|
||||
void changed();
|
||||
|
||||
};
|
||||
|
||||
#endif // MATERIAL_EDITOR_H
|
||||
891
qglview/material_editor.ui
Normal file
@@ -0,0 +1,891 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MaterialEditor</class>
|
||||
<widget class="QWidget" name="MaterialEditor">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>327</width>
|
||||
<height>588</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="horizontalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Diffuse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="ColorButton" name="colorDiffuse">
|
||||
<property name="useAlphaChannel">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Specular</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="ColorButton" name="colorSpecular">
|
||||
<property name="useAlphaChannel">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Light model</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="comboModel">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Phong</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Cook-Torrance</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Minnaert</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Strauss</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Oren-Nayar</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Shininess</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="SpinSlider" name="spinShine">
|
||||
<property name="maximum">
|
||||
<double>128.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<double>16.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Shine strength</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="SpinSlider" name="spinShineStrength">
|
||||
<property name="maximum">
|
||||
<double>64.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="squareScale">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Transparency</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="SpinSlider" name="spinTransparent">
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Reflectivity</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="SpinSlider" name="spinReflect">
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Bump scale</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="SpinSlider" name="spinBump">
|
||||
<property name="maximum">
|
||||
<double>4.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Diffuse map</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineDiffuse"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonDiffuseClear">
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonDiffuseSelect">
|
||||
<property name="text">
|
||||
<string>^</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Bump map</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineBump"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonBumpClear">
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonBumpSelect">
|
||||
<property name="text">
|
||||
<string>^</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="checkGlass">
|
||||
<property name="text">
|
||||
<string>Glass</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>IOF</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="SpinSlider" name="spinIOF">
|
||||
<property name="maximum">
|
||||
<double>2.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Self-illumination</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="ColorButton" name="colorSelfIllum">
|
||||
<property name="useAlphaChannel">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Reflection map</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="1">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Front:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>Back:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>Left:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>Right:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_23">
|
||||
<property name="text">
|
||||
<string>Top:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>Bottom:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineReflLeft"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonReflLeftClear">
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonReflLeftSelect">
|
||||
<property name="text">
|
||||
<string>^</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineReflFront"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonReflFrontClear">
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonReflFrontSelect">
|
||||
<property name="text">
|
||||
<string>^</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineReflBack"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonReflBackClear">
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonReflBackSelect">
|
||||
<property name="text">
|
||||
<string>^</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_11">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineReflRight"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonReflRightClear">
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonReflRightSelect">
|
||||
<property name="text">
|
||||
<string>^</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineReflTop"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonReflTopClear">
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonReflTopSelect">
|
||||
<property name="text">
|
||||
<string>^</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_13">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineReflBottom"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonReflBottomClear">
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonReflBottomSelect">
|
||||
<property name="text">
|
||||
<string>^</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="buttonLoadCubeDir">
|
||||
<property name="text">
|
||||
<string>load from directory</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Dispersion</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="SpinSlider" name="spinDispersion">
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>Relief map</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineRelief"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonReliefClear">
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonReliefSelect">
|
||||
<property name="text">
|
||||
<string>^</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>Relief scale</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="SpinSlider" name="spinRelief">
|
||||
<property name="maximum">
|
||||
<double>4.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SpinSlider</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>spinslider.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ColorButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>colorbutton.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>colorDiffuse</sender>
|
||||
<signal>colorChanged(QColor)</signal>
|
||||
<receiver>MaterialEditor</receiver>
|
||||
<slot>materialChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>272</x>
|
||||
<y>17</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>282</x>
|
||||
<y>17</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>colorSpecular</sender>
|
||||
<signal>colorChanged(QColor)</signal>
|
||||
<receiver>MaterialEditor</receiver>
|
||||
<slot>materialChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>271</x>
|
||||
<y>39</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>284</x>
|
||||
<y>45</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>comboModel</sender>
|
||||
<signal>currentIndexChanged(int)</signal>
|
||||
<receiver>MaterialEditor</receiver>
|
||||
<slot>materialChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>279</x>
|
||||
<y>98</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>284</x>
|
||||
<y>70</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinShine</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>MaterialEditor</receiver>
|
||||
<slot>materialChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>279</x>
|
||||
<y>127</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>280</x>
|
||||
<y>95</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinShineStrength</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>MaterialEditor</receiver>
|
||||
<slot>materialChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>279</x>
|
||||
<y>153</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>283</x>
|
||||
<y>120</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinTransparent</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>MaterialEditor</receiver>
|
||||
<slot>materialChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>279</x>
|
||||
<y>179</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>283</x>
|
||||
<y>149</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinReflect</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>MaterialEditor</receiver>
|
||||
<slot>materialChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>279</x>
|
||||
<y>204</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>284</x>
|
||||
<y>174</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinBump</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>MaterialEditor</receiver>
|
||||
<slot>materialChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>279</x>
|
||||
<y>230</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>284</x>
|
||||
<y>202</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>lineDiffuse</sender>
|
||||
<signal>textChanged(QString)</signal>
|
||||
<receiver>MaterialEditor</receiver>
|
||||
<slot>materialChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>264</x>
|
||||
<y>349</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>99</x>
|
||||
<y>211</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>lineBump</sender>
|
||||
<signal>textChanged(QString)</signal>
|
||||
<receiver>MaterialEditor</receiver>
|
||||
<slot>materialChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>264</x>
|
||||
<y>376</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>98</x>
|
||||
<y>245</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinIOF</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>MaterialEditor</receiver>
|
||||
<slot>materialChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>279</x>
|
||||
<y>291</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>284</x>
|
||||
<y>236</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>checkGlass</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>MaterialEditor</receiver>
|
||||
<slot>materialChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>279</x>
|
||||
<y>121</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>284</x>
|
||||
<y>84</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>colorSelfIllum</sender>
|
||||
<signal>colorChanged(QColor)</signal>
|
||||
<receiver>MaterialEditor</receiver>
|
||||
<slot>materialChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>322</x>
|
||||
<y>63</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>326</x>
|
||||
<y>63</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinDispersion</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>MaterialEditor</receiver>
|
||||
<slot>materialChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>313</x>
|
||||
<y>313</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>326</x>
|
||||
<y>288</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>lineRelief</sender>
|
||||
<signal>textChanged(QString)</signal>
|
||||
<receiver>MaterialEditor</receiver>
|
||||
<slot>materialChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>123</x>
|
||||
<y>391</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>17</x>
|
||||
<y>364</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinRelief</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>MaterialEditor</receiver>
|
||||
<slot>materialChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>317</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>327</x>
|
||||
<y>261</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<slots>
|
||||
<slot>materialChanged()</slot>
|
||||
</slots>
|
||||
</ui>
|
||||
404
qglview/propertyeditor.cpp
Normal file
@@ -0,0 +1,404 @@
|
||||
#include "propertyeditor.h"
|
||||
|
||||
|
||||
QWidget * Delegate::widgetForProperty(QWidget * parent, const QModelIndex & index) const {
|
||||
QWidget * w = 0;
|
||||
int type = 0;
|
||||
QVariant value = index.data(Qt::UserRole);
|
||||
if (index.data(Qt::UserRole + 2).toString() == "__flags") return 0;
|
||||
if (index.data(Qt::UserRole + 1).toString() == "__flag") {
|
||||
qulonglong key = index.data(Qt::UserRole).toULongLong();
|
||||
value = index.parent().data(Qt::UserRole);
|
||||
//QMetaProperty prop = index.parent().data(Qt::UserRole + 1).value<QMetaProperty>();
|
||||
w = new QCheckBox(parent); type = 14; ((QCheckBox*)w)->setChecked(((value.toULongLong() & key) == key && key != 0) || (value.toULongLong() == 0 && key == 0));
|
||||
((QCheckBox*)w)->setText("0x" + QString::number(key, 16).toUpper());
|
||||
connect((QCheckBox*)w, SIGNAL(toggled(bool)), this, SLOT(changedFlag()));
|
||||
//qDebug() << prop.enumerator().name();
|
||||
} else {
|
||||
if (value.canConvert<PropertyValuePair>()) {
|
||||
PropertyValuePair prop = value.value<PropertyValuePair>();
|
||||
if (prop.first.isEnumType()) {
|
||||
w = new QComboBox(parent); type = 13; ((QComboBox*)w)->setCurrentIndex(value.toInt());
|
||||
w->setProperty("__prop", QVariant::fromValue<QMetaProperty>(prop.first));
|
||||
QMetaEnum menum = prop.first.enumerator();
|
||||
for (int i = 0; i < menum.keyCount(); ++i) {
|
||||
((QComboBox*)w)->addItem(QString(menum.key(i)) + " (0x" + QString::number(menum.value(i), 16).toUpper() + ")", menum.value(i));
|
||||
if (menum.value(i) == prop.second.toInt())
|
||||
((QComboBox*)w)->setCurrentIndex(i);
|
||||
}
|
||||
connect((QComboBox*)w, SIGNAL(currentIndexChanged(int)), this, SLOT(changed()));
|
||||
}
|
||||
} else {
|
||||
switch (value.type()) {
|
||||
case QVariant::Int: w = new QSpinBox(parent); type = 2; ((QSpinBox*)w)->setRange(-0x7FFFFFFF, 0x7FFFFFFF); connect((QSpinBox*)w, SIGNAL(valueChanged(int)), this, SLOT(changed())); break;
|
||||
case QVariant::UInt: w = new QSpinBox(parent); type = 3; ((QSpinBox*)w)->setRange(0, 0xFFFFFFFF); connect((QSpinBox*)w, SIGNAL(valueChanged(int)), this, SLOT(changed())); break;
|
||||
case QVariant::LongLong: w = new QSpinBox(parent); type = 4; ((QSpinBox*)w)->setRange(-0x7FFFFFFF, 0x7FFFFFFF); connect((QSpinBox*)w, SIGNAL(valueChanged(int)), this, SLOT(changed())); break;
|
||||
case QVariant::ULongLong: w = new QSpinBox(parent); type = 5; ((QSpinBox*)w)->setRange(0, 0xFFFFFFFF); connect((QSpinBox*)w, SIGNAL(valueChanged(int)), this, SLOT(changed())); break;
|
||||
case QVariant::Double: w = new QDoubleSpinBox(parent); type = 6; ((QDoubleSpinBox*)w)->setRange(-999999999, 999999999); ((QDoubleSpinBox*)w)->setDecimals(3); connect((QDoubleSpinBox*)w, SIGNAL(valueChanged(double)), this, SLOT(changed())); break;
|
||||
case QVariant::Bool: w = new QCheckBox(parent); type = 7; ((QCheckBox*)w)->setChecked(value.toBool()); connect((QCheckBox*)w, SIGNAL(toggled(bool)), this, SLOT(changed())); break;
|
||||
case QVariant::Color: w = new ColorButton(parent); type = 8; ((ColorButton*)w)->setUseAlphaChannel(true); ((ColorButton*)w)->setColor(value.value<QColor>()); connect((ColorButton*)w, SIGNAL(colorChanged(QColor)), this, SLOT(changed())); break;
|
||||
case QVariant::Point: w = new QPointEdit(parent); type = 9; ((QPointEdit*)w)->setDecimals(0); ((QPointEdit*)w)->setValue(QPointF(value.toPoint())); connect((QPointEdit*)w, SIGNAL(valueChanged(QPointF)), this, SLOT(changed())); break;
|
||||
case QVariant::PointF: w = new QPointEdit(parent); type = 10; ((QPointEdit*)w)->setDecimals(3); ((QPointEdit*)w)->setValue(value.toPointF()); connect((QPointEdit*)w, SIGNAL(valueChanged(QPointF)), this, SLOT(changed())); break;
|
||||
case QVariant::Rect: w = new QRectEdit(parent); type = 11; ((QRectEdit*)w)->setDecimals(0); ((QRectEdit*)w)->setValue(QRectF(value.toRect())); connect((QRectEdit*)w, SIGNAL(valueChanged(QRectF)), this, SLOT(changed())); break;
|
||||
case QVariant::RectF: w = new QRectEdit(parent); type = 12; ((QRectEdit*)w)->setDecimals(3); ((QRectEdit*)w)->setValue(value.toRectF()); connect((QRectEdit*)w, SIGNAL(valueChanged(QRectF)), this, SLOT(changed())); break;
|
||||
case QVariant::String: default: w = new CLineEdit(parent); type = 1; ((CLineEdit*)w)->setDefaultText(value.toString()); connect((CLineEdit*)w, SIGNAL(textChanged(QString)), this, SLOT(changed())); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (w == 0) return 0;
|
||||
/*QPalette pal = w->palette();
|
||||
pal.setColor(QPalette::Window, Qt::white);
|
||||
w->setPalette(pal);*/
|
||||
w->setAutoFillBackground(true);
|
||||
w->setProperty("__type", type);
|
||||
return w;
|
||||
}
|
||||
|
||||
|
||||
void Delegate::setWidgetProperty(QWidget * w, const QVariant & value) const {
|
||||
if (w == 0) return;
|
||||
switch (w->property("__type").toInt()) {
|
||||
case 1: ((CLineEdit*)w)->setText(value.toString()); break;
|
||||
case 2: case 3: case 4: case 5: ((QSpinBox*)w)->setValue(value.toInt()); break;
|
||||
case 6: ((QDoubleSpinBox*)w)->setValue(value.toDouble()); break;
|
||||
case 7: ((QCheckBox*)w)->setChecked(value.toBool()); break;
|
||||
case 8: ((ColorButton*)w)->setColor(value.value<QColor>()); break;
|
||||
case 9: ((QPointEdit*)w)->setValue(value.value<QPoint>()); break;
|
||||
case 10: ((QPointEdit*)w)->setValue(value.value<QPointF>()); break;
|
||||
case 11: ((QRectEdit*)w)->setValue(value.value<QRect>()); break;
|
||||
case 12: ((QRectEdit*)w)->setValue(value.value<QRectF>()); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const QVariant Delegate::widgetProperty(QWidget * w) const {
|
||||
if (w == 0) return QVariant();
|
||||
switch (w->property("__type").toInt()) {
|
||||
case 1: return QVariant::fromValue<QString>(((CLineEdit*)w)->text()); break;
|
||||
case 2: return QVariant::fromValue<int>(((QSpinBox*)w)->value()); break;
|
||||
case 3: return QVariant::fromValue<uint>(((QSpinBox*)w)->value()); break;
|
||||
case 4: return QVariant::fromValue<qlonglong>(((QSpinBox*)w)->value()); break;
|
||||
case 5: return QVariant::fromValue<qulonglong>(((QSpinBox*)w)->value()); break;
|
||||
case 6: return QVariant::fromValue<double>(((QDoubleSpinBox*)w)->value()); break;
|
||||
case 7: return QVariant::fromValue<bool>(((QCheckBox*)w)->isChecked()); break;
|
||||
case 8: return QVariant::fromValue<QColor>(((ColorButton*)w)->color()); break;
|
||||
case 9: return QVariant::fromValue<QPoint>(((QPointEdit*)w)->value().toPoint()); break;
|
||||
case 10: return QVariant::fromValue<QPointF>(((QPointEdit*)w)->value()); break;
|
||||
case 11: return QVariant::fromValue<QRect>(((QRectEdit*)w)->value().toRect()); break;
|
||||
case 12: return QVariant::fromValue<QRectF>(((QRectEdit*)w)->value()); break;
|
||||
case 13: return QVariant::fromValue<PropertyValuePair>(PropertyValuePair(w->property("__prop").value<QMetaProperty>(), ((QComboBox*)w)->itemData(((QComboBox*)w)->currentIndex()))); break;
|
||||
default: return QVariant(); break;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
void Delegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const {
|
||||
if (index.data(Qt::UserRole + 1).toString() != "__flag")
|
||||
model->setData(index, widgetProperty(editor), Qt::UserRole);
|
||||
}
|
||||
|
||||
|
||||
void Delegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const {
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
QVariant value = index.data(Qt::UserRole);
|
||||
QStyle * style = QApplication::style();
|
||||
QStyleOption * so = 0;
|
||||
QStyleOptionComplex * soc = 0;
|
||||
QString text;
|
||||
QRect rect;
|
||||
QPalette::ColorRole role = (option.state.testFlag(QStyle::State_Selected) && option.state.testFlag(QStyle::State_Active) ? QPalette::HighlightedText : QPalette::WindowText);
|
||||
if (index.data(Qt::UserRole + 2).toString() == "__flags") {
|
||||
text = "0x" + QString::number(value.toInt(), 16).toUpper();
|
||||
style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role);
|
||||
return;
|
||||
}
|
||||
if (index.data(Qt::UserRole + 1) == "__flag") {
|
||||
qulonglong key = index.data(Qt::UserRole).toULongLong();
|
||||
value = index.parent().data(Qt::UserRole);
|
||||
so = new QStyleOptionButton();
|
||||
so->rect = option.rect;
|
||||
so->palette = option.palette;
|
||||
so->fontMetrics = option.fontMetrics;
|
||||
((QStyleOptionButton*)so)->state = (((value.toULongLong() & key) == key && key != 0) || (value.toULongLong() == 0 && key == 0) ? QStyle::State_On : QStyle::State_Off) | option.state;
|
||||
((QStyleOptionButton*)so)->text = "0x" + QString::number(key, 16).toUpper();
|
||||
if (option.state.testFlag(QStyle::State_Selected))
|
||||
so->palette.setColor(QPalette::WindowText, so->palette.color(QPalette::HighlightedText));
|
||||
style->drawControl(QStyle::CE_CheckBox, so, painter);
|
||||
} else {
|
||||
if (value.canConvert<PropertyValuePair>()) {
|
||||
PropertyValuePair prop = value.value<PropertyValuePair>();
|
||||
if (prop.first.isEnumType()) {
|
||||
QMetaEnum menum = prop.first.enumerator();
|
||||
for (int i = 0; i < menum.keyCount(); ++i) {
|
||||
if (menum.value(i) == prop.second.toInt()) {
|
||||
text = QString(menum.key(i)) + " (0x" + QString::number(menum.value(i), 16).toUpper() + ")";
|
||||
break;
|
||||
}
|
||||
}
|
||||
style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role);
|
||||
}
|
||||
} else {
|
||||
switch (value.type()) {
|
||||
case QVariant::Int:
|
||||
text.setNum(value.toInt());
|
||||
style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role);
|
||||
break;
|
||||
case QVariant::UInt:
|
||||
text.setNum(value.toUInt());
|
||||
style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role);
|
||||
break;
|
||||
case QVariant::LongLong:
|
||||
text.setNum(value.toLongLong());
|
||||
style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role);
|
||||
break;
|
||||
case QVariant::ULongLong:
|
||||
text.setNum(value.toULongLong());
|
||||
style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role);
|
||||
break;
|
||||
case QVariant::Double:
|
||||
text.setNum(value.toDouble(), 'f', 3);
|
||||
style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role);
|
||||
break;
|
||||
case QVariant::Bool:
|
||||
so = new QStyleOptionButton();
|
||||
so->rect = option.rect;
|
||||
so->state = option.state;
|
||||
so->palette = option.palette;
|
||||
so->fontMetrics = option.fontMetrics;
|
||||
((QStyleOptionButton*)so)->state = (value.toBool() ? QStyle::State_On : QStyle::State_Off) | option.state;
|
||||
style->drawControl(QStyle::CE_CheckBox, so, painter);
|
||||
break;
|
||||
case QVariant::Color:
|
||||
rect = option.rect;//style->subElementRect(QStyle::QStyle::SE_FrameContents, so);
|
||||
rect.setRect(rect.x() + 3, rect.y() + 3, rect.width() - 6, rect.height() - 6);
|
||||
painter->fillRect(rect, ab);
|
||||
painter->fillRect(rect, value.value<QColor>());
|
||||
break;
|
||||
case QVariant::Point:
|
||||
text = pointString(value.toPoint());
|
||||
style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role);
|
||||
break;
|
||||
case QVariant::PointF:
|
||||
text = pointString(value.toPointF());
|
||||
style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role);
|
||||
break;
|
||||
case QVariant::Rect:
|
||||
text = rectString(value.toRect());
|
||||
style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role);
|
||||
break;
|
||||
case QVariant::RectF:
|
||||
text = rectString(value.toRectF());
|
||||
style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role);
|
||||
break;
|
||||
case QVariant::String: default:
|
||||
style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, value.toString()),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, value.toString(), role);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*so = new QStyleOptionFrame();
|
||||
so->rect = option.rect;
|
||||
so->state = option.state;
|
||||
so->palette = option.palette;
|
||||
so->fontMetrics = option.fontMetrics;
|
||||
((QStyleOptionFrame*)so)->state = (value.toBool() ? QStyle::State_On : QStyle::State_Off);
|
||||
style->drawPrimitive(QStyle::PE_PanelLineEdit, so, painter);
|
||||
style->drawPrimitive(QStyle::PE_FrameLineEdit, so, painter);
|
||||
break;*/
|
||||
if (so != 0) delete so;
|
||||
if (soc != 0) delete soc;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Delegate::changedFlag() {
|
||||
QAbstractItemModel * model = const_cast<QAbstractItemModel * >(cmi.model());
|
||||
model->setData(cmi, qobject_cast<QCheckBox * >(sender())->isChecked(), Qt::UserRole + 3);
|
||||
QModelIndex p = cmi.parent(), mi;
|
||||
int row = 0;
|
||||
qulonglong val = 0;
|
||||
QList<QModelIndex> chldr;
|
||||
mi = p.child(row, 1);
|
||||
while (mi.isValid()) {
|
||||
chldr << mi;
|
||||
model->setData(mi, !mi.data(Qt::UserRole + 4).toBool(), Qt::UserRole + 4);
|
||||
mi = p.child(++row, 1);
|
||||
}
|
||||
bool cc = cmi.data(Qt::UserRole + 3).toBool();
|
||||
qulonglong cv = cmi.data(Qt::UserRole).toULongLong();
|
||||
//qDebug() << "*****";
|
||||
if (cc && cv == 0) {
|
||||
val = 0;
|
||||
//qDebug() << "null" << cv;
|
||||
} else {
|
||||
if (!cc && cv != 0) {
|
||||
//qDebug() << "uncheck" << cv;
|
||||
for (int i = 0; i < chldr.size(); ++i) {
|
||||
if (chldr[i] == cmi) continue;
|
||||
//qDebug() << (chldr[i].data(Qt::UserRole).toULongLong() & cv);
|
||||
if (chldr[i].data(Qt::UserRole).toULongLong() & cv)
|
||||
model->setData(chldr[i], false, Qt::UserRole + 3);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < chldr.size(); ++i) {
|
||||
//qDebug() << chldr[i].data(Qt::UserRole + 3).toBool();
|
||||
if (chldr[i].data(Qt::UserRole + 3).toBool())
|
||||
val |= chldr[i].data(Qt::UserRole).toULongLong();
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < chldr.size(); ++i) {
|
||||
if (chldr[i] == cmi) continue;
|
||||
cv = chldr[i].data(Qt::UserRole).toULongLong();
|
||||
model->setData(chldr[i], ((val & cv) == cv && cv != 0) || (val == 0 && cv == 0), Qt::UserRole + 3);
|
||||
}
|
||||
//qDebug() << val;
|
||||
model->setData(p, val, Qt::UserRole);
|
||||
model->setData(p.sibling(p.row(), 1), val, Qt::UserRole);
|
||||
}
|
||||
|
||||
|
||||
|
||||
PropertyEditor::PropertyEditor(QWidget * parent): QTreeWidget(parent) {
|
||||
object = 0;
|
||||
configTree();
|
||||
connect(this, SIGNAL(itemClicked(QTreeWidgetItem * , int)), this, SLOT(itemClicked(QTreeWidgetItem * , int)));
|
||||
connect(this, SIGNAL(itemChanged(QTreeWidgetItem * , int)), this, SLOT(itemChanged(QTreeWidgetItem * , int)));
|
||||
}
|
||||
|
||||
|
||||
PropertyEditor::~PropertyEditor() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void PropertyEditor::changeEvent(QEvent * e) {
|
||||
QTreeWidget::changeEvent(e);
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
configTree();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PropertyEditor::configTree() {
|
||||
setColumnCount(2);
|
||||
setRootIsDecorated(false);
|
||||
setColumnWidth(0, 170);
|
||||
setColumnWidth(1, 10);
|
||||
header()->setStretchLastSection(true);
|
||||
QStringList lbls;
|
||||
lbls << tr("Property") << tr("Value");
|
||||
setHeaderLabels(lbls);
|
||||
setAlternatingRowColors(true);
|
||||
setItemDelegateForColumn(1, new Delegate());
|
||||
|
||||
}
|
||||
|
||||
|
||||
void PropertyEditor::itemClicked(QTreeWidgetItem * item, int column) {
|
||||
if (column == 0)
|
||||
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
|
||||
else {
|
||||
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable);
|
||||
editItem(item, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PropertyEditor::itemChanged(QTreeWidgetItem * item, int column) {
|
||||
if (column != 1) return;
|
||||
QVariant value = item->data(1, Qt::UserRole);
|
||||
if (value.canConvert<PropertyValuePair>()) {
|
||||
value = value.value<PropertyValuePair>().second;
|
||||
}
|
||||
object->setProperty(item->text(0).toAscii(), value);
|
||||
}
|
||||
|
||||
|
||||
void PropertyEditor::rebuild() {
|
||||
clear();
|
||||
configTree();
|
||||
if (object == 0) return;
|
||||
const QMetaObject * mo = object->metaObject();
|
||||
QList<const QMetaObject * > mol;
|
||||
while (mo != 0) {
|
||||
mol.push_front(mo);
|
||||
mo = mo->superClass();
|
||||
}
|
||||
int ps, pe;
|
||||
QTreeWidgetItem * ti, * tli, * tfi;
|
||||
QVariant value;
|
||||
QWidget * pw = 0;
|
||||
int chue = 0;
|
||||
QColor bc;
|
||||
font_b = font();
|
||||
font_b.setBold(true);
|
||||
foreach (const QMetaObject * o, mol) {
|
||||
ps = o->propertyOffset();
|
||||
pe = o->propertyCount();// - ps;
|
||||
//qDebug() << i->className() << ps << pe;
|
||||
tli = new QTreeWidgetItem();
|
||||
tli->setText(0, o->className());
|
||||
tli->setFont(0, font_b);
|
||||
setItemBackColor(tli, Qt::darkGray);
|
||||
setItemForeColor(tli, Qt::white);
|
||||
addTopLevelItem(tli);
|
||||
setFirstItemColumnSpanned(tli, true);
|
||||
tli->setExpanded(true);
|
||||
for (int i = ps; i < pe; ++i) {
|
||||
props << o->property(i);
|
||||
value = o->property(i).read(object);
|
||||
ti = new QTreeWidgetItem();
|
||||
ti->setSizeHint(1, QSize(20, 20));
|
||||
bc.setHsv(chue, 60, 245 + (i % 2) * 20 - 10);
|
||||
setItemBackColor(ti, bc);
|
||||
ti->setText(0, o->property(i).name());
|
||||
if (props.back().isFlagType()) {
|
||||
QMetaEnum menum = props.back().enumerator();
|
||||
for (int j = 0; j < menum.keyCount(); ++j) {
|
||||
tfi = new QTreeWidgetItem();
|
||||
tfi->setText(0, menum.key(j));
|
||||
tfi->setData(1, Qt::UserRole, menum.value(j));
|
||||
tfi->setData(1, Qt::UserRole + 1, "__flag");
|
||||
tfi->setData(1, Qt::UserRole + 2, value.toULongLong());
|
||||
tfi->setData(1, Qt::UserRole + 3, (value.toULongLong() & menum.value(j)) > 0);
|
||||
tfi->setSizeHint(1, QSize(20, 20));
|
||||
bc.setHsv(chue, 60, 245 + ((i + j + 1) % 2) * 20 - 10);
|
||||
setItemBackColor(tfi, bc);
|
||||
ti->addChild(tfi);
|
||||
}
|
||||
ti->setData(0, Qt::UserRole, value);
|
||||
ti->setData(1, Qt::UserRole, value);
|
||||
ti->setData(1, Qt::UserRole + 2, "__flags");
|
||||
ti->setData(0, Qt::UserRole + 1, QVariant::fromValue<QMetaProperty>(props.back()));
|
||||
}
|
||||
else if (props.back().isEnumType())
|
||||
value.setValue<PropertyValuePair>(PropertyValuePair(props.back(), value));
|
||||
//ti->setText(1, value.toString());
|
||||
ti->setData(1, Qt::UserRole, value);
|
||||
tli->addChild(ti);
|
||||
//const_cast<QModelIndex & >(indexFromItem(ti, 1)).;
|
||||
//if (pw != 0) setItemWidget(ti, 1, pw);
|
||||
}
|
||||
chue += 60;
|
||||
chue %= 360;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PropertyEditor::refresh() {
|
||||
|
||||
}
|
||||
76
qglview/propertyeditor.h
Normal file
@@ -0,0 +1,76 @@
|
||||
#ifndef PROPERTYEDITOR_H
|
||||
#define PROPERTYEDITOR_H
|
||||
|
||||
#include <QTreeWidget>
|
||||
#include <QHeaderView>
|
||||
#include <QMetaProperty>
|
||||
#include <QEvent>
|
||||
#include <QDebug>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <qpiconfigwidget.h>
|
||||
|
||||
|
||||
class Delegate: public QStyledItemDelegate {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Delegate(QObject * parent = 0): QStyledItemDelegate() {ab = QBrush(QImage(":/icons/alpha.png"));}
|
||||
|
||||
QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const {cmi = const_cast<QModelIndex & >(index); return widgetForProperty(parent, index);}
|
||||
void setEditorData(QWidget * editor, const QModelIndex & index) const {setWidgetProperty(editor, index.data(Qt::UserRole));}
|
||||
void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const;
|
||||
void updateEditorGeometry(QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index) const {editor->setGeometry(option.rect);}
|
||||
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const;
|
||||
|
||||
private:
|
||||
QWidget * widgetForProperty(QWidget * parent, const QModelIndex & index) const;
|
||||
void setWidgetProperty(QWidget * w, const QVariant & value) const;
|
||||
const QVariant widgetProperty(QWidget * w) const;
|
||||
QString pointString(const QPoint & p) const {return QString::number(p.x()) + " x " + QString::number(p.y());}
|
||||
QString pointString(const QPointF & p) const {return QString::number(p.x()) + " x " + QString::number(p.y());}
|
||||
QString rectString(const QRect & r) const {return QString::number(r.x()) + " x " + QString::number(r.y()) + " : " +
|
||||
QString::number(r.width()) + " x " + QString::number(r.height());}
|
||||
QString rectString(const QRectF & r) const {return QString::number(r.x()) + " x " + QString::number(r.y()) + " : " +
|
||||
QString::number(r.width()) + " x " + QString::number(r.height());}
|
||||
|
||||
QBrush ab;
|
||||
mutable QModelIndex cmi;
|
||||
|
||||
private slots:
|
||||
void changed() {setModelData((QWidget * )sender(), const_cast<QAbstractItemModel * >(cmi.model()), cmi);}
|
||||
void changedFlag();
|
||||
|
||||
};
|
||||
|
||||
typedef QPair<QMetaProperty, QVariant> PropertyValuePair;
|
||||
Q_DECLARE_METATYPE (PropertyValuePair)
|
||||
Q_DECLARE_METATYPE (QMetaProperty)
|
||||
|
||||
class PropertyEditor: public QTreeWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PropertyEditor(QWidget * parent = 0);
|
||||
virtual ~PropertyEditor();
|
||||
|
||||
void assignObject(QObject * o) {object = o; rebuild();}
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent * e);
|
||||
|
||||
private:
|
||||
void configTree();
|
||||
void setItemBackColor(QTreeWidgetItem * i, const QColor & c) {i->setBackgroundColor(0, c); i->setBackgroundColor(1, c);}
|
||||
void setItemForeColor(QTreeWidgetItem * i, const QColor & c) {i->setForeground(0, c); i->setForeground(1, c);}
|
||||
void rebuild();
|
||||
void refresh();
|
||||
|
||||
QObject * object;
|
||||
QFont font_b;
|
||||
QList<QMetaProperty> props;
|
||||
|
||||
private slots:
|
||||
void itemClicked(QTreeWidgetItem * item, int column);
|
||||
void itemChanged(QTreeWidgetItem * item, int column);
|
||||
|
||||
};
|
||||
|
||||
#endif // PROPERTYEDITOR_H
|
||||
609
qglview/qglview.cpp
Normal file
@@ -0,0 +1,609 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qglview.h"
|
||||
|
||||
|
||||
QGLView::QGLView(QWidget * parent): QGraphicsView(parent), fbo_selection(3) {
|
||||
setFrameShape(QFrame::NoFrame);
|
||||
setViewportUpdateMode(FullViewportUpdate);
|
||||
setCacheMode(CacheNone);
|
||||
setViewport(new QGLWidget(QGLFormat(QGL::DoubleBuffer | QGL::DepthBuffer | QGL::Rgba | QGL::AlphaChannel | QGL::DirectRendering | QGL::SampleBuffers)));
|
||||
setMouseTracking(true);
|
||||
setFocusPolicy(Qt::WheelFocus);
|
||||
setScene(new QGraphicsScene());
|
||||
setInteractive(true);
|
||||
painter_ = 0;
|
||||
backColor_ = Qt::black;
|
||||
hoverHaloColor_ = QColor(195, 140, 255, 96);
|
||||
selectionHaloColor_ = QColor(175, 255, 140);
|
||||
ambientColor_ = QColor(10, 10, 10);
|
||||
lastPos = QPoint(-1, -1);
|
||||
lineWidth_ = 1.;
|
||||
linearFiltering_ = cameraOrbit_ = true;
|
||||
shaders_supported = selecting_ = customMouseMove_ = false;
|
||||
sel_button = Qt::LeftButton;
|
||||
sel_mod = Qt::NoModifier;
|
||||
anisotropicLevel_ = 8;
|
||||
renderer_ = 0;
|
||||
fps_cnt = 0;
|
||||
fps_tm = fps_ = 0.;
|
||||
sel_obj = hov_obj = 0;
|
||||
fogDensity_ = fogEnd_ = 1.;
|
||||
fogStart_ = 0.;
|
||||
fogMode_ = Exp;
|
||||
hoverHaloFill_ = 0.333;
|
||||
selectionHaloFill_ = 0.5;
|
||||
shadow_map_size = dynamic_cubemap_size = 512;
|
||||
//lmode = Simple;
|
||||
shader_select = shader_halo = shader_rope = 0;
|
||||
cur_luminance = 1.;
|
||||
accom_time = 32.;
|
||||
accom_max_speed = 0.1;
|
||||
mouse_first = mouseSelect_ = accomodation_ = hoverHalo_ = selectionHalo_ = true;
|
||||
fogEnabled_ = is_init = grabMouse_ = mouseRotate_ = mouseThis_ = shaders_bind = shadows_ = shadows_soft = dynamic_reflections = hdr_ = bloom_ = msaa_ = fxaa_ = changed_ = false;
|
||||
rmode = GLObjectBase::Fill;
|
||||
sel_mode = QGLView::SingleSelection;
|
||||
sel_pen = QPen(Qt::black, 1, Qt::DashLine);
|
||||
sel_brush = QBrush(QColor(170, 100, 255, 120));
|
||||
camera_.setAim(QVector3D(0,0,5.5));
|
||||
camera_.setPos(QVector3D(10, 5, 5.5));
|
||||
emit cameraPosChanged(camera_.pos());
|
||||
//camera_.aim_ = camera_.pos_;
|
||||
ktm_.restart();
|
||||
sh_lm_diff << "Phong_diffuse" << "Cook_Torrance_diffuse" << "Minnaert_diffuse" << "Strauss_diffuse" << "Oren_Nayar_diffuse";
|
||||
sh_lm_spec << "Phong_specular" << "Cook_Torrance_specular" << "Minnaert_specular" << "Strauss_specular" << "Oren_Nayar_specular";
|
||||
}
|
||||
|
||||
|
||||
QGLView::~QGLView() {
|
||||
if (shader_select != 0) delete shader_select;
|
||||
if (shader_halo != 0) delete shader_halo;
|
||||
if (shader_rope != 0) delete shader_rope;
|
||||
}
|
||||
|
||||
|
||||
void QGLView::addObject(QWidget * o, Qt::WindowFlags f) {
|
||||
scene()->addWidget(o, f)->setCacheMode(QGraphicsItem::ItemCoordinateCache);
|
||||
/*QList<QGraphicsItem * > il = collectGraphicItems();
|
||||
foreach (QGraphicsItem * i, il) {
|
||||
QGraphicsProxyWidget * p = qgraphicsitem_cast<QGraphicsProxyWidget * >(i);
|
||||
if (p == 0) continue;
|
||||
p->setCacheMode(QGraphicsItem::ItemCoordinateCache);
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
void QGLView::addObject(GLObjectBase * o) {
|
||||
o->view_ = this;
|
||||
objects_.addChild(o);
|
||||
collectLights();
|
||||
if (is_init) {
|
||||
globMutex.lock();
|
||||
o->init();
|
||||
globMutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QGLView::drawBackground(QPainter * painter, const QRectF & rect) {
|
||||
static bool f = true;
|
||||
painter_ = painter;
|
||||
painter_->beginNativePainting();
|
||||
if (f) {
|
||||
resizeGL(viewport()->width(), viewport()->height());
|
||||
initializeGL();
|
||||
}
|
||||
f = false;
|
||||
paintGL();
|
||||
painter_->endNativePainting();
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glReleaseTextures();
|
||||
QGraphicsView::drawBackground(painter_, rect);
|
||||
}
|
||||
|
||||
|
||||
void QGLView::initializeGL() {
|
||||
//qDebug() << "init glview";
|
||||
makeCurrent();
|
||||
currentQGLView = (QGLWidget * )viewport();
|
||||
currentGLTextureManager = &textures_manager;
|
||||
currentCamera = &camera_;
|
||||
//glEnable(GL_POLYGON_SMOOTH);
|
||||
glEnable(GL_TEXTURE_MAX_ANISOTROPY_EXT);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
//glEnable(GL_TEXTURE_2D);
|
||||
//glEnable(GL_TEXTURE_CUBE_MAP);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
|
||||
|
||||
glActiveTextureChannel(3);
|
||||
glEnable(GL_TEXTURE_GEN_S);
|
||||
glEnable(GL_TEXTURE_GEN_T);
|
||||
glEnable(GL_TEXTURE_GEN_R);
|
||||
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
|
||||
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
|
||||
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
glActiveTextureChannel(0);
|
||||
//glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NONE);
|
||||
//glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NONE);
|
||||
|
||||
//glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glColorMaterial(GL_FRONT, GL_DIFFUSE);
|
||||
|
||||
textures_manager.loadTextures();
|
||||
objects_.initInternal();
|
||||
checkCaps();
|
||||
|
||||
shader_select = new QGLShaderProgram(context());
|
||||
shader_halo = new QGLShaderProgram(context());
|
||||
shader_rope = new QGLShaderProgram(context());
|
||||
reloadThisShaders();
|
||||
is_init = true;
|
||||
|
||||
//dynamic_cubemap.loadPathesFromDirectory("e");
|
||||
//dynamic_cubemap.load();
|
||||
/*dynamic_cubemap.loadFront("e/front.jpg");
|
||||
dynamic_cubemap.loadBack("e/back.jpg");
|
||||
dynamic_cubemap.loadLeft("e/left.jpg");
|
||||
dynamic_cubemap.loadRight("e/right.jpg");
|
||||
dynamic_cubemap.loadTop("e/top.jpg");
|
||||
dynamic_cubemap.loadBottom("e/bottom.jpg");*/
|
||||
//glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
||||
//GLuint t = 0;
|
||||
//createGLTexture(t, QImage("e/bottom.jpg"));
|
||||
//qDebug() << bindTexture(QImage("e/bottom.jpg"));
|
||||
|
||||
emit glInitializeDone();
|
||||
}
|
||||
|
||||
|
||||
void QGLView::paintGL() {
|
||||
//QMutexLocker ml_v(&v_mutex);
|
||||
glEnable(GL_CULL_FACE);
|
||||
camera_.apply(aspect);
|
||||
|
||||
/// Selection detect
|
||||
//glClearFramebuffer(QColor(100, 0, 0, 0));
|
||||
if (mouseSelect_) {
|
||||
glReleaseTextures();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
glDepthMask(GL_TRUE);
|
||||
glDisable(GL_TEXTURE_1D);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_TEXTURE_CUBE_MAP);
|
||||
glDisable(GL_MULTISAMPLE);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glDisable(GL_RESCALE_NORMAL);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
fbo_selection.bind();
|
||||
fbo_selection.setWriteBuffer(0);
|
||||
glClearFramebuffer(QColor(0, 0, 0, 0));
|
||||
if (shaders_supported) shader_select->bind();
|
||||
renderSelection();
|
||||
if (shaders_supported) shader_select->release();
|
||||
uchar cgid[4] = {0, 0, 0, 0};
|
||||
uint iid;
|
||||
GLObjectBase * so = 0;
|
||||
if (!rect().contains(lastPos)) {
|
||||
if (hov_obj != 0) {
|
||||
hov_obj = 0;
|
||||
emit hoverChanged(0, hov_obj);
|
||||
}
|
||||
} else {
|
||||
glReadPixels(lastPos.x(), viewport()->height() - lastPos.y(), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, cgid);
|
||||
iid = (cgid[0] << 24) | (cgid[1] << 16) | (cgid[2] << 8) | cgid[3];
|
||||
so = ids[iid];
|
||||
//qDebug() <<cgid[0]<<cgid[1]<<cgid[2]<<cgid[3]<< iid;
|
||||
if (so != hov_obj) {
|
||||
emit hoverChanged(so, hov_obj);
|
||||
hov_obj = so;
|
||||
}
|
||||
//if (so != 0) qDebug() << sel_obj->name() << cgid[3];
|
||||
}
|
||||
if (hoverHalo_) {
|
||||
fbo_selection.setWriteBuffer(1);
|
||||
renderHalo(so, iid, hoverHaloColor_, hoverHaloFill_);
|
||||
}
|
||||
if (selectionHalo_) {
|
||||
fbo_selection.setWriteBuffer(2);
|
||||
renderHalo(sel_obj, ids.key(sel_obj), selectionHaloColor_, selectionHaloFill_);
|
||||
}
|
||||
fbo_selection.release();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_RESCALE_NORMAL);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
camera_.apply(aspect);
|
||||
|
||||
static GLRendererBase * prev_rend = 0;
|
||||
if (prev_rend != renderer_) {
|
||||
prev_rend = renderer_;
|
||||
if (renderer_ != 0) {
|
||||
renderer_->init(viewport()->width(), viewport()->height());
|
||||
renderer_->resize(viewport()->width(), viewport()->height());
|
||||
renderer_->reloadShaders();
|
||||
}
|
||||
}
|
||||
if (renderer_ != 0) renderer_->renderScene();
|
||||
if (selectionHalo_ || hoverHalo_) {
|
||||
glReleaseTextures();
|
||||
glReleaseShaders();
|
||||
glReleaseFramebuffer();
|
||||
glActiveTextureChannel(0);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_TEXTURE_CUBE_MAP);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
if (selectionHalo_) {
|
||||
glBindTexture(GL_TEXTURE_2D, fbo_selection.colorTexture(2));
|
||||
glDrawQuad();
|
||||
}
|
||||
if (hoverHalo_) {
|
||||
glBindTexture(GL_TEXTURE_2D, fbo_selection.colorTexture(1));
|
||||
glDrawQuad();
|
||||
}
|
||||
}
|
||||
|
||||
if (selecting_ && painter_) {
|
||||
painter_->setPen(sel_pen);
|
||||
painter_->setBrush(sel_brush);
|
||||
painter_->drawRect(QRect(downPos, lastPos).normalized());
|
||||
qDebug() << QRect(downPos, lastPos).normalized();
|
||||
}
|
||||
|
||||
emit glPainting();
|
||||
|
||||
/*releaseShaders();
|
||||
glActiveTextureChannel(0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glColor4f(0.3, 0.5, 0.8, 0.5);
|
||||
glResetAllTransforms();
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.f, 0.f); glVertex2f(-1.f, -1.f);
|
||||
glTexCoord2f(1.f, 0.f); glVertex2f(1.f, -1.);
|
||||
glTexCoord2f(1.f, 1.f); glVertex2f(1.f, 1.f);
|
||||
glTexCoord2f(0.f, 1.f); glVertex2f(-1.f, 1.f);
|
||||
glEnd();*/
|
||||
/*
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glDisable(GL_LIGHTING);
|
||||
glActiveTextureChannel(0);
|
||||
glBindTexture(GL_TEXTURE_2D, fbo->texture());
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(1.f, 1.f, 1.f);
|
||||
glTexCoord2f(0.f, 0.f); glVertex2f(-1.f, -1.f);
|
||||
glTexCoord2f(0.f, 1.f); glVertex2f(-1.f, 1.f);
|
||||
glTexCoord2f(1.f, 1.f); glVertex2f(1.f, 1.f);
|
||||
glTexCoord2f(1.f, 0.f); glVertex2f(1.f, -1.);
|
||||
glEnd();
|
||||
glEnable(GL_DEPTH_TEST);*/
|
||||
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;
|
||||
|
||||
//glResetAllTransforms();
|
||||
}
|
||||
|
||||
|
||||
void QGLView::renderHalo(const GLObjectBase * obj, const int iid, const QColor & color, const double & fill) {
|
||||
if (!shaders_supported) return;
|
||||
if (obj == 0) {
|
||||
glClearFramebuffer(Qt::black, false);
|
||||
} else {
|
||||
glActiveTextureChannel(0);
|
||||
glBindTexture(GL_TEXTURE_2D, fbo_selection.colorTexture());
|
||||
shader_halo->bind();
|
||||
shader_halo->setUniformValue("t0", 0);
|
||||
shader_halo->setUniformValue("dt", QVector2D(1. / viewport()->width(), 1. / viewport()->height()));
|
||||
shader_halo->setUniformValue("selected", QVector4D(float((iid >> 24) & 0xFF) / 255.f,
|
||||
float((iid >> 16) & 0xFF) / 255.f,
|
||||
float((iid >> 8) & 0xFF) / 255.f,
|
||||
float(iid & 0xFF) / 255.f));
|
||||
shader_halo->setUniformValue("color", color);
|
||||
shader_halo->setUniformValue("fill", GLfloat(fill));
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
glDrawQuad();
|
||||
glDepthMask(GL_TRUE);
|
||||
shader_halo->release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QGLView::renderSelection() {
|
||||
cid = 1;
|
||||
ids.clear();
|
||||
if (shaders_supported) sh_id_loc = shader_select->uniformLocation("id");
|
||||
//qDebug() << sh_id_loc;
|
||||
renderSingleSelection(objects_);
|
||||
}
|
||||
|
||||
|
||||
void QGLView::renderSingleSelection(GLObjectBase & o) {
|
||||
if (!o.isInit()) {
|
||||
o.init();
|
||||
o.loadTextures();
|
||||
}
|
||||
if (!o.visible_ || !o.select_) return;
|
||||
glPushMatrix();
|
||||
if (o.pos_.x() != 0. || o.pos_.y() != 0. || o.pos_.z() != 0.) qglTranslate(o.pos_);
|
||||
if (o.angles_.z() != 0.) glRotated(o.angles_.z(), 0., 0., 1.);
|
||||
if (o.angles_.y() != 0.) glRotated(o.angles_.y(), 0., 1., 0.);
|
||||
if (o.angles_.x() != 0.) glRotated(o.angles_.x(), 1., 0., 0.);
|
||||
if (o.scale_.x() != 1. || o.scale_.y() != 1. || o.scale_.z() != 1.) qglScale(o.scale_);
|
||||
ids.insert(cid, &o);
|
||||
if (shaders_supported) shader_select->setUniformValue(sh_id_loc, QVector4D(float((cid >> 24) & 0xFF) / 255.f,
|
||||
float((cid >> 16) & 0xFF) / 255.f,
|
||||
float((cid >> 8) & 0xFF) / 255.f,
|
||||
float(cid & 0xFF) / 255.f));
|
||||
else glColor4f(float((cid >> 24) & 0xFF) / 255.f,
|
||||
float((cid >> 16) & 0xFF) / 255.f,
|
||||
float((cid >> 8) & 0xFF) / 255.f,
|
||||
float(cid & 0xFF) / 255.f);
|
||||
//qDebug() << o.name() << "assign to" << sh_id_loc << cid;
|
||||
//glColor4f(float((cid >> 24) & 0xFF) / 255.f, float((cid >> 16) & 0xFF) / 255.f, float((cid >> 8) & 0xFF) / 255.f, float(cid & 0xFF) / 255.f);
|
||||
++cid;
|
||||
o.draw(true);
|
||||
foreach (GLObjectBase * i, o.children_)
|
||||
renderSingleSelection(*i);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
void QGLView::renderSingleShadow(GLObjectBase & o) {
|
||||
if (!o.isInit()) {
|
||||
o.init();
|
||||
o.loadTextures();
|
||||
}
|
||||
if (!o.visible_) return;
|
||||
glPushMatrix();
|
||||
if (o.pos_.x() != 0. || o.pos_.y() != 0. || o.pos_.z() != 0.) qglTranslate(o.pos_);
|
||||
if (o.angles_.z() != 0.) glRotated(o.angles_.z(), 0., 0., 1.);
|
||||
if (o.angles_.y() != 0.) glRotated(o.angles_.y(), 0., 1., 0.);
|
||||
if (o.angles_.x() != 0.) glRotated(o.angles_.x(), 1., 0., 0.);
|
||||
if (o.scale_.x() != 1. || o.scale_.y() != 1. || o.scale_.z() != 1.) qglScale(o.scale_);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, o.render_mode != GLObjectBase::View ? o.render_mode : (rmode != GLObjectBase::View ? rmode : GL_FILL));
|
||||
glLineWidth(o.line_width > 0. ? o.line_width : lineWidth_);
|
||||
glPointSize(o.line_width > 0. ? o.line_width : lineWidth_);
|
||||
o.draw(true);
|
||||
foreach (GLObjectBase * i, o.children_)
|
||||
renderSingleSelection(*i);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
void QGLView::collectLights() {
|
||||
lights_.clear();
|
||||
collectObjectLights(&objects_);
|
||||
}
|
||||
|
||||
|
||||
QList<QGraphicsItem * > QGLView::collectGraphicItems() {
|
||||
QList<QGraphicsItem * > list = scene()->items();
|
||||
foreach (QGraphicsItem * i, list)
|
||||
collectGraphicItems(list, i);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
void QGLView::collectGraphicItems(QList<QGraphicsItem * > & list, QGraphicsItem * o) {
|
||||
QList<QGraphicsItem * > cl = o->childItems();
|
||||
foreach (QGraphicsItem * i, cl) {
|
||||
list << i;
|
||||
collectGraphicItems(list, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QGLView::collectObjectLights(GLObjectBase * o) {
|
||||
if (o->type_ == GLObjectBase::Light) lights_ << globject_cast<Light * >(o);
|
||||
foreach (GLObjectBase * i, o->children())
|
||||
collectObjectLights(i);
|
||||
}
|
||||
|
||||
|
||||
void QGLView::checkCaps() {
|
||||
glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropic);
|
||||
shaders_supported = QGLShaderProgram::hasOpenGLShaderPrograms();
|
||||
}
|
||||
|
||||
|
||||
void QGLView::reloadThisShaders() {
|
||||
if (!shaders_supported) return;
|
||||
loadShaders(shader_select, "selection", "shaders");
|
||||
loadShaders(shader_halo, "selection_halo", "shaders");
|
||||
//loadShaders(shader_rope, "rope", "shaders");
|
||||
}
|
||||
|
||||
|
||||
inline void QGLView::applyFog() {
|
||||
GLfloat fog_col[4] = {float(fogColor_.redF()), float(fogColor_.greenF()), float(fogColor_.blueF()), .0f};
|
||||
if (fogEnabled_) {
|
||||
glEnable(GL_FOG);
|
||||
glFogf(GL_FOG_DENSITY, fogDensity_);
|
||||
glFogf(GL_FOG_START, fogStart_);
|
||||
glFogf(GL_FOG_END, fogEnd_);
|
||||
glFogi(GL_FOG_MODE, fogMode_);
|
||||
fog_col[0] = fogColor_.redF();
|
||||
fog_col[1] = fogColor_.greenF();
|
||||
fog_col[2] = fogColor_.blueF();
|
||||
glFogfv(GL_FOG_COLOR, fog_col);
|
||||
} else glDisable(GL_FOG);
|
||||
}
|
||||
|
||||
|
||||
void QGLView::resizeGL(int width, int height) {
|
||||
aspect = double(width) / double(height);
|
||||
if (renderer_ != 0) renderer_->resize(width, height);
|
||||
fbo_selection.resize(width, height);
|
||||
mouse_first = true;
|
||||
iaspect = (aspect == 0.) ? 0. : 1 / aspect;
|
||||
glViewport(0, 0, width, height);
|
||||
emit glResize(width, height);
|
||||
}
|
||||
|
||||
|
||||
void QGLView::mouseReleaseEvent(QMouseEvent * e) {
|
||||
QGraphicsView::mouseReleaseEvent(e);
|
||||
//setCursor(QCursor(Qt::ArrowCursor));
|
||||
selecting_ = false;
|
||||
if (mouseThis_ && mouseSelect_ && e->button() == Qt::LeftButton) {
|
||||
if ((lastPos - downPos).manhattanLength() < 8) {
|
||||
if (sel_obj != hov_obj) {
|
||||
emit selectionChanged(hov_obj, sel_obj);
|
||||
sel_obj = hov_obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
emit glMouseReleaseEvent(e);
|
||||
}
|
||||
|
||||
|
||||
void QGLView::mousePressEvent(QMouseEvent * e) {
|
||||
QGraphicsView::mousePressEvent(e);
|
||||
mouseThis_ = (scene()->itemAt(mapToScene(e->pos())) == 0);
|
||||
selecting_ = false;
|
||||
if (!mouseThis_) return;
|
||||
/// TODO select by rect
|
||||
//if (e->button() == sel_button && e->modifiers() == sel_mod)
|
||||
// selecting_ = true;
|
||||
lastPos = e->pos();
|
||||
downPos = lastPos;
|
||||
//qDebug() << mouseThis_;
|
||||
emit glMousePressEvent(e);
|
||||
}
|
||||
|
||||
|
||||
void QGLView::mouseMoveEvent(QMouseEvent * e) {
|
||||
QGraphicsView::mouseMoveEvent(e);
|
||||
//qDebug() << scene()->itemAt(mapToScene(e->pos()));
|
||||
//lastPos = e->pos();
|
||||
if (selecting_) {
|
||||
|
||||
return;
|
||||
}
|
||||
if (!mouseThis_) return;
|
||||
//if (scene()->itemAt(mapToScene(e->pos())) != 0) return;
|
||||
///qDebug() << e->x() << e->y();
|
||||
if (mouseRotate_) {
|
||||
double dx = e->x() - lastPos.x();
|
||||
double dy = e->y() - lastPos.y();
|
||||
if (e->buttons() & Qt::LeftButton) {
|
||||
//camera_.angle_z += dx / 4.;
|
||||
//camera_.angle_xy += dy / 4.;
|
||||
if (cameraOrbit_) {
|
||||
camera_.orbitZ(dx / 4.);
|
||||
camera_.orbitXY(dy / 4.);
|
||||
} else {
|
||||
camera_.rotateZ(dx / 4.);
|
||||
camera_.rotateXY(dy / 4.);
|
||||
}
|
||||
emit cameraPosChanged(camera_.pos());
|
||||
} else if (e->buttons() & Qt::RightButton) {
|
||||
camera_.moveLeft(dx / 100.);
|
||||
camera_.moveUp(dy / 100.);
|
||||
//camera_.pos.setX(camera_.pos.x() + camera_.pos.z() * dx / 500.);
|
||||
//camera_.pos.setY(camera_.pos.y() - camera_.pos.z() * dy / 500.);
|
||||
emit cameraPosChanged(camera_.pos());
|
||||
}
|
||||
//lights[0]->pos_ = camera_.pos();
|
||||
}
|
||||
if (customMouseMove_) emit customMouseMoveEvent(e->pos(), lastPos, e->buttons());
|
||||
lastPos = e->pos();
|
||||
if (grabMouse_) {
|
||||
//if (!isrunning) return;
|
||||
QCursor::setPos(mapToGlobal(rect().center()));
|
||||
static bool mouse_sec = false;
|
||||
if (mouse_sec) {
|
||||
mouse_sec = false;
|
||||
return;
|
||||
}
|
||||
if (mouse_first) {
|
||||
mouse_first = false;
|
||||
mouse_sec = true;
|
||||
//qDebug() << "first" << e->pos();
|
||||
return;
|
||||
}
|
||||
lastPos = rect().center();
|
||||
int dx = e->x() - lastPos.x();
|
||||
int dy = e->y() - lastPos.y();
|
||||
emit glMouseMoveEvent(new QMouseEvent(QEvent::MouseMove, QPoint(dx, dy), e->button(), e->buttons(), e->modifiers()));
|
||||
return;
|
||||
}
|
||||
//emit glMouseMoveEvent(e);
|
||||
}
|
||||
|
||||
|
||||
void QGLView::wheelEvent(QWheelEvent * e) {
|
||||
QGraphicsView::wheelEvent(e);
|
||||
if (scene()->itemAt(mapToScene(e->pos())) != 0) return;
|
||||
if (mouseRotate_) {
|
||||
if (e->delta() > 0) camera_.flyCloser(0.1); //camera_.pos.setZ(camera_.pos.z() - 0.1 * camera_.pos.z());
|
||||
if (e->delta() < 0) camera_.flyFarer(0.1); //camera_.pos.setZ(camera_.pos.z() + 0.1 * camera_.pos.z());
|
||||
emit cameraPosChanged(camera_.pos());
|
||||
}
|
||||
emit glWheelEvent(e);
|
||||
}
|
||||
|
||||
|
||||
void QGLView::processKeys() {
|
||||
if (ktm_.elapsed() < QApplication::keyboardInputInterval()) return;
|
||||
Qt::KeyboardModifiers km = QApplication::keyboardModifiers();
|
||||
foreach (int i, keys_)
|
||||
emit keyEvent((Qt::Key)i, km);
|
||||
}
|
||||
325
qglview/qglview.h
Normal file
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef QGLVIEW_H
|
||||
#define QGLVIEW_H
|
||||
|
||||
#include "glframebuffer.h"
|
||||
#include <QGraphicsProxyWidget>
|
||||
#include <QGraphicsView>
|
||||
#include <QGLWidget>
|
||||
#include <QGLShaderProgram>
|
||||
#include <QGLFramebufferObject>
|
||||
#include <QVector3D>
|
||||
#include <QTimer>
|
||||
#include <QTime>
|
||||
#include <QMouseEvent>
|
||||
#include <QDebug>
|
||||
#include <QMutex>
|
||||
#include <QThread>
|
||||
#include <QApplication>
|
||||
#include "glprimitives.h"
|
||||
#include "glparticles_system.h"
|
||||
|
||||
|
||||
class QGLView: public QGraphicsView, public QGLViewBase
|
||||
{
|
||||
friend class GLRendererBase;
|
||||
Q_OBJECT
|
||||
Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor)
|
||||
Q_PROPERTY (double lineWidth READ lineWidth WRITE setLineWidth)
|
||||
Q_PROPERTY (double FOV READ FOV WRITE setFOV)
|
||||
Q_PROPERTY (double depthStart READ depthStart WRITE setDepthStart)
|
||||
Q_PROPERTY (double depthEnd READ depthEnd WRITE setDepthEnd)
|
||||
Q_PROPERTY (bool linearFiltering READ linearFiltering WRITE setLinearFiltering)
|
||||
Q_PROPERTY (int anisotropicLevel READ anisotropicLevel WRITE setAnisotropicLevel)
|
||||
Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor)
|
||||
Q_PROPERTY (QColor fogColor READ fogColor WRITE setFogColor)
|
||||
Q_PROPERTY (double fogDensity READ fogDensity WRITE setFogDensity)
|
||||
Q_PROPERTY (double fogStart READ fogStart WRITE setFogStart)
|
||||
Q_PROPERTY (double fogEnd READ fogEnd WRITE setFogEnd)
|
||||
Q_PROPERTY (FogMode fogMode READ fogMode WRITE setFogMode)
|
||||
Q_PROPERTY (bool fogEnabled READ isFogEnabled WRITE setFogEnabled)
|
||||
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 (double hoverHaloFillAlpha READ hoverHaloFillAlpha WRITE setHoverHaloFillAlpha)
|
||||
Q_PROPERTY (bool selectionHalo READ isSelectionHaloEnabled WRITE setSelectionHaloEnabled)
|
||||
Q_PROPERTY (QColor selectionHaloColor READ selectionHaloColor WRITE setSelectionHaloColor)
|
||||
Q_PROPERTY (double selectionHaloFillAlpha READ selectionHaloFillAlpha WRITE setSelectionHaloFillAlpha)
|
||||
//Q_PROPERTY (LightingMode lightingMode READ lightingMode WRITE setLightingMode)
|
||||
Q_PROPERTY (bool shadowsEnabled READ isShadowsEnabled WRITE setShadowsEnabled)
|
||||
Q_PROPERTY (bool softShadowsEnabled READ isSoftShadowsEnabled WRITE setSoftShadowsEnabled)
|
||||
Q_PROPERTY (int shadowMapSize READ shadowMapSize WRITE setShadowMapSize)
|
||||
Q_PROPERTY (bool dynamicReflectionsEnabled READ isDynamicReflectionsEnabled WRITE setDynamicReflectionsEnabled)
|
||||
Q_PROPERTY (int dynamicReflectionsMapSize READ dynamicReflectionsMapSize WRITE setDynamicReflectionsMapSize)
|
||||
Q_PROPERTY (bool HDREnabled READ isHDREnabled WRITE setHDREnabled)
|
||||
Q_PROPERTY (bool bloomEnabled READ isBloomEnabled WRITE setBloomEnabled)
|
||||
Q_PROPERTY (bool multisamplingEnabled READ isMultisamplingEnabled WRITE setMultisamplingEnabled)
|
||||
Q_PROPERTY (bool FXAAEnabled READ isFXAAEnabled WRITE setFXAAEnabled)
|
||||
Q_PROPERTY (bool accomodationEnabled READ isAccomodationEnabled WRITE setAccomodationEnabled)
|
||||
Q_PROPERTY (double accomodationTime READ accomodationTime WRITE setAccomodationTime)
|
||||
Q_PROPERTY (double accomodationMaxSpeed READ accomodationMaxSpeed WRITE setAccomodationMaxSpeed)
|
||||
Q_PROPERTY (Qt::MouseButton selectionButton READ selectionButton WRITE setSelectionButton)
|
||||
Q_PROPERTY (Qt::KeyboardModifier selectionModifier READ selectionModifier WRITE setSelectionModifier)
|
||||
Q_PROPERTY (SelectionMode selectionMode READ selectionMode WRITE setSelectionMode)
|
||||
Q_PROPERTY (QPen selectionRectPen READ selectionRectPen WRITE setSelectionRectPen)
|
||||
Q_PROPERTY (QBrush selectionRectBrush READ selectionRectBrush WRITE setSelectionRectBrush)
|
||||
|
||||
public:
|
||||
QGLView(QWidget * parent = 0);
|
||||
virtual ~QGLView();
|
||||
|
||||
enum FogMode {Linear = GL_LINEAR, Exp = GL_EXP, Exp2 = GL_EXP2};
|
||||
enum SelectionMode {NoSelection, SingleSelection, MultiSelection};
|
||||
|
||||
Q_ENUMS (FogMode)
|
||||
Q_ENUMS (SelectionMode)
|
||||
//enum LightingMode {Simple, PerPixel, DeferredShading};
|
||||
//Q_ENUMS (LightingMode)
|
||||
|
||||
void stop() {killTimer(timer);}
|
||||
void start(double freq = 40.) {timer = startTimer(freq <= 0. ? 0 : 1000. / freq);}
|
||||
|
||||
GLRendererBase * renderer() {return renderer_;}
|
||||
void setRenderer(GLRendererBase * r, GLRendererBase ** prev = 0) {if (prev != 0) *prev = renderer_; renderer_ = r;}
|
||||
|
||||
const QGLContext * context() const {return ((const QGLWidget * )viewport())->context();}
|
||||
void makeCurrent() {((QGLWidget * )viewport())->makeCurrent();}
|
||||
|
||||
QColor backColor() const {return backColor_;}
|
||||
double lineWidth() const {return lineWidth_;}
|
||||
double FOV() const {return camera_.fov_;}
|
||||
double depthStart() const {return camera_.depth_start;}
|
||||
double depthEnd() const {return camera_.depth_end;}
|
||||
double currentFPS() const {return fps_;}
|
||||
bool linearFiltering() const {return linearFiltering_;}
|
||||
int anisotropicLevel() const {return anisotropicLevel_;}
|
||||
int maxAnisotropicLevel() const {return max_anisotropic;}
|
||||
int shadowMapSize() const {return shadow_map_size;}
|
||||
int dynamicReflectionsMapSize() const {return dynamic_cubemap_size;}
|
||||
|
||||
QColor ambientColor() const {return ambientColor_;}
|
||||
QColor fogColor() const {return fogColor_;}
|
||||
double fogDensity() const {return fogDensity_;}
|
||||
double fogStart() const {return fogStart_;}
|
||||
double fogEnd() const {return fogEnd_;}
|
||||
FogMode fogMode() const {return fogMode_;}
|
||||
//LightingMode lightingMode() const {return lmode;}
|
||||
bool isFogEnabled() const {return fogEnabled_;}
|
||||
bool isGrabMouseEnabled() const {return grabMouse_;}
|
||||
bool isMouseRotateEnabled() const {return mouseRotate_;}
|
||||
bool isMouseSelectionEnabled() const {return mouseSelect_;}
|
||||
bool isCameraOrbit() const {return cameraOrbit_;}
|
||||
bool isHoverHaloEnabled() const {return hoverHalo_;}
|
||||
QColor hoverHaloColor() const {return hoverHaloColor_;}
|
||||
double hoverHaloFillAlpha() const {return hoverHaloFill_;}
|
||||
bool isSelectionHaloEnabled() const {return selectionHalo_;}
|
||||
QColor selectionHaloColor() const {return selectionHaloColor_;}
|
||||
double selectionHaloFillAlpha() const {return selectionHaloFill_;}
|
||||
bool isShadowsEnabled() const {return shadows_;}
|
||||
bool isSoftShadowsEnabled() const {return shadows_soft;}
|
||||
bool isDynamicReflectionsEnabled() const {return dynamic_reflections;}
|
||||
bool isHDREnabled() const {return hdr_;}
|
||||
bool isBloomEnabled() const {return bloom_;}
|
||||
bool isMultisamplingEnabled() const {return msaa_;}
|
||||
bool isFXAAEnabled() const {return fxaa_;}
|
||||
bool isAccomodationEnabled() const {return accomodation_;}
|
||||
|
||||
int renderMode() const {return (int)rmode;}
|
||||
void setRenderMode(int mode) {rmode = (GLObjectBase::RenderMode)mode;}
|
||||
|
||||
double accomodationTime() const {return accom_time;}
|
||||
double accomodationMaxSpeed() const {return accom_max_speed;}
|
||||
|
||||
void addObject(QGraphicsItem * o) {scene()->addItem(o);}
|
||||
void addObject(QWidget * o, Qt::WindowFlags f = Qt::Widget);
|
||||
void addObject(GLObjectBase * o);
|
||||
void addObject(GLObjectBase & o) {addObject(&o);}
|
||||
int objectsCount(bool all = false) {if (!all) return objects_.childCount(); int cnt = 0; objectsCountInternal(&cnt, &objects_); return cnt;}
|
||||
void removeObject(GLObjectBase * o, bool inChildren = true) {if (inChildren) removeObjectInternal(o, &objects_); else objects_.removeChild(o);}
|
||||
void removeObject(GLObjectBase & o, bool inChildren = true) {removeObject(&o, inChildren);}
|
||||
void clearObjects(bool deleteAll = false) {objects_.clearChildren(deleteAll);}
|
||||
QList<GLObjectBase * > objects(bool all = false) {return objects_.children(all);}
|
||||
|
||||
int lightsCount() const {return lights_.size();}
|
||||
void removeLight(int index) {removeObject(lights_.at(index)); lights_.removeAt(index);}
|
||||
void removeLight(Light * l) {foreach (Light * i, lights_) removeObject(i); lights_.removeAll(l);}
|
||||
void clearLights(bool deleteAll = false) {if (deleteAll) foreach (Light * i, lights_) delete i; lights_.clear();}
|
||||
QList<Light * > lights() {return lights_;}
|
||||
|
||||
GLTextureManager * textureManager() {return &textures_manager;}
|
||||
void addTexture(const QString & path) {textures_manager.addTexture(path);}
|
||||
void addAnimation(const QString & dir, const QString & name) {textures_manager.addAnimation(dir, name);}
|
||||
|
||||
GLObjectBase * object(int index) {return objects_.child(index);}
|
||||
GLObjectBase * object(const QString & name) {return objects_.child(name);}
|
||||
Light * light(int index) {return lights_[index];}
|
||||
Light * light(const QString & name) {foreach (Light * i, lights_) if (i->name_ == name) return i; return 0;}
|
||||
|
||||
QPen selectionRectPen() const {return sel_pen;}
|
||||
QBrush selectionRectBrush() const {return sel_brush;}
|
||||
SelectionMode selectionMode() const {return sel_mode;}
|
||||
Qt::MouseButton selectionButton() const {return sel_button;}
|
||||
Qt::KeyboardModifier selectionModifier() const {return sel_mod;}
|
||||
|
||||
void setSelectionMode(SelectionMode v) {sel_mode = v;}
|
||||
void setSelectionButton(Qt::MouseButton v) {sel_button = v;}
|
||||
void setSelectionModifier(Qt::KeyboardModifier v) {sel_mod = v;}
|
||||
void setSelectionRectPen(const QPen & v) {sel_pen = v;}
|
||||
void setSelectionRectBrush(const QBrush & v) {sel_brush = v;}
|
||||
|
||||
GLdouble aspect, iaspect;
|
||||
QGLShaderProgram * shader_rope;
|
||||
|
||||
protected:
|
||||
virtual void drawBackground(QPainter * painter, const QRectF & rect);
|
||||
virtual void resizeEvent(QResizeEvent * e) {resizeGL(viewport()->width(), viewport()->height()); QGraphicsView::resizeEvent(e);}
|
||||
|
||||
void timerEvent(QTimerEvent * ) {/*globMutex.lock();*/ processKeys(); viewport()->repaint(); /*globMutex.unlock();*/}
|
||||
void initializeGL();
|
||||
void paintGL();
|
||||
void resizeGL(int width, int height);
|
||||
virtual void mousePressEvent(QMouseEvent * e);
|
||||
virtual void mouseMoveEvent(QMouseEvent * e);
|
||||
virtual void mouseReleaseEvent(QMouseEvent * e);
|
||||
virtual void wheelEvent(QWheelEvent * e);
|
||||
virtual void keyPressEvent(QKeyEvent * e) {emit glKeyPressEvent(e); if (e->key() > 0) keys_.insert(e->key());}
|
||||
virtual void keyReleaseEvent(QKeyEvent * e) {emit glKeyReleaseEvent(e); keys_.remove(e->key());}
|
||||
virtual void focusOutEvent(QFocusEvent *) {keys_.clear();}
|
||||
|
||||
inline void applyFog();
|
||||
void renderSelection();
|
||||
void renderShadow() {renderSingleShadow(objects_);}
|
||||
|
||||
void checkCaps();
|
||||
void collectLights();
|
||||
|
||||
private:
|
||||
void collectObjectLights(GLObjectBase * o);
|
||||
void objectsCountInternal(int * cnt, GLObjectBase * where) {++(*cnt); foreach (GLObjectBase * i, where->children_) objectsCountInternal(cnt, i);}
|
||||
void removeObjectInternal(GLObjectBase * o, GLObjectBase * where) {foreach (GLObjectBase * i, where->children_) {if (o == i) where->removeChild(i); else removeObjectInternal(o, i);}}
|
||||
void renderSingleSelection(GLObjectBase & o);
|
||||
void renderSingleShadow(GLObjectBase & o);
|
||||
void renderHalo(const GLObjectBase * obj, const int iid, const QColor & color, const double & fill);
|
||||
void applyLightShader(Material::LightModel type);
|
||||
QList<QGraphicsItem * > collectGraphicItems();
|
||||
void collectGraphicItems(QList<QGraphicsItem * > & list, QGraphicsItem * o);
|
||||
void reloadThisShaders();
|
||||
void processKeys();
|
||||
|
||||
QPoint lastPos, downPos;
|
||||
QMutex v_mutex;
|
||||
GLTextureManager textures_manager;
|
||||
GLObjectBase objects_;
|
||||
QList<Light * > lights_;
|
||||
uint cid;
|
||||
QMap<uint, GLObjectBase * > ids;
|
||||
QSet<int> keys_;
|
||||
FogMode fogMode_;
|
||||
QColor backColor_, fogColor_, ambientColor_, hoverHaloColor_, selectionHaloColor_;
|
||||
QPainter * painter_;
|
||||
QTime time, ktm_;
|
||||
QPen sel_pen;
|
||||
QBrush sel_brush;
|
||||
GLint max_anisotropic, anisotropicLevel_;
|
||||
GLObjectBase::RenderMode rmode;
|
||||
//LightingMode lmode;
|
||||
GLObjectBase * sel_obj, * hov_obj;
|
||||
GLFramebuffer fbo_selection;
|
||||
QGLShaderProgram * shader_select, * shader_halo;
|
||||
QStringList sh_lm_diff, sh_lm_spec;
|
||||
GLRendererBase * renderer_;
|
||||
SelectionMode sel_mode;
|
||||
Qt::MouseButton sel_button;
|
||||
Qt::KeyboardModifier sel_mod;
|
||||
double lineWidth_, linearFiltering_, accom_time, accom_max_speed, cur_luminance;
|
||||
double fogDensity_, fogStart_, fogEnd_, fps_, fps_tm, hoverHaloFill_, selectionHaloFill_;
|
||||
int timer, fps_cnt, sh_id_loc, shadow_map_size, dynamic_cubemap_size;
|
||||
bool is_init, fogEnabled_, grabMouse_, mouse_first, mouseRotate_, mouseSelect_, customMouseMove_;
|
||||
bool hoverHalo_, selectionHalo_, mouseThis_, shaders_bind, shadows_, shadows_soft, selecting_;
|
||||
bool shaders_supported, dynamic_reflections, hdr_, bloom_, msaa_, fxaa_, accomodation_, changed_, cameraOrbit_;
|
||||
|
||||
public slots:
|
||||
void setBackColor(const QColor & arg) {backColor_ = arg;}
|
||||
void setLineWidth(const double & arg) {lineWidth_ = arg;}
|
||||
void setFOV(const double & arg) {camera_.fov_ = arg;}
|
||||
void setDepthStart(const double & arg) {camera_.depth_start = arg;}
|
||||
void setDepthEnd(const double & arg) {camera_.depth_end = arg;}
|
||||
void setLinearFiltering(const bool & arg) {linearFiltering_ = arg;}
|
||||
void setAnisotropicLevel(const int & arg) {anisotropicLevel_ = arg;}
|
||||
void setAmbientColor(const QColor & arg) {ambientColor_ = arg;}
|
||||
void setFogColor(const QColor & arg) {fogColor_ = arg;}
|
||||
void setFogDensity(const double & arg) {fogDensity_ = arg;}
|
||||
void setFogStart(const double & arg) {fogStart_ = arg;}
|
||||
void setFogEnd(const double & arg) {fogEnd_ = arg;}
|
||||
void setFogMode(const FogMode & arg) {fogMode_ = arg;}
|
||||
void setFogEnabled(const bool & arg) {fogEnabled_ = arg;}
|
||||
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;}
|
||||
void setHoverHaloEnabled(const bool & arg) {hoverHalo_ = arg;}
|
||||
void setHoverHaloColor(const QColor & arg) {hoverHaloColor_ = arg;}
|
||||
void setHoverHaloFillAlpha(const double & arg) {hoverHaloFill_ = arg;}
|
||||
void setSelectionHaloEnabled(const bool & arg) {selectionHalo_ = arg;}
|
||||
void setSelectionHaloColor(const QColor & arg) {selectionHaloColor_ = arg;}
|
||||
void setSelectionHaloFillAlpha(const double & arg) {selectionHaloFill_ = arg;}
|
||||
//void setLightingMode(const LightingMode & arg) {lmode = arg;}
|
||||
void setShadowsEnabled(const bool & arg) {shadows_ = arg;}
|
||||
void setSoftShadowsEnabled(const bool & arg) {shadows_soft = arg;}
|
||||
void setShadowMapSize(const int & arg) {shadow_map_size = arg; changed_ = true;}
|
||||
void setDynamicReflectionsMapSize(const int & arg) {dynamic_cubemap_size = arg; changed_ = true;}
|
||||
void setAccomodationTime(const double & arg) {accom_time = arg;}
|
||||
void setAccomodationMaxSpeed(const double & arg) {accom_max_speed = arg;}
|
||||
void setDynamicReflectionsEnabled(const bool & arg) {dynamic_reflections = arg;}
|
||||
void setHDREnabled(const bool & arg) {hdr_ = arg; changed_ = true;}
|
||||
void setBloomEnabled(const bool & arg) {bloom_ = arg; changed_ = true;}
|
||||
void setMultisamplingEnabled(const bool & arg) {msaa_ = arg;}
|
||||
void setFXAAEnabled(const bool & arg) {fxaa_ = arg;}
|
||||
void setAccomodationEnabled(const bool & arg) {accomodation_ = arg;}
|
||||
|
||||
void reloadShaders() {if (renderer_ != 0) renderer_->reloadShaders(); reloadThisShaders();}
|
||||
void deselect() {sel_obj = 0;}
|
||||
|
||||
signals:
|
||||
void glBeginPaint();
|
||||
void glPainting();
|
||||
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(GLObjectBase * cur, GLObjectBase * prev);
|
||||
void selectionChanged(GLObjectBase * cur, GLObjectBase * prev);
|
||||
|
||||
};
|
||||
|
||||
#endif // QGLVIEW_H
|
||||
3
qglview/qglview.kdev4
Normal file
@@ -0,0 +1,3 @@
|
||||
[Project]
|
||||
Manager=KDevCMakeManager
|
||||
Name=qglview
|
||||
BIN
qglview/qglview_test.exe
Normal file
115
qglview/renderer_deferred_shading.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "renderer_deferred_shading.h"
|
||||
|
||||
|
||||
RendererDeferredShading::RendererDeferredShading(QGLView * view_): GLRendererBase(view_), fbo(5, true, GL_RGBA16F) {
|
||||
shader_fxaa = shader_ds_0 = shader_ds_1 = 0;
|
||||
}
|
||||
|
||||
|
||||
void RendererDeferredShading::renderScene() {
|
||||
int passes = (view.lightsCount() - 1) / 8 + 1;
|
||||
QMatrix4x4 pm = getGLMatrix(GL_PROJECTION_MATRIX);//, mvm = getGLMatrix(GL_MODELVIEW_MATRIX), pmvm = pm * mvm, lpm, lmvm, lpmvm;
|
||||
if (passes < 1) passes = 1;
|
||||
fbo.bind();
|
||||
int buffs[] = {0, 1, 2};
|
||||
fbo.setWriteBuffers(buffs);
|
||||
glClearFramebuffer(QColor(0, 0, 0, 0));
|
||||
//glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
glDepthMask(GL_TRUE);
|
||||
shader_ds_0->bind();
|
||||
shader_ds_0->setUniformValue("t0", 0);
|
||||
shader_ds_0->setUniformValue("t1", 1);
|
||||
shader_ds_0->setUniformValue("t2", 2);
|
||||
shader_ds_0->setUniformValue("dt", QVector2D(1. / view.viewport()->width(), 1. / view.viewport()->height()));
|
||||
renderObjects(GLObjectBase::Solid, 0, 0, true, false, false);
|
||||
//glReleaseShaders();
|
||||
//fbo.release();
|
||||
|
||||
glSetLightEnabled(false);
|
||||
glDisable(GL_BLEND);
|
||||
//glBlendFunc(GL_ONE, GL_ONE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
shader_ds_1->bind();
|
||||
shader_ds_1->setUniformValue("t0", 0);
|
||||
shader_ds_1->setUniformValue("t1", 1);
|
||||
shader_ds_1->setUniformValue("t2", 2);
|
||||
shader_ds_1->setUniformValue("back_color", view.backColor());
|
||||
shader_ds_1->setUniformValue("mat", pm.inverted());
|
||||
shader_ds_1->setUniformValue("dt", QVector2D(1. / view.viewport()->width(), 1. / view.viewport()->height()));
|
||||
fbo.setWriteBuffer(3);
|
||||
fbo.bindColorTextures();
|
||||
glClearFramebuffer(Qt::black, false);
|
||||
QVector<QVector4D> lpos;
|
||||
GLfloat glmvm[16];
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, glmvm);
|
||||
//glResetAllTransforms();
|
||||
for (int l = 0; l < passes; ++l) {
|
||||
fbo.setWriteBuffer(4 - l % 2);
|
||||
shader_ds_1->setUniformValue("tb", 3 + l % 2);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadMatrixf(glmvm);
|
||||
setupLights(l, 8);
|
||||
shader_ds_1->setUniformValue("lightsCount", cplc);
|
||||
glDrawQuad();
|
||||
//renderObjects(GLObjectBase::Solid, l, 0, true, true, view.isFogEnabled());
|
||||
//renderObjects(GLObjectBase::Transparent, l, 0, true, true, view.isFogEnabled());
|
||||
glFinish();
|
||||
}
|
||||
fbo.release();
|
||||
glReleaseShaders();
|
||||
glActiveTextureChannel(0);
|
||||
glBindTexture(GL_TEXTURE_2D, fbo.colorTexture(3 + passes % 2));
|
||||
if (view.isFXAAEnabled()) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
shader_fxaa->bind();
|
||||
shader_fxaa->setUniformValue("dt", QVector2D(1. / view.viewport()->width(), 1. / view.viewport()->height()));
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
}
|
||||
glDrawQuad();
|
||||
if (view.isFXAAEnabled())
|
||||
shader_fxaa->release();
|
||||
}
|
||||
|
||||
|
||||
void RendererDeferredShading::reloadShaders() {
|
||||
if (shader_fxaa == 0) shader_fxaa = new QGLShaderProgram(view.context());
|
||||
if (shader_ds_0 == 0) shader_ds_0 = new QGLShaderProgram(view.context());
|
||||
if (shader_ds_1 == 0) shader_ds_1 = new QGLShaderProgram(view.context());
|
||||
//if (shader_ds_0 == 0) shader_ds_0 = new QGLShaderProgram(view.context());
|
||||
loadShaders(shader_fxaa, "FXAA", "shaders");
|
||||
loadShaders(shader_ds_0, "dsl_pass_0", "shaders");
|
||||
loadShaders(shader_ds_1, "dsl_pass_1", "shaders");
|
||||
}
|
||||
|
||||
|
||||
void RendererDeferredShading::setupShadersTextures(GLObjectBase & object, GLRendererBase::RenderingParameters & rp) {
|
||||
shader_ds_0->setUniformValue("has_diffuse", object.material().diffuse.bitmap_id != 0);
|
||||
shader_ds_0->setUniformValue("has_bump", object.material().bump.bitmap_id != 0);
|
||||
shader_ds_0->setUniformValue("has_height", object.material().relief.bitmap_id != 0);
|
||||
shader_ds_0->setUniformValue("bump_scale", object.material().bump_scale);
|
||||
shader_ds_0->setUniformValue("height_scale", object.material().relief_scale);
|
||||
}
|
||||
46
qglview/renderer_deferred_shading.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef RENDERER_DEFERRED_SHADING_H
|
||||
#define RENDERER_DEFERRED_SHADING_H
|
||||
|
||||
#include "qglview.h"
|
||||
|
||||
class RendererDeferredShading: public GLRendererBase
|
||||
{
|
||||
public:
|
||||
RendererDeferredShading(QGLView * view);
|
||||
virtual ~RendererDeferredShading() {if (shader_fxaa != 0) delete shader_fxaa;}
|
||||
|
||||
virtual void renderScene();
|
||||
|
||||
protected:
|
||||
virtual void init(int width, int height) {fbo.resize(width, height);}
|
||||
virtual void resize(int width, int height) {fbo.resize(width, height);}
|
||||
virtual void reloadShaders();
|
||||
virtual void setupShadersTextures(GLObjectBase & object, RenderingParameters & rp);
|
||||
virtual void setupShadersLights(int lights_count) {cplc = lights_count;}
|
||||
|
||||
private:
|
||||
int cplc;
|
||||
GLFramebuffer fbo;
|
||||
QGLShaderProgram * shader_fxaa, * shader_ds_0, * shader_ds_1;
|
||||
|
||||
};
|
||||
|
||||
#endif // RENDERER_DEFERRED_SHADING_H
|
||||
91
qglview/renderer_simple.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "renderer_simple.h"
|
||||
|
||||
|
||||
RendererSimple::RendererSimple(QGLView * view_): GLRendererBase(view_), fbo(2) {
|
||||
shader_fxaa = 0;
|
||||
}
|
||||
|
||||
|
||||
void RendererSimple::renderScene() {
|
||||
int passes = (view.lightsCount() - 1) / 8 + 1;
|
||||
//QMatrix4x4 pm = getGLMatrix(GL_PROJECTION_MATRIX), mvm = getGLMatrix(GL_MODELVIEW_MATRIX), pmvm = pm * mvm, lpm, lmvm, lpmvm;
|
||||
glSetCapEnabled(GL_MULTISAMPLE, view.isMultisamplingEnabled());
|
||||
if (passes < 1) passes = 1;
|
||||
//glEnable(GL_FOG);
|
||||
if (view.isFXAAEnabled()) fbo.bind();
|
||||
//glEnable(GL_TEXTURE_2D);
|
||||
if (passes > 1) {
|
||||
fbo.bind();
|
||||
fbo.setWriteBuffer(0);
|
||||
glClearFramebuffer();
|
||||
}
|
||||
for (int l = 0; l < passes; ++l) {
|
||||
if (passes > 1) fbo.setWriteBuffer(1);
|
||||
if (l == 0) {
|
||||
glClearFramebuffer(view.backColor());
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
glDepthMask(GL_TRUE);
|
||||
} else {
|
||||
glClearFramebuffer(Qt::black, false);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
glDepthFunc(GL_EQUAL);
|
||||
}
|
||||
view.camera().apply(view.aspect);
|
||||
setupLights(l, 8);
|
||||
//glEnable(GL_MULTISAMPLE);
|
||||
renderObjects(GLObjectBase::Solid, l, 0, true, true, view.isFogEnabled());
|
||||
renderObjects(GLObjectBase::Transparent, l, 0, true, true, view.isFogEnabled());
|
||||
if (passes > 1) {
|
||||
glSetLightEnabled(false);
|
||||
glSetCapEnabled(GL_BLEND);
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
glReleaseTextures();
|
||||
glBindTexture(GL_TEXTURE_2D, fbo.colorTexture(1));
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
fbo.setWriteBuffer(0);
|
||||
glDrawQuad();
|
||||
}
|
||||
}
|
||||
if (view.isFXAAEnabled() || passes > 1) {
|
||||
fbo.release();
|
||||
//glClearFramebuffer();
|
||||
glActiveTextureChannel(0);
|
||||
glBindTexture(GL_TEXTURE_2D, fbo.colorTexture());
|
||||
glSetLightEnabled(false);
|
||||
glSetCapEnabled(GL_BLEND, false);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
if (view.isFXAAEnabled()) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
shader_fxaa->bind();
|
||||
shader_fxaa->setUniformValue("dt", QVector2D(1. / view.viewport()->width(), 1. / view.viewport()->height()));
|
||||
glDrawQuad();
|
||||
shader_fxaa->release();
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glDrawQuad();
|
||||
}
|
||||
}
|
||||
}
|
||||
43
qglview/renderer_simple.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef RENDERER_SIMPLE_H
|
||||
#define RENDERER_SIMPLE_H
|
||||
|
||||
#include "qglview.h"
|
||||
|
||||
class RendererSimple: public GLRendererBase
|
||||
{
|
||||
public:
|
||||
RendererSimple(QGLView * view);
|
||||
virtual ~RendererSimple() {if (shader_fxaa != 0) delete shader_fxaa;}
|
||||
|
||||
virtual void renderScene();
|
||||
|
||||
protected:
|
||||
virtual void init(int width, int height) {fbo.resize(width, height);}
|
||||
virtual void resize(int width, int height) {fbo.resize(width, height);}
|
||||
virtual void reloadShaders() {if (shader_fxaa == 0) shader_fxaa = new QGLShaderProgram(view.context()); loadShaders(shader_fxaa, "FXAA", "shaders");}
|
||||
|
||||
private:
|
||||
GLFramebuffer fbo;
|
||||
QGLShaderProgram * shader_fxaa;
|
||||
|
||||
};
|
||||
|
||||
#endif // RENDERER_SIMPLE_H
|
||||
66
qglview/rope_system.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "rope_system.h"
|
||||
#include "qglview.h"
|
||||
|
||||
|
||||
RopeSystem::RopeSystem(): GLObjectBase(), fbo(2, false, GL_RGBA16F, GL_TEXTURE_1D) {
|
||||
tex[0] = tex[1] = tex[2] = 0;
|
||||
}
|
||||
|
||||
|
||||
RopeSystem::~RopeSystem() {
|
||||
}
|
||||
|
||||
|
||||
void RopeSystem::init() {
|
||||
pos.clear();
|
||||
for (int i = 0; i < 1024; ++i)
|
||||
pos << (i - 512) / 51.2f << 0.f << 20.f << 0.1f;
|
||||
deleteGLTexture(tex[0]);
|
||||
deleteGLTexture(tex[1]);
|
||||
deleteGLTexture(tex[2]);
|
||||
glGenTextures(3, tex);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_1D, tex[0]);
|
||||
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA16F, 1024, 0, GL_RGBA, GL_FLOAT, pos.constData());
|
||||
glBindTexture(GL_TEXTURE_1D, tex[1]);
|
||||
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA16F, 1024, 0, GL_RGBA, GL_FLOAT, pos.constData());
|
||||
glBindTexture(GL_TEXTURE_1D, tex[2]);
|
||||
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA16F, 1024, 0, GL_RGBA, GL_FLOAT, pos.constData());
|
||||
}
|
||||
|
||||
|
||||
void RopeSystem::draw(bool simplest) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_1D, tex[0]);
|
||||
glGetTexImage(GL_TEXTURE_1D, 0, GL_RGBA, GL_FLOAT, pos.data());
|
||||
glColor3f(1.f, 1.f, 1.f);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
int ind = 0;
|
||||
for (int i = 0; i < 1024; ++i) {
|
||||
ind = i * 4;
|
||||
glVertex3f(pos[ind], pos[ind + 1], pos[ind + 2]);
|
||||
}
|
||||
glEnd();
|
||||
/*((QGLView * )view_)->shader_rope->bind();
|
||||
((QGLView * )view_)->shader_rope->setUniformValue("t0", 0);
|
||||
((QGLView * )view_)->shader_rope->setUniformValue("dt", 1.f / 1024.f);
|
||||
((QGLView * )view_)->shader_rope->release();*/
|
||||
}
|
||||
41
qglview/rope_system.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Water system
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ROPE_SYSTEM_H
|
||||
#define ROPE_SYSTEM_H
|
||||
|
||||
#include "globject.h"
|
||||
|
||||
class RopeSystem: public GLObjectBase
|
||||
{
|
||||
public:
|
||||
RopeSystem();
|
||||
~RopeSystem();
|
||||
|
||||
virtual void draw(bool simplest = false);
|
||||
virtual void init();
|
||||
virtual void update() {}
|
||||
|
||||
protected:
|
||||
GLuint tex[3];
|
||||
QVector<GLfloat> pos;
|
||||
GLFramebuffer fbo;
|
||||
|
||||
};
|
||||
|
||||
#endif // ROPE_SYSTEM_H
|
||||
230
qglview/shaders/FXAA.frag
Normal file
@@ -0,0 +1,230 @@
|
||||
#version 130
|
||||
|
||||
in vec4 posPos;
|
||||
|
||||
uniform sampler2D tex0; // 0
|
||||
//uniform float vx_offset;
|
||||
uniform vec2 dt;
|
||||
uniform float FXAA_SPAN_MAX = 8.;
|
||||
uniform float FXAA_REDUCE_MUL = 1. / 8.;
|
||||
|
||||
#define FxaaInt2 ivec2
|
||||
//#define vec2 vec2
|
||||
|
||||
vec3 FxaaPixelShader(vec4 posPos, // Output of FxaaVertexShader interpolated across screen.
|
||||
sampler2D tex, // Input texture.
|
||||
vec2 rcpFrame) { // Constant {1.0/frameWidth, 1.0/frameHeight}.
|
||||
/*---------------------------------------------------------*/
|
||||
// #define FXAA_REDUCE_MIN (1. / 128.)
|
||||
#define FXAA_REDUCE_MIN (1. / 128.)
|
||||
//#define FXAA_REDUCE_MUL (1.0/8.0)
|
||||
//#define FXAA_SPAN_MAX 8.0
|
||||
/*---------------------------------------------------------*/
|
||||
vec3 rgbNW = texture2D(tex, posPos.zw).xyz;
|
||||
vec3 rgbNE = textureOffset(tex, posPos.zw, ivec2(1, 0)).xyz;
|
||||
vec3 rgbSW = textureOffset(tex, posPos.zw, ivec2(0, 1)).xyz;
|
||||
vec3 rgbSE = textureOffset(tex, posPos.zw, ivec2(1, 1)).xyz;
|
||||
vec3 rgbM = texture2D(tex, posPos.xy).xyz;
|
||||
/*---------------------------------------------------------*/
|
||||
vec3 luma = vec3(0.299, 0.587, 0.114);
|
||||
float lumaNW = dot(rgbNW, luma);
|
||||
float lumaNE = dot(rgbNE, luma);
|
||||
float lumaSW = dot(rgbSW, luma);
|
||||
float lumaSE = dot(rgbSE, luma);
|
||||
float lumaM = dot(rgbM, luma);
|
||||
/*---------------------------------------------------------*/
|
||||
float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
|
||||
float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
|
||||
/*---------------------------------------------------------*/
|
||||
vec2 dir;
|
||||
dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
|
||||
dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
|
||||
/*---------------------------------------------------------*/
|
||||
float dirReduce = max(
|
||||
(lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL),
|
||||
FXAA_REDUCE_MIN);
|
||||
float rcpDirMin = 1. / (min(abs(dir.x), abs(dir.y)) + dirReduce);
|
||||
dir = min(vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),
|
||||
max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
|
||||
dir * rcpDirMin)) * rcpFrame.xy;
|
||||
/*--------------------------------------------------------*/
|
||||
vec3 rgbA = (1. / 2.) * (
|
||||
texture2D(tex, posPos.xy + dir * (1. / 3. - 0.5)).xyz +
|
||||
texture2D(tex, posPos.xy + dir * (2. / 3. - 0.5)).xyz);
|
||||
vec3 rgbB = rgbA * (1. / 2.) + (1. / 4.) * (
|
||||
texture2D(tex, posPos.xy + dir * (0. / 3. - 0.5)).xyz +
|
||||
texture2D(tex, posPos.xy + dir * (3. / 3. - 0.5)).xyz);
|
||||
float lumaB = dot(rgbB, luma);
|
||||
if ((lumaB < lumaMin) || (lumaB > lumaMax)) return rgbA;
|
||||
return rgbB;
|
||||
}
|
||||
|
||||
|
||||
vec3 Fxaa3PixelShader (
|
||||
// {xy} = center of pixel
|
||||
vec4 pos,
|
||||
// {xyzw} = not used on FXAA3 Quality
|
||||
//vec4 posPos,
|
||||
// {rgb_} = color in linear or perceptual color space
|
||||
// {__a} = luma in perceptual color space (not linear)
|
||||
sampler2D tex,
|
||||
// This must be from a constant/uniform.
|
||||
// {x_} = 1.0/screenWidthInPixels
|
||||
// {_y} = 1.0/screenHeightInPixels
|
||||
vec2 rcpFrame
|
||||
// {xyzw} = not used on FXAA3 Quality
|
||||
//vec4 rcpFrameOpt
|
||||
) {
|
||||
/*--------------------------------------------------------------------------*/
|
||||
//#if (FXAA_GATHER4_ALPHA == 1)
|
||||
/*vec4 luma4A = FxaaTexOffAlpha4(tex, pos.xy, FxaaInt2(-1, -1), rcpFrame.xy);
|
||||
#if (FXAA_DISCARD == 0)
|
||||
vec4 rgbyM = texture2D(tex, pos.xy);
|
||||
#endif
|
||||
vec4 luma4B = FxaaTexAlpha4(tex, pos.xy, rcpFrame.xy);
|
||||
float lumaNE = textureOffset(tex, pos.xy, ivec(1, -1)).w;
|
||||
float lumaSW = textureOffset(tex, pos.xy, ivec(-1, 1)).w;
|
||||
float lumaNW = luma4A.w;
|
||||
float lumaN = luma4A.z;
|
||||
float lumaW = luma4A.x;
|
||||
float lumaM = luma4A.y;
|
||||
float lumaE = luma4B.z;
|
||||
float lumaS = luma4B.x;
|
||||
float lumaSE = luma4B.y;*/
|
||||
//#else
|
||||
vec3 luma = vec3(0.299, 0.587, 0.114);
|
||||
float lumaN = dot(textureLodOffset(tex, pos.xy, 0., ivec2(0, -1)).rgb, luma);
|
||||
float lumaW = dot(textureLodOffset(tex, pos.xy, 0., ivec2(-1, 0)).rgb, luma);
|
||||
vec4 rgbyM = texture2D(tex, pos.xy);
|
||||
float lumaE = dot(textureLodOffset(tex, pos.xy, 0., ivec2( 1, 0)).rgb, luma);
|
||||
float lumaS = dot(textureLodOffset(tex, pos.xy, 0., ivec2( 0, 1)).rgb, luma);
|
||||
float lumaM = dot(rgbyM.rgb, luma);
|
||||
//#endif
|
||||
/*--------------------------------------------------------------------------*/
|
||||
float rangeMin = min(lumaM, min(min(lumaN, lumaW), min(lumaS, lumaE)));
|
||||
float rangeMax = max(lumaM, max(max(lumaN, lumaW), max(lumaS, lumaE)));
|
||||
float range = rangeMax - rangeMin;
|
||||
//return vec4(range);
|
||||
/*--------------------------------------------------------------------------*/
|
||||
#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/12.0)
|
||||
#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/6.0)
|
||||
if(range < max(FXAA_QUALITY_EDGE_THRESHOLD_MIN, rangeMax * FXAA_QUALITY_EDGE_THRESHOLD))
|
||||
/*#if (FXAA_DISCARD == 1)
|
||||
FxaaDiscard;
|
||||
#else*/
|
||||
return rgbyM.rgb;
|
||||
//return vec3(0);
|
||||
//#endif
|
||||
/*--------------------------------------------------------------------------*/
|
||||
//#if (FXAA_GATHER4_ALPHA == 0)
|
||||
float lumaNW = dot(textureLodOffset(tex, pos.xy, 0., ivec2(-1,-1)).rgb, luma);
|
||||
float lumaNE = dot(textureLodOffset(tex, pos.xy, 0., ivec2( 1,-1)).rgb, luma);
|
||||
float lumaSW = dot(textureLodOffset(tex, pos.xy, 0., ivec2(-1, 1)).rgb, luma);
|
||||
float lumaSE = dot(textureLodOffset(tex, pos.xy, 0., ivec2( 1, 1)).rgb, luma);
|
||||
//#endif
|
||||
/*--------------------------------------------------------------------------*/
|
||||
#define FXAA_QUALITY_SUBPIX_CAP (3.0/4.0)
|
||||
//#define FXAA_QUALITY_SUBPIX_CAP 0
|
||||
#define FXAA_QUALITY_SUBPIX_TRIM (1.0/4.0)
|
||||
#define FXAA_QUALITY_SUBPIX_TRIM_SCALE (1.0/(1.0 - FXAA_QUALITY_SUBPIX_TRIM))
|
||||
/*--------------------------------------------------------------------------*/
|
||||
float lumaL = (lumaN + lumaW + lumaE + lumaS) * 0.25;
|
||||
float rangeL = abs(lumaL - lumaM);
|
||||
float blendL = clamp((rangeL / range) - FXAA_QUALITY_SUBPIX_TRIM, 0., 1.) * FXAA_QUALITY_SUBPIX_TRIM_SCALE;
|
||||
blendL = min(FXAA_QUALITY_SUBPIX_CAP, blendL);
|
||||
/*--------------------------------------------------------------------------*/
|
||||
float edgeVert =
|
||||
abs(lumaNW + (-2.0 * lumaN) + lumaNE) +
|
||||
10.0 * abs(lumaW + (-2.0 * lumaM) + lumaE ) +
|
||||
abs(lumaSW + (-2.0 * lumaS) + lumaSE);
|
||||
float edgeHorz =
|
||||
abs(lumaNW + (-2.0 * lumaW) + lumaSW) +
|
||||
10.0 * abs(lumaN + (-2.0 * lumaM) + lumaS ) +
|
||||
abs(lumaNE + (-2.0 * lumaE) + lumaSE);
|
||||
//return vec3(edgeHorz);
|
||||
//float edgeVert = abs(lumaS - lumaN);
|
||||
//float edgeHorz = abs(lumaE - lumaW);
|
||||
bool horzSpan = edgeHorz >= edgeVert;
|
||||
/*--------------------------------------------------------------------------*/
|
||||
float lengthSign = horzSpan ? -rcpFrame.y : -rcpFrame.x;
|
||||
//if (edgeHorz == edgeVert) ;//lengthSign = 0.;
|
||||
if(!horzSpan) {
|
||||
lumaN = lumaW;
|
||||
lumaS = lumaE;
|
||||
}
|
||||
float gradientN = abs(lumaN - lumaM);
|
||||
float gradientS = abs(lumaS - lumaM);
|
||||
lumaN = (lumaN + lumaM) * 0.5;
|
||||
lumaS = (lumaS + lumaM) * 0.5;
|
||||
/*--------------------------------------------------------------------------*/
|
||||
bool pairN = gradientN >= gradientS;
|
||||
if(!pairN) {
|
||||
lumaN = lumaS;
|
||||
gradientN = gradientS;
|
||||
lengthSign = -lengthSign;
|
||||
}
|
||||
vec2 posN;
|
||||
posN = pos.xy + (horzSpan ? vec2(0.0, lengthSign * 0.5) : vec2(lengthSign * 0.5, 0.0));
|
||||
//posN.x = pos.x + (horzSpan ? 0.0 : lengthSign * 0.5);
|
||||
//posN.y = pos.y + (horzSpan ? lengthSign * 0.5 : 0.0);
|
||||
/*--------------------------------------------------------------------------*/
|
||||
#define FXAA_SEARCH_STEPS 8
|
||||
#define FXAA_SEARCH_THRESHOLD (1.0/8.0)
|
||||
/*--------------------------------------------------------------------------*/
|
||||
gradientN *= FXAA_SEARCH_THRESHOLD;
|
||||
/*--------------------------------------------------------------------------*/
|
||||
vec2 posP = posN;
|
||||
vec2 offNP = horzSpan ? vec2(rcpFrame.x, 0.0) : vec2(0.0, rcpFrame.y);
|
||||
float lumaEndN = 0.;
|
||||
float lumaEndP = 0.;
|
||||
bool doneN = false;
|
||||
bool doneP = false;
|
||||
posN += offNP * (-1.5);
|
||||
posP += offNP * ( 1.5);
|
||||
for(int i = 0; i < FXAA_SEARCH_STEPS; i++) {
|
||||
lumaEndN = dot(texture2DLod(tex, posN.xy, 0.).rgb, luma);
|
||||
lumaEndP = dot(texture2DLod(tex, posP.xy, 0.).rgb, luma);
|
||||
bool doneN2 = abs(lumaEndN - lumaN) >= gradientN;
|
||||
bool doneP2 = abs(lumaEndP - lumaN) >= gradientN;
|
||||
if(doneN2 && !doneN) posN += offNP;
|
||||
if(doneP2 && !doneP) posP -= offNP;
|
||||
if(doneN2 && doneP2) break;
|
||||
doneN = doneN2;
|
||||
doneP = doneP2;
|
||||
if(!doneN) posN -= offNP * 2.0;
|
||||
if(!doneP) posP += offNP * 2.0;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
float dstN = horzSpan ? pos.x - posN.x : pos.y - posN.y;
|
||||
float dstP = horzSpan ? posP.x - pos.x : posP.y - pos.y;
|
||||
/*--------------------------------------------------------------------------*/
|
||||
bool directionN = dstN < dstP;
|
||||
lumaEndN = directionN ? lumaEndN : lumaEndP;
|
||||
/*--------------------------------------------------------------------------*/
|
||||
if(((lumaM - lumaN) < 0.0) == ((lumaEndN - lumaN) < 0.0))
|
||||
lengthSign = 0.0;
|
||||
/*--------------------------------------------------------------------------*/
|
||||
float spanLength = (dstP + dstN);
|
||||
dstN = directionN ? dstN : dstP;
|
||||
float subPixelOffset = 0.5 + (dstN * (-1.0/spanLength));
|
||||
subPixelOffset += blendL * (1.0/8.0);
|
||||
subPixelOffset *= lengthSign;
|
||||
vec3 rgbF = texture2DLod(tex, pos.xy + (horzSpan ? vec2(0., subPixelOffset) : vec2(subPixelOffset, 0.)), 0.).xyz;
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/*#if (FXAA_LINEAR == 1)
|
||||
lumaL *= lumaL;
|
||||
#endif*/
|
||||
float lumaF = dot(rgbF, vec3(0.299, 0.587, 0.114)) + (1.0/(65536.0*256.0));
|
||||
float lumaB = mix(lumaF, lumaL, blendL);
|
||||
float scale = min(4.0, lumaB/lumaF);
|
||||
rgbF *= scale;
|
||||
return vec3(rgbF);//, lumaM.rgb);
|
||||
//, lumaM.rgb);
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
gl_FragColor.rgb = Fxaa3PixelShader(posPos, tex0, dt);
|
||||
}
|
||||
|
||||
|
||||
13
qglview/shaders/FXAA.vert
Normal file
@@ -0,0 +1,13 @@
|
||||
#version 130
|
||||
|
||||
out vec4 posPos;
|
||||
|
||||
uniform float FXAA_SUBPIX_SHIFT = 1. / 4.;
|
||||
uniform vec2 dt;
|
||||
|
||||
void main(void) {
|
||||
posPos.xy = gl_MultiTexCoord0.xy;
|
||||
posPos.zw = gl_MultiTexCoord0.xy - (dt * (0.5 + FXAA_SUBPIX_SHIFT));
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_Position = ftransform();
|
||||
}
|
||||
8
qglview/shaders/bloom_0.frag
Normal file
@@ -0,0 +1,8 @@
|
||||
#version 120
|
||||
|
||||
uniform sampler2D t0;
|
||||
uniform float clum;
|
||||
|
||||
void main(void) {
|
||||
gl_FragColor = max((texture2D(t0, gl_TexCoord[0].xy) / clum - 0.8) * 5., vec4(0.));
|
||||
}
|
||||
30
qglview/shaders/bloom_1.frag
Normal file
@@ -0,0 +1,30 @@
|
||||
#version 130
|
||||
|
||||
uniform sampler2D t0;
|
||||
uniform vec2 vsize;
|
||||
|
||||
void main(void) {
|
||||
vec2 tc = gl_TexCoord[0].xy, dt = 2. / vsize, dt2 = dt + dt;
|
||||
gl_FragColor = (texture2D(t0, tc) * 3. +
|
||||
textureOffset(t0, tc, ivec2(1, 0)) * 2. +
|
||||
textureOffset(t0, tc, ivec2(0, 1)) * 2. +
|
||||
textureOffset(t0, tc, ivec2(-1, 0)) * 2. +
|
||||
textureOffset(t0, tc, ivec2(0, -1)) * 2. +
|
||||
textureOffset(t0, tc, ivec2(1, 1)) * 1.5 +
|
||||
textureOffset(t0, tc, ivec2(1, -1)) * 1.5 +
|
||||
textureOffset(t0, tc, ivec2(-1, -1)) * 1.5 +
|
||||
textureOffset(t0, tc, ivec2(-1, 1)) * 1.5 +
|
||||
textureOffset(t0, tc, ivec2(2, 0)) +
|
||||
textureOffset(t0, tc, ivec2(0, 2)) +
|
||||
textureOffset(t0, tc, ivec2(-2, 0)) +
|
||||
textureOffset(t0, tc, ivec2(0, -2)) +
|
||||
textureOffset(t0, tc, ivec2(2, 1)) +
|
||||
textureOffset(t0, tc, ivec2(2, -1)) +
|
||||
textureOffset(t0, tc, ivec2(-2, -1)) +
|
||||
textureOffset(t0, tc, ivec2(-2, 1)) +
|
||||
textureOffset(t0, tc, ivec2(1, 2)) +
|
||||
textureOffset(t0, tc, ivec2(1, -2)) +
|
||||
textureOffset(t0, tc, ivec2(-1, -2)) +
|
||||
textureOffset(t0, tc, ivec2(-1, 2))) / 29.;
|
||||
//gl_FragColor = texture2D(t0, tc);
|
||||
}
|
||||
52
qglview/shaders/dsl_pass_0.frag
Normal file
@@ -0,0 +1,52 @@
|
||||
#version 130
|
||||
|
||||
in vec3 src_normal, normal, et;
|
||||
in vec4 pos, col;
|
||||
in float fogCoord;
|
||||
|
||||
uniform int light_model;
|
||||
uniform sampler2D t0, t1, t2, t3;
|
||||
uniform float bump_scale, height_scale;
|
||||
uniform bool acc_fog, has_diffuse, has_bump, has_height;
|
||||
uniform vec2 dt;
|
||||
|
||||
const vec3 luma = vec3(0.299, 0.587, 0.114);
|
||||
|
||||
void main(void) {
|
||||
vec4 dc = col;
|
||||
vec2 tc = gl_TexCoord[0].xy;
|
||||
float hei = 0.;
|
||||
if (has_height) hei = dot(texture2D(t2, gl_TexCoord[0].xy).rgb, luma) * height_scale;
|
||||
if (acc_fog) dc.xyz = mix(dc.rgb, gl_Fog.color.rgb, fogCoord);
|
||||
|
||||
vec3 n;
|
||||
if (has_bump) n = normalize(normal - (texture2D(t1, gl_TexCoord[0].xy).rgb - vec3(0.5, 0.5, 1.)) * bump_scale);
|
||||
else n = normalize(normal);
|
||||
|
||||
if (has_diffuse) {
|
||||
|
||||
/*vec2 dpm = normalize(gl_FragCoord.xy * dt * 2. - vec2(1., 1.)), ntc;
|
||||
ntc = gl_FragCoord.xy * dt * 2. - vec2(1., 1.) + dpm * hei;
|
||||
dpm = gl_ModelViewProjectionMatrixInverse
|
||||
dpm = dpm * gl_ModelViewProjectionMatrixInverse;
|
||||
dpm += */
|
||||
tc += 1-et.xy * hei/10;// / et.z;
|
||||
dc *= texture2D(t0, tc);
|
||||
}
|
||||
|
||||
gl_FragData[0] = vec4(dc.rgb, pos.w);
|
||||
gl_FragData[1] = vec4(n.xyz / 2. + vec3(0.5), gl_FrontMaterial.shininess);
|
||||
gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, hei);
|
||||
//gl_FragData[0] = vec4(et.xyz, pos.w);
|
||||
//gl_FragDepth = gl_FragCoord.z - clamp(hei / pos.z / pos.z / (abs(n.z) + 1), -0.01, 0.01);
|
||||
/*vec4 dp = pos;
|
||||
dp.x = floor(dp.w / 255.) / 255.;
|
||||
dp.w -= dp.x * 65025;
|
||||
dp.y = floor(dp.w) / 255.;
|
||||
dp.w -= dp.y * 255.;
|
||||
dp.z = fract(dp.w);*/
|
||||
//dp.x = dp.w;
|
||||
//dp.w = (gl_FrontMaterial.specular.r + gl_FrontMaterial.specular.g + gl_FrontMaterial.specular.b) / 3. / 25.5;
|
||||
//gl_FragData[2] = dp;
|
||||
//gl_FragData[3] = vec4(light_model / 255., 0, 0, 0);
|
||||
}
|
||||
14
qglview/shaders/dsl_pass_0.geom
Normal file
@@ -0,0 +1,14 @@
|
||||
#version 130
|
||||
|
||||
layout(triangles, invocations = 1) in;
|
||||
|
||||
in vec3 normal[];
|
||||
out vec3 tangent[];
|
||||
|
||||
void main() {
|
||||
for (int i = 0; i < gl_in.length(); i++ ) {
|
||||
gl_Position = gl_in[i].gl_Position;
|
||||
EmitVertex();
|
||||
}
|
||||
EndPrimitive();
|
||||
}
|
||||