/* 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 . */ #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::children(bool all_) { if (!all_) return children_; QList cl; addChildren(cl, this); return cl; } void GLObjectBase::addChildren(QList & 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 { 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_); } //qDebug() << name_ << itransform_; 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; } 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 * 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); }