File indexing completed on 2024-04-14 03:39:20

0001 /*************************************************************************************
0002  *  Copyright (C) 2012 by Percy Camilo T. Aucahuasi <percy.camilo.ta@gmail.com>      *
0003  *                                                                                   *
0004  *  This program is free software; you can redistribute it and/or                    *
0005  *  modify it under the terms of the GNU General Public License                      *
0006  *  as published by the Free Software Foundation; either version 2                   *
0007  *  of the License, or (at your option) any later version.                           *
0008  *                                                                                   *
0009  *  This program is distributed in the hope that it will be useful,                  *
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                    *
0012  *  GNU General Public License for more details.                                     *
0013  *                                                                                   *
0014  *  You should have received a copy of the GNU General Public License                *
0015  *  along with this program; if not, write to the Free Software                      *
0016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
0017  *************************************************************************************/
0018 
0019 
0020 #include "abstractsurface.h"
0021 
0022 #include <QVector3D>
0023 
0024 static const int MAXAROUND = 32;
0025 static const int MAXSTRIP = 32;
0026 static const int MAXALONG = 32;
0027 
0028 using namespace Analitza;
0029 
0030 AbstractSurface::AbstractSurface(const Analitza::Expression& e, const QSharedPointer<Analitza::Variables>& v)
0031 : AbstractFunctionGraph(e, v)
0032 {}
0033 
0034 AbstractSurface::~AbstractSurface()
0035 {}
0036 
0037 bool AbstractSurface::buildParametricSurface()
0038 {
0039     double tmpsize = 4.0;
0040     qreal umin = -tmpsize;
0041     qreal umax = tmpsize;
0042     qreal vmin = -tmpsize;
0043     qreal vmax = tmpsize;    
0044     
0045     if (hasIntervals())
0046     {
0047         QStringList bvars = parameters();
0048 
0049         //TODO remove the assert en el caso de implicitas se deberia tratar siempre de crear la superficies parametrica primero
0050         Q_ASSERT(bvars.size() == 2); // solo para superficies que puedan ser parametrizadas
0051         
0052         QPair<double, double> intervalx = interval(bvars.at(0));
0053         QPair<double, double> intervaly = interval(bvars.at(1));
0054 
0055         umin = intervalx.first;
0056         umax = intervalx.second;
0057         vmin = intervaly.first;
0058         vmax = intervaly.second;
0059     }
0060     
0061     int usteps = MAXALONG;
0062     int vsteps = MAXAROUND;
0063     
0064     vertices.clear();
0065     normals.clear();
0066     indexes.clear();
0067 
0068     QVector3D surface[MAXALONG][MAXAROUND];
0069 
0070     for ( int i=0; i<usteps; i++ )
0071         for ( int j=0; j<vsteps; j++ )
0072         {
0073             float u = (umin+((umax-umin)/(float)(usteps-1))*(float)(i));
0074             float v = (vmin+((vmax-vmin)/(float)(vsteps-1))*(float)(j));
0075 
0076             surface[i][j] = fromParametricArgs(u,v);
0077         }
0078 
0079     for (int i = 0; i < usteps -1; i++ )
0080         for ( int j=0; j<vsteps-1; j++ )
0081             doQuad(1, 1, surface[i][j], surface[i+1][j], surface[i][j+1], surface[i+1][j+1]);
0082         
0083     return !indexes.isEmpty();
0084 }
0085 
0086 void AbstractSurface::doQuad(int n, int m, const QVector3D &p0,  const QVector3D &p1,  const QVector3D &p2,  const QVector3D &p3)
0087 {
0088     for (int i=0; i<m; i++)
0089     {
0090         const QVector3D A((p0.x()*(float)(m-i) + p1.x()*(float)i)/(float)m,
0091                           (p0.y()*(float)(m-i) + p1.y()*(float)i)/(float)m,
0092                           (p0.z()*(float)(m-i) + p1.z()*(float)i)/(float)m);
0093         
0094         const QVector3D B((p0.x()*(float)(m-i-1) + p1.x()*(float)(i+1))/(float)m,
0095                           (p0.y()*(float)(m-i-1) + p1.y()*(float)(i+1))/(float)m,
0096                           (p0.z()*(float)(m-i-1) + p1.z()*(float)(i+1))/(float)m);
0097 
0098         const QVector3D C((p2.x()*(float)(m-i)   + p3.x()*(float)i)/(float)m,
0099                           (p2.y()*(float)(m-i)   + p3.y()*(float)i)/(float)m,
0100                           (p2.z()*(float)(m-i)   + p3.z()*(float)i)/(float)m);
0101 
0102         const QVector3D D((p2.x()*(float)(m-i-1) + p3.x()*(float)(i+1))/(float)m,
0103                           (p2.y()*(float)(m-i-1) + p3.y()*(float)(i+1))/(float)m,
0104                           (p2.z()*(float)(m-i-1) + p3.z()*(float)(i+1))/(float)m);
0105         
0106         doStrip(n, A, B, C, D);
0107     }
0108 }
0109 
0110 void AbstractSurface::doStrip(int n, const QVector3D &p0,  const QVector3D &p1,  const QVector3D &p2,  const QVector3D &p3)
0111 {
0112     QVector3D buffer[3];
0113     QVector3D theStrip[MAXSTRIP][2];
0114 
0115     for (int i=0; i<=n; i++)
0116     {
0117         const QVector3D A((p0.x()*(float)(n-i) + p2.x()*(float)i)/(float)n,
0118                           (p0.y()*(float)(n-i) + p2.y()*(float)i)/(float)n,
0119                           (p0.z()*(float)(n-i) + p2.z()*(float)i)/(float)n);
0120 
0121         const QVector3D B((p1.x()*(float)(n-i) + p3.x()*(float)i)/(float)n,
0122                           (p1.y()*(float)(n-i) + p3.y()*(float)i)/(float)n,
0123                           (p1.z()*(float)(n-i) + p3.z()*(float)i)/(float)n);
0124 
0125         theStrip[i][0] = A;
0126         theStrip[i][1] = B;
0127     }
0128     
0129     buffer[0] = theStrip[0][0];
0130     buffer[1] = theStrip[0][1];
0131     for (int i=1; i<=n; i++)
0132         for (int j=0; j<2; j++)
0133         {
0134             buffer[2] = theStrip[i][j];
0135             createFace(buffer);
0136             buffer[0] = buffer[1];
0137             buffer[1] = buffer[2];
0138         }
0139 }
0140 
0141 void AbstractSurface::createFace(QVector3D *buffer)
0142 {
0143     QVector3D n = QVector3D::normal(buffer[0], buffer[1], buffer[2]);
0144 
0145     vertices << buffer[0] << buffer[1] << buffer[2];
0146 
0147     normals << n;
0148 
0149     indexes.append(indexes.size());
0150     indexes.append(indexes.size());
0151     indexes.append(indexes.size());
0152 }
0153 
0154 QVector3D AbstractSurface::fromParametricArgs(double, double)
0155 {
0156     return QVector3D();
0157 }