00001 #include "lugre_prefix.h"
00002 #include <math.h>
00003
00004 #include "GhoulPrimitives.h"
00005 #include "Ogre.h"
00006
00007 using namespace GhoulPrimitive;
00008 using namespace Lugre;
00009
00010
00011 inline int max (const int a, const int b) { return (a>b)?a:b; }
00012
00013
00014
00015 Drawer::Drawer () {}
00016 Drawer::~Drawer () {}
00017 void Drawer::Prepare (eOpType opType,eGeometryChange gcHint,size_t vertexCount,size_t indexCount,bool hasNormals,bool hasTexCoords) {}
00018 void Drawer::AddVertex (kVector3 p,kVector3 n,kReal u,kReal v) { AddVertex(p.x,p.y,p.z,n.x,n.y,n.z,u,v); }
00019 void Drawer::AddVertex (kReal x,kReal y,kReal z,kReal nx,kReal ny,kReal nz,kReal u,kReal v) {}
00020 void Drawer::AddIndex (IndexInt i) {}
00021 void Drawer::Finish () {}
00022
00023 Primitive::Primitive () {}
00024 Primitive::~Primitive () {}
00025 void Primitive::Update (Drawer& drawer,bool bHasNormals,bool bHasTexCoords) {}
00026
00027
00037 void Primitive::Ellipse (Real* a,size_t blocks,size_t components,kReal radiusx,kReal radiusy,kReal startang,kReal endang,bool setOtherComponentsToZero) { PROFILE
00038 assert(blocks > 1 && "min one block");
00039 int i,j;
00040 if (components <= 0) return;
00041 Real ang,angstep=(endang-startang)/((Real)(blocks-1));
00042 for (i=0,ang=startang;i<blocks;++i,ang+=angstep) {
00043 if (i==blocks-1) ang = endang;
00044 a[i*components+0] = radiusx * sin(ang);
00045 if (components > 1) {
00046 a[i*components+1] = radiusy * cos(ang);
00047 if (setOtherComponentsToZero) for (j=2;j<components;++j) a[i*components+j] = 0.0;
00048 }
00049 }
00050 }
00051
00052 void Primitive::Circle (Real* a,size_t blocks,size_t components,kReal radius,kReal startang,kReal endang,bool setOtherComponentsToZero) { PROFILE
00053 Primitive::Ellipse(a,blocks,components,radius,radius,startang,endang,setOtherComponentsToZero);
00054 }
00055
00056
00068 void Primitive::InterpolatateFloatV (kReal* source,Real* dest,kReal t,size_t num,size_t startoff,size_t bufsize,eInterpolationMode mode,size_t stride) { PROFILE
00069
00070 ASSERT(startoff >= 0 && "negative startoff");
00071 ASSERT(stride >= 0 && "negative stride");
00072 ASSERT(source && "source buffer null");
00073 ASSERT(dest && "dest buffer null");
00074 ASSERT(bufsize >= (num+stride) + startoff && "source buffer too small");
00075 int i,j;
00076 switch (mode) {
00077 case kInterpolate_Constant:
00078 for (i=0;i<num;++i) {
00079 dest[i] = source[startoff+i];
00080 }
00081 break;
00082 case kInterpolate_SmoothQuadric:
00083 {
00084
00085
00086 Real t2 = t * t;
00087 Real t3 = t2 * t;
00088 Real t3m2 = t3 - t2;
00089 Real p1,p2,q1,q2,r1,r2;
00090
00091
00092
00093
00094
00095
00096
00097 for (i=0;i<num;++i) {
00098
00099 p1 = source[startoff+i];
00100 j = startoff+i + (num+stride);
00101 p2 = (j<bufsize)?source[j]:p1;
00102 j += (num+stride);
00103 q2 = (j<bufsize)?source[j]:p2;
00104 j = startoff+i - (num+stride);
00105 q1 = (j>=0)?source[j]:p1;
00106
00107 r1 = (p2 - q1) * 0.5;
00108 r2 = (q2 - p1) * 0.5;
00109 dest[i] = (t<0.0)?p1:((t>1.0)?p2:( p1*(t3m2+t3m2-t2+1.0) + r1*(t3m2-t2+t) + p2*(-t3m2-t3m2+t2) + r2*(t3m2) ));
00110 }
00111 }
00112 break;
00113 case kInterpolate_Linear:
00114 default :
00115 {
00116 Real p1,p2;
00117 for (i=0;i<num;++i) {
00118
00119 p1 = source[startoff+i];
00120 j = startoff+i + (num+stride);
00121 p2 = (j<bufsize)?source[j]:p1;
00122 dest[i] = (t<0.0)?p1:((t>1.0)?p2:(p1+(p2-p1)*t));
00123 }
00124 }
00125 }
00126 }
00127
00128 Real Primitive::InterpolatateFloat (kReal* source,kReal t,size_t startoff,size_t bufsize,eInterpolationMode mode,size_t stride) { PROFILE
00129 Real res;
00130 Primitive::InterpolatateFloatV(source,&res,t,1,startoff,bufsize,mode,stride);
00131 return res;
00132 }
00133
00134
00135 Real InterpolatateFloat_Linear (kReal p1,kReal p2,kReal t) { PROFILE
00136 Real source[] = { p1, p2 };
00137 return Primitive::InterpolatateFloat(source,t,0,2,kInterpolate_Linear,0);
00138 }
00139 Real InterpolatateFloat_Smooth (kReal q1,kReal p1,kReal p2,kReal q2,kReal t) { PROFILE
00140 Real source[] = { q1, p1, p2, q2 };
00141 return Primitive::InterpolatateFloat(source,t,1,4,kInterpolate_SmoothQuadric,0);
00142 }
00143
00144
00146 Ellipsoid::~Ellipsoid() {}
00147 Ellipsoid::Ellipsoid (kVector3 pos,kVector3 rad,size_t rings,size_t segments) : Loft() { PROFILE
00148 SetParams(pos,rad,rings,segments);
00149 }
00150 Ellipsoid& Ellipsoid::SetParams (kVector3 pos,kVector3 rad,size_t rings,size_t segments) { PROFILE
00151 size_t i;
00152 Real t;
00153 Real *circle;
00154 circle = new Real[segments*2];
00155 Primitive::Ellipse(circle,segments,2,rad.x,rad.y);
00156 for (i=0;i<segments;++i)
00157 AddBasePoint(Vector3(circle[i*2+0],circle[i*2+1],0.0),Vector3::ZERO,(Real)i/(Real)(max(2,segments)-1));
00158
00159 for (i=0;i<rings;++i) {
00160 t = (Real)i/(Real)(max(2,rings)-1);
00161 AddPathPoint(Vector3(pos.x,pos.y,pos.z-rad.z*cos(t*pi)),t,0,Vector3::UNIT_SCALE*sin(t*pi));
00162 }
00163 mSphericalAutoNormals = true;
00164 mSphericalAutoNormals_Center = pos;
00165 delete(circle);
00166 return *this;
00167 }
00168
00169 OgreEllipsoid::~OgreEllipsoid() {}
00170 OgreEllipsoid::OgreEllipsoid (kVector3 pos,kVector3 rad,size_t rings,size_t segments)
00171 : Ellipsoid(pos,rad,rings,segments), OgreRenderableDrawer() { PROFILE
00172 Update(*this);
00173 }
00174
00175
00176
00178 Cone::~Cone() {}
00179 Cone::Cone (kVector3 pos1,kVector3 pos2,kReal rad1X,kReal rad1Y,kReal endscale,size_t segments,size_t height_segments) : Loft() { PROFILE
00180 SetParams(pos1,pos2,rad1X,rad1Y,endscale,segments,height_segments);
00181 }
00182 Cone& Cone::SetParams (kVector3 pos1,kVector3 pos2,kReal rad1X,kReal rad1Y,kReal endscale,size_t segments,size_t height_segments) { PROFILE
00183 size_t i;
00184 Vector3 v = pos2 - pos1;
00185 Vector3 vn = v.normalisedCopy();
00186 Vector3 x,y;
00187 if (fabs(vn.x) > fabs(vn.y))
00188 x = vn.crossProduct(Vector3::UNIT_Y);
00189 else x = vn.crossProduct(Vector3::UNIT_X);
00190 y = vn.crossProduct(x);
00191
00192 Real t;
00193 Real *circle;
00194 circle = new Real[segments*2];
00195 Primitive::Ellipse(circle,segments,2,rad1X,rad1Y);
00196 for (i=0;i<segments;++i) {
00197 AddBasePoint(x*circle[i*2+0] + y*circle[i*2+1],Vector3::ZERO,(Real)i/(Real)(max(2,segments)-1));
00198 }
00199
00200 height_segments = max(2,height_segments);
00201 for (i=0;i<height_segments;++i) {
00202 t = (Real)i/(Real)(max(2,height_segments)-1);
00203 AddPathPoint(pos1+t*v,t,0,Vector3::UNIT_SCALE*(1.0 - t*(1.0-endscale)));
00204 }
00205 delete(circle);
00206 return *this;
00207 }
00208
00209 OgreCone::~OgreCone() {}
00210 OgreCone::OgreCone (kVector3 pos1,kVector3 pos2,kReal rad1X,kReal rad1Y,kReal endscale,size_t segments,size_t height_segments)
00211 : Cone(pos1,pos2,rad1X,rad1Y,endscale,segments,height_segments), OgreRenderableDrawer() { PROFILE
00212 Update(*this);
00213 }