git-svn-id: svn://db.shs.com.ru/libs@1 a8b55f48-bf90-11e4-a774-851b48703e85
This commit is contained in:
2015-02-28 21:28:53 +00:00
commit ba8bc27298
2358 changed files with 336795 additions and 0 deletions

View 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

View 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
View 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

File diff suppressed because it is too large Load Diff

17648
qglview/GLee.h Normal file

File diff suppressed because it is too large Load Diff

4
qglview/clean Normal file
View 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
View 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

Binary file not shown.

BIN
qglview/data/NMBalls.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

BIN
qglview/data/NMBumpsOut.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
qglview/data/NMStripes.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

BIN
qglview/data/celtic_010.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 KiB

BIN
qglview/data/e/back.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
qglview/data/e/bottom.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
qglview/data/e/front.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
qglview/data/e/left.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
qglview/data/e/right.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
qglview/data/e/top.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
qglview/data/expl_07.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

BIN
qglview/data/hel.3DS Normal file

Binary file not shown.

BIN
qglview/data/l.3DS Normal file

Binary file not shown.

BIN
qglview/data/l_.3DS Normal file

Binary file not shown.

19878
qglview/data/l_.ASE Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
qglview/data/s.3DS Normal file

Binary file not shown.

BIN
qglview/data/test.3DS Normal file

Binary file not shown.

42823
qglview/data/test.DAE Normal file

File diff suppressed because one or more lines are too long

BIN
qglview/data/test_.3DS Normal file

Binary file not shown.

BIN
qglview/data/waveNM.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

127
qglview/glframebuffer.cpp Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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>

View 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);
}

View 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
View 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
View 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

View 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();
}

View 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
View 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
View 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
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

BIN
qglview/icons/configure.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 813 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 644 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 802 B

BIN
qglview/icons/edit-copy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

BIN
qglview/icons/edit-find.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 B

BIN
qglview/icons/item-add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 639 B

BIN
qglview/icons/item.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 B

BIN
qglview/icons/list-add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

BIN
qglview/icons/node-add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

BIN
qglview/icons/node.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 658 B

BIN
qglview/icons/view-grid.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 B

276
qglview/loader_3ds.cpp Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@@ -0,0 +1 @@
cmake_mgw -DLIB= && make install && qmake && make install

192
qglview/material_editor.cpp Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@@ -0,0 +1,3 @@
[Project]
Manager=KDevCMakeManager
Name=qglview

BIN
qglview/qglview_test.exe Normal file

Binary file not shown.

View 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);
}

View 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

View 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
View 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
View 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
View 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
View 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
View 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();
}

View 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.));
}

View 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);
}

View 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);
}

View 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();
}

Some files were not shown because too many files have changed in this diff Show More