/* 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; 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::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::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 * 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); }