krita/ui

kis_3d_object_model.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002  * Copyright (C) Lukáš Tvrdý, lukast.dev@gmail.com (c) 2009
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public License
00015  * along with this library; see the file COPYING.LIB.  If not, write to
00016  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018  */
00019 
00020 #include <QFile>
00021 #include <QTextStream>
00022 #include <QString>
00023 #include <QStringList>
00024 #include <QHash>
00025 
00026 #include "kis_3d_object_model.h"
00027 #include "kis_vec.h"
00028 #include "kis_debug.h"
00029 
00030 #include <kglobal.h>
00031 #include <kstandarddirs.h>
00032 #include <kcomponentdata.h>
00033 
00034 Kis3DObjectModel::Kis3DObjectModel(const QString& model, const QString& material)
00035 {
00036     KGlobal::mainComponent().dirs()->addResourceType("kis_brushmodels", "data", "krita/brushmodels/");
00037     QString path = KGlobal::mainComponent().dirs()->findResource("kis_brushmodels", model);
00038 
00039     m_cached = false;
00040 
00041     parseMaterial(material);
00042 
00043     QFile file(path);
00044     if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
00045         kDebug() << "File " + model + " Not Found";
00046         return;
00047     }
00048 
00049     QTextStream in(&file);
00050     QString key;
00051     QString edge;
00052     QStringList edgeList;
00053 
00054     while (!in.atEnd()) {
00055 
00056         QString line = in.readLine();
00057         if (line.isEmpty() || line[0] == '#') {
00058             continue;
00059         }
00060 
00061         QTextStream ts(&line);
00062         QString id;
00063         ts >> id;
00064         if (id == "v") {
00065             KisVector3D vector;
00066             for (int i = 0; i < 3; i++) {
00067                 ts >> vector[i];
00068             }
00069             m_vertex.append(vector);
00070         } else if (id == "vn") {
00071             KisVector3D normal;
00072             for (int i = 0; i < 3; i++) {
00073                 ts >> normal[i];
00074 
00075             }
00076             m_normal.append(normal);
00077         } else if (id == "usemtl") {
00078             ts >> key;
00079         } else if (id == "f") {
00080             if (key.isEmpty() || key.isNull()) {
00081                 // TODO: will we support obj files without materials? I don't like that idea..
00082                 qFatal("No material defined in model file!");
00083             }
00084             // triangles are supported so far and format f vertexIndex//vertexNormalIndex
00085             for (int i = 0; i < 3; i++) {
00086                 ts >> edge;
00087                 edgeList = edge.split('/');
00088                 //m_vertexIndex.append( edgeList.value(0).toInt() - 1);
00089                 //m_normalIndex.append( edgeList.value(2).toInt() - 1);
00090                 m_vertexHash[ key ].append(edgeList.value(0).toInt() - 1);
00091                 m_normalHash[ key ].append(edgeList.value(2).toInt() - 1);
00092             }
00093         }
00094     } // while
00095 
00096 // DEBUG CODE
00097 #if 0
00098     kDebug() << "(v) vertex: " << m_vertex.size();
00099     kDebug() << "(vn) normals: " << m_normal.size();
00100     kDebug() << "(usemtl) keys (v): " << m_vertexHash.keys();
00101     kDebug() << "(usemtl) keys (vn): " << m_normalHash.keys();
00102 
00103     int vSize = 0;
00104     int nSize = 0;
00105     QList<QString> keyList = m_vertexHash.keys();
00106     for (int i = 0; i < keyList.size(); i++) {
00107         vSize += m_vertexHash[ keyList[i] ].size();
00108     }
00109     keyList = m_normalHash.keys();
00110     for (int i = 0; i < keyList.size(); i++) {
00111         nSize += m_normalHash[ keyList[i] ].size();
00112     }
00113     kDebug() << "(f) faces-vertex: " << vSize;
00114     kDebug() << "(f) faces-normal: " << nSize;
00115     kDebug() << "(f) faces-vertex/3.0: " << vSize / 3.0;
00116     kDebug() << "(f) faces-normal/3.0: " << nSize / 3.0;
00117 
00118 #endif
00119 }
00120 
00121 #define MODEL_SCALE 30
00122 GLuint Kis3DObjectModel::displayList()
00123 {
00124     if (m_cached) {
00125         return m_displayList;
00126     }
00127 
00128     // nothing to render
00129     if (m_vertex.size() == 0) {
00130         return 0;
00131     }
00132 
00133     KisVector3D vertex;
00134     KisVector3D normal;
00135     QList<QString> keyList = m_vertexHash.keys();
00136 
00137     m_displayList = glGenLists(1);
00138 
00139     glNewList(m_displayList, GL_COMPILE);
00140     glScalef(MODEL_SCALE, MODEL_SCALE, MODEL_SCALE);
00141     glBegin(GL_TRIANGLES);
00142     for (int k = 0; k < keyList.size(); k++) {
00143         m_vertexIndex = m_vertexHash.value(keyList[k]);
00144         m_normalIndex = m_normalHash.value(keyList[k]);
00145 
00146         Material m = m_material.value(keyList[k]);
00147         glColor3f(m.Kd[0], m.Kd[1], m.Kd[2]);
00148 #if 0
00149         kDebug() << "Name: " << keyList[k];
00150         debug(m);
00151 #endif
00152 
00153         for (int i = 0; i < m_vertexIndex.size(); i += 3) {
00154             for (int j = 0; j < 3; j++) {
00155                 int vi = m_vertexIndex[i+j];
00156                 int ni = m_normalIndex[i+j];
00157                 vertex = m_vertex[ vi ];
00158                 normal = m_normal[ ni ];
00159                 glNormal3f(normal.x(), normal.y(), normal.z());
00160                 glVertex3f(vertex.x(), vertex.y(), vertex.z());
00161             }
00162         }
00163 
00164 
00165     }
00166 
00167 
00168     glEnd();
00169     const GLfloat _1_MODEL_SCALE = GLfloat(1.0 / MODEL_SCALE);
00170     glScalef(_1_MODEL_SCALE, _1_MODEL_SCALE, _1_MODEL_SCALE);
00171     glEndList();
00172     /*        glEnableClientState(GL_VERTEX_ARRAY);
00173             glEnableClientState(GL_NORMAL_ARRAY);
00174 
00175             glVertexPointer(3, GL_FLOAT, 0, (float *)m_vertex.data());
00176             glNormalPointer(GL_FLOAT, 0, (float *)m_normal.data());
00177             glDrawElements(GL_TRIANGLES, m_vertexIndex.size(), GL_UNSIGNED_INT, m_vertexIndex.data());
00178 
00179             glDisableClientState(GL_NORMAL_ARRAY);
00180             glDisableClientState(GL_VERTEX_ARRAY);
00181     */
00182 
00183 
00184     // list is ready
00185     m_cached = true;
00186     return m_displayList;
00187 
00188 }
00189 
00190 
00191 void Kis3DObjectModel::parseMaterial(const QString& fileName)
00192 {
00193 
00194     QString path = KGlobal::mainComponent().dirs()->findResource("kis_brushmodels", fileName);
00195 
00196     QFile file(path);
00197     if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
00198         kDebug() << "File " + fileName + " Not Found";
00199         return;
00200     }
00201 
00202     QTextStream in(&file);
00203 
00204     QString key;
00205     while (!in.atEnd()) {
00206 
00207         QString line = in.readLine();
00208         if (line.isEmpty() || line[0] == '#') {
00209             continue;
00210         }
00211 
00212         QTextStream ts(&line);
00213         QString id;
00214         ts >> id;
00215         if (id == "Ka") {
00216             KisVector3D vector;
00217             for (int i = 0; i < 3; i++) {
00218                 ts >> vector[i];
00219             }
00220             m_material[ key ].Ka = vector;
00221 
00222         } else if (id == "Kd") {
00223 
00224             KisVector3D vector;
00225             for (int i = 0; i < 3; i++) {
00226                 ts >> vector[i];
00227             }
00228             m_material[ key ].Kd = vector;
00229 
00230         } else if (id == "Ks") {
00231             KisVector3D vector;
00232             for (int i = 0; i < 3; i++) {
00233                 ts >> vector[i];
00234             }
00235             m_material[ key ].Ks = vector;
00236         } else if (id == "d") {
00237             ts >> m_material[ key ].d;
00238         } else if (id == "Ns") {
00239             ts >> m_material[ key ].Ns;
00240         } else if (id == "Ni") {
00241             ts >> m_material[ key ].Ni;
00242         } else if (id == "newmtl") {
00243             ts >> key;
00244         }
00245 
00246     }
00247 
00248 #if 0
00249     QList<QString> list = m_material.keys();
00250     kDebug() << list;
00251     kDebug() << "----------------------------\n";
00252     for (int i = 0; i < list.size(); i++) {
00253         kDebug() << list[ i ];
00254         debug(m_material.value(list[ i ]));
00255     }
00256     kDebug() << "----------------------------\n";
00257 #endif
00258 
00259 }
00260 
00261 
00262 void Kis3DObjectModel::debug(Material m)
00263 {
00264     kDebug() << "Ka:" << m.Ka[0] << " " << m.Ka[1] << " " << m.Ka[2];
00265     kDebug() << "Kd:" << m.Kd[0] << " " << m.Kd[1] << " " << m.Kd[2];
00266     kDebug() << "Ks:" << m.Ks[0] << " " << m.Ks[1] << " " << m.Ks[2];
00267 }