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 }