Files
qad/qglview/globject.cpp

243 lines
6.2 KiB
C++

/*
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;
raw_matrix = false;
mat_.setToIdentity();
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->raw_matrix = raw_matrix;
o->mat_ = mat_;
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->norms = norms;
o->normals = normals;
o->vbo.vertices_ = vbo.vertices_;
o->vbo.normals_ = vbo.normals_;
o->vbo.texcoords_ = vbo.texcoords_;
o->vbo.colors_ = vbo.colors_;
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(QGLShaderProgram * prog, bool simplest) {
vbo.draw(geom_prim, prog, 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::setTransform(const QMatrix4x4 & t) {
raw_matrix = true;
mat_ = t;
pos_ = mat_.column(3).toVector3D();
mat_.setColumn(3, QVector4D(0., 0., 0., 1.));
buildTransform();
}
void GLObjectBase::buildTransform() {
itransform_.setToIdentity();
GLObjectBase * p = parent_;
if (p != 0)
itransform_ = p->itransform_;
if (raw_matrix) {
itransform_.translate(pos_);
itransform_ *= mat_;
//qDebug() << "raw_matrix" << itransform_;
} else
localTransform(itransform_);
//qDebug() << name_ << itransform_;
foreach (GLObjectBase * i, children_)
i->buildTransform();
}
void GLObjectBase::localTransform(QMatrix4x4 & m) {
m.translate(pos_);
m.rotate(angles_.z(), 0., 0., 1.);
m.rotate(angles_.y(), 0., 1., 0.);
m.rotate(angles_.x(), 1., 0., 0.);
m.scale(scale_);
}
void GLObjectBase::checkPass() {
if (material_.reflectivity > 0.f || material_.color_diffuse.alphaF() * (1.f - material_.transparency) < 1.f) pass_ = Transparent;
else pass_ = Solid;
}
QMatrix4x4 GLObjectBase::worldMatrix(QMatrix4x4 parent) const {
QMatrix4x4 mat;
mat.translate(pos_);
if (raw_matrix) {
mat *= mat_;
} else {
if (angles_.z() != 0.) mat.rotate(angles_.z(), 0., 0., 1.);
if (angles_.y() != 0.) mat.rotate(angles_.y(), 0., 1., 0.);
if (angles_.x() != 0.) mat.rotate(angles_.x(), 1., 0., 0.);
mat.scale(scale_);
}
return parent * mat;
}
void GLObjectBase::render(int * id, QMap<int, GLObjectBase * > * ids, int sh_id_loc) {
if (!visible_) return;
//glPushMatrix();
///qglMultMatrix TODO
material_.apply(0);
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(0);
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(QGLShaderProgram * prog, 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);
}