00001 /*!@file AppPsycho/psycho-objectworld.C Create an object world */ 00002 00003 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003 // 00004 // by the University of Southern California (USC) and the iLab at USC. // 00005 // See http://iLab.usc.edu for information about this project. // 00006 // //////////////////////////////////////////////////////////////////// // 00007 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00008 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00009 // in Visual Environments, and Applications'' by Christof Koch and // 00010 // Laurent Itti, California Institute of Technology, 2001 (patent // 00011 // pending; application number 09/912,225 filed July 23, 2001; see // 00012 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00013 // //////////////////////////////////////////////////////////////////// // 00014 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00015 // // 00016 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00017 // redistribute it and/or modify it under the terms of the GNU General // 00018 // Public License as published by the Free Software Foundation; either // 00019 // version 2 of the License, or (at your option) any later version. // 00020 // // 00021 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00022 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00023 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00024 // PURPOSE. See the GNU General Public License for more details. // 00025 // // 00026 // You should have received a copy of the GNU General Public License // 00027 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00028 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00029 // Boston, MA 02111-1307 USA. // 00030 // //////////////////////////////////////////////////////////////////// // 00031 // Primary maintainer for this file: Dan Parks <danielfp@usc.edu> 00032 // $HeadURL$ 00033 // $Id$ 00034 00035 00036 #include "GUI/ViewPort3D.H" 00037 #include "GUI/SuperQuadric.H" 00038 #include "Util/log.H" 00039 #include "Util/WorkThreadServer.H" 00040 #include "Util/JobWithSemaphore.H" 00041 #include "Component/ModelManager.H" 00042 #include "Raster/GenericFrame.H" 00043 #include "Image/Layout.H" 00044 #include "Image/MatrixOps.H" 00045 #include "Image/DrawOps.H" 00046 #include "GUI/DebugWin.H" 00047 #include "Media/FrameSeries.H" 00048 #include "Transport/FrameInfo.H" 00049 #include <stdlib.h> 00050 #include <math.h> 00051 #include <rutz/rand.h> 00052 #include <nub/object.h> 00053 00054 class CartesianPosition 00055 { 00056 protected: 00057 std::vector<float> itsPos; 00058 public: 00059 CartesianPosition(const float x, const float y, const float z, const float roll, const float pitch, const float yaw) 00060 { 00061 itsPos = std::vector<float>(6); 00062 itsPos[0]=x; itsPos[1]=y; itsPos[2]=z; 00063 itsPos[3]=roll; itsPos[4]=pitch; itsPos[5]=yaw; 00064 } 00065 00066 inline const float& operator[](const uint lev) const; 00067 inline float& operator[](const uint lev); 00068 inline CartesianPosition& operator=(const CartesianPosition& pos); 00069 00070 inline size_t size() { return itsPos.size(); } 00071 00072 }; 00073 00074 00075 inline const float& CartesianPosition::operator[](const uint lev) const 00076 { 00077 ASSERT(lev>=0 && lev <=6); 00078 return itsPos[lev]; 00079 } 00080 00081 inline float& CartesianPosition::operator[](const uint lev) 00082 { 00083 ASSERT(lev>=0 && lev <=6); 00084 return itsPos[lev]; 00085 } 00086 00087 inline CartesianPosition& CartesianPosition::operator=(const CartesianPosition& pos) 00088 { 00089 itsPos = pos.itsPos; 00090 return *this; 00091 } 00092 00093 inline CartesianPosition operator*(const CartesianPosition& pos, const float scale) 00094 { 00095 return CartesianPosition(pos[0]*scale,pos[1]*scale,pos[2]*scale,pos[3]*scale,pos[4]*scale,pos[5]*scale); 00096 } 00097 00098 inline CartesianPosition& operator*=(CartesianPosition& pos, const float scale) 00099 { 00100 return (pos=pos*scale); 00101 } 00102 00103 inline CartesianPosition operator+(const CartesianPosition& pos, const CartesianPosition& off) 00104 { 00105 return CartesianPosition(pos[0]+off[0],pos[1]+off[1],pos[2]+off[2],pos[3]+off[3],pos[4]+off[4],pos[5]+off[5]); 00106 } 00107 00108 inline CartesianPosition& operator+=(CartesianPosition& pos, const CartesianPosition& off) 00109 { 00110 return (pos=pos+off); 00111 } 00112 00113 inline CartesianPosition operator-(const CartesianPosition& pos, const CartesianPosition& off) 00114 { 00115 return CartesianPosition(pos[0]-off[0],pos[1]-off[1],pos[2]-off[2],pos[3]-off[3],pos[4]-off[4],pos[5]-off[5]); 00116 } 00117 00118 inline CartesianPosition& operator-=(CartesianPosition& pos, const CartesianPosition& off) 00119 { 00120 return (pos=pos-off); 00121 } 00122 00123 00124 // 3D version of rectangle 00125 class Box 00126 { 00127 protected: 00128 // Center position 00129 CartesianPosition itsPos; 00130 // 3D dims 00131 CartesianPosition itsDims; 00132 public: 00133 Box(CartesianPosition pos, CartesianPosition dims) : 00134 itsPos(pos), 00135 itsDims(dims) 00136 { 00137 } 00138 00139 bool dimContained(CartesianPosition pnt, size_t i) 00140 { 00141 ASSERT(i>=0 && i<=itsDims.size()); 00142 // Check lower bound 00143 if(pnt[i] < itsPos[i]-itsDims[i]/2) 00144 return false; 00145 // Check upper bound 00146 if(pnt[i] > itsPos[i]+itsDims[i]/2) 00147 return false; 00148 return true; 00149 } 00150 00151 bool contains(CartesianPosition pnt) 00152 { 00153 for(size_t i=0;i<itsDims.size();i++) 00154 { 00155 if(!this->dimContained(pnt,i)) 00156 return false; 00157 } 00158 return true; 00159 } 00160 float getVolume() { return itsDims[0]*itsDims[1]*itsDims[2]; } 00161 CartesianPosition getPosition() { return itsPos;} 00162 CartesianPosition getDimensions() { return itsDims;} 00163 }; 00164 00165 class Obj3DComponent : public nub::object 00166 { 00167 protected: 00168 // Type of object 00169 std::string itsType; 00170 rutz::shared_ptr<ViewPort3D> itsViewPort; 00171 CartesianPosition itsPos; 00172 PixRGB<byte> itsColor; 00173 00174 public: 00175 virtual void draw() = 0; 00176 CartesianPosition getPosition() { return itsPos; } 00177 PixRGB<byte> getColor() { return itsColor; } 00178 void setPosition(CartesianPosition pos) { this->itsPos = pos; } 00179 00180 protected: 00181 Obj3DComponent(std::string type,rutz::shared_ptr<ViewPort3D> vp,CartesianPosition pos,PixRGB<byte> color) : 00182 itsType(type), 00183 itsViewPort(vp), 00184 itsPos(pos), 00185 itsColor(color) 00186 { 00187 00188 } 00189 }; 00190 00191 class Obj3DRectangle : public Obj3DComponent 00192 { 00193 float width; 00194 float height; 00195 00196 public: 00197 Obj3DRectangle(rutz::shared_ptr<ViewPort3D> vp, CartesianPosition pos, PixRGB<byte> color, float width, float height) 00198 : Obj3DComponent("Rectangle",vp,pos,color) 00199 { 00200 this->width = width; 00201 this->height = height; 00202 } 00203 00204 virtual void draw() 00205 { 00206 Point3D<float> posPt(itsPos[0],itsPos[1],itsPos[2]); 00207 Point3D<float> rotPt(itsPos[3],itsPos[4],itsPos[5]); 00208 itsViewPort->drawRectangle(posPt,rotPt,width,height,itsColor); 00209 } 00210 }; 00211 class Obj3DCircle : public Obj3DComponent 00212 { 00213 float radius; 00214 public: 00215 Obj3DCircle(rutz::shared_ptr<ViewPort3D> vp, CartesianPosition pos, PixRGB<byte> color, float radius) 00216 : Obj3DComponent("Rectangle",vp,pos,color) 00217 { 00218 this->radius = radius; 00219 } 00220 00221 virtual void draw() 00222 { 00223 Point3D<float> posPt(itsPos[0],itsPos[1],itsPos[2]); 00224 Point3D<float> rotPt(itsPos[3],itsPos[4],itsPos[5]); 00225 itsViewPort->drawCircle(posPt,rotPt,radius,itsColor); 00226 } 00227 }; 00228 00229 class Obj3DBox : public Obj3DComponent 00230 { 00231 Point3D<float> size; 00232 public: 00233 Obj3DBox(rutz::shared_ptr<ViewPort3D> vp, CartesianPosition pos, PixRGB<byte> color, Point3D<float> size) 00234 : Obj3DComponent("Rectangle",vp,pos,color) 00235 { 00236 this->size = size; 00237 } 00238 00239 virtual void draw() 00240 { 00241 Point3D<float> posPt(itsPos[0],itsPos[1],itsPos[2]); 00242 Point3D<float> rotPt(itsPos[3],itsPos[4],itsPos[5]); 00243 itsViewPort->drawBox(posPt,rotPt,size,itsColor); 00244 } 00245 }; 00246 00247 class Obj3DSphere : public Obj3DComponent 00248 { 00249 Point3D<float> size; 00250 public: 00251 Obj3DSphere(rutz::shared_ptr<ViewPort3D> vp, CartesianPosition pos, PixRGB<byte> color, Point3D<float> size) 00252 : Obj3DComponent("Rectangle",vp,pos,color) 00253 { 00254 this->size = size; 00255 } 00256 00257 virtual void draw() 00258 { 00259 Point3D<float> posPt(itsPos[0],itsPos[1],itsPos[2]); 00260 Point3D<float> rotPt(itsPos[3],itsPos[4],itsPos[5]); 00261 itsViewPort->drawSphere(posPt,rotPt,size,itsColor); 00262 } 00263 }; 00264 00265 class Obj3DCylinder : public Obj3DComponent 00266 { 00267 float radius; 00268 float length; 00269 public: 00270 Obj3DCylinder(rutz::shared_ptr<ViewPort3D> vp, CartesianPosition pos, PixRGB<byte> color, float radius, float length) 00271 : Obj3DComponent("Rectangle",vp,pos,color) 00272 { 00273 this->radius = radius; 00274 this->length = length; 00275 } 00276 00277 virtual void draw() 00278 { 00279 Point3D<float> posPt(itsPos[0],itsPos[1],itsPos[2]); 00280 Point3D<float> rotPt(itsPos[3],itsPos[4],itsPos[5]); 00281 itsViewPort->drawCylinder(posPt,rotPt,radius,length,itsColor); 00282 } 00283 }; 00284 00285 class Obj3DComposite : public Obj3DComponent 00286 { 00287 // Note order of members is important, as components are drawn in this order 00288 std::vector<rutz::shared_ptr<Obj3DComponent> > members; 00289 std::vector< CartesianPosition > offsets; 00290 public: 00291 Obj3DComposite(rutz::shared_ptr<ViewPort3D> vp, CartesianPosition pos, PixRGB<byte> color, 00292 std::vector<rutz::shared_ptr<Obj3DComponent> > members, std::vector< CartesianPosition > offsets) 00293 : Obj3DComponent("Rectangle",vp,pos,color) 00294 { 00295 this->members = members; 00296 this->offsets = offsets; 00297 ASSERT(offsets.size() == members.size()); 00298 } 00299 00300 virtual void draw() 00301 { 00302 for(size_t i=0;i<members.size();i++) 00303 { 00304 // Calculate transform between offset and global coordinate frame 00305 members[i]->setPosition(itsPos+offsets[i]); 00306 members[i]->draw(); 00307 } 00308 } 00309 00310 00311 }; 00312 00313 // Subclasses should modify update function 00314 // Simple constant velocity trajectory generator, with bounds 00315 class ObjTrajectory 00316 { 00317 protected: 00318 Box itsBounds; 00319 CartesianPosition itsCurPos; 00320 CartesianPosition itsCurVel; 00321 //! Integration window 00322 float itsIntegStep; 00323 //! Change in time per call (for constant velocity, iterStep==timeStep is ok, but with acceleration, should be integStep << timeStep) 00324 float itsTimeStep; 00325 public: 00326 ObjTrajectory(Box bounds, CartesianPosition initPos, CartesianPosition initVel, float integStep=0.01, float timeStep=0.1) : 00327 itsBounds(bounds), 00328 itsCurPos(initPos), 00329 itsCurVel(initVel) 00330 { 00331 itsIntegStep = integStep; 00332 itsTimeStep = timeStep; 00333 // Integration must be within or equal to the timestep 00334 ASSERT(itsIntegStep<=itsTimeStep); 00335 // The bounds must contain the initial position of the trajectory 00336 ASSERT(itsBounds.contains(itsCurPos)); 00337 } 00338 00339 void update() 00340 { 00341 for(int iter=0;iter*itsIntegStep<itsTimeStep;iter++) 00342 { 00343 CartesianPosition tmp = itsCurPos + itsCurVel*itsIntegStep; 00344 if(!itsBounds.contains(tmp)) 00345 { 00346 for(size_t i=0;i<tmp.size();i++) 00347 { 00348 // Change velocity direction, based on any bound has been exceeded 00349 if(!itsBounds.dimContained(tmp,i)) 00350 { 00351 itsCurVel[i]=-itsCurVel[i]; 00352 } 00353 } 00354 } 00355 else 00356 itsCurPos = tmp; 00357 } 00358 } 00359 00360 CartesianPosition getPosition(){ return itsCurPos; } 00361 00362 }; 00363 00364 00365 rutz::shared_ptr<Obj3DComponent> initObject1(rutz::shared_ptr<ViewPort3D> vp) 00366 { 00367 CartesianPosition z(0,0,0,0,0,0); 00368 float basew=70,baseh=100; 00369 Obj3DRectangle *rbase = new Obj3DRectangle(vp,z,PixRGB<byte>(256,0,0),basew,baseh); 00370 float r1w=20,r1h=20; 00371 Obj3DRectangle *r1 = new Obj3DRectangle(vp,z,PixRGB<byte>(0,256,0),r1w,r1h); 00372 float c1r=8; 00373 Obj3DCircle *c1 = new Obj3DCircle(vp,z,PixRGB<byte>(0,0,256),c1r); 00374 Obj3DCircle *c2 = new Obj3DCircle(vp,z,PixRGB<byte>(0,0,256),c1r); 00375 std::vector<rutz::shared_ptr<Obj3DComponent> > members; 00376 members.push_back(rutz::shared_ptr<Obj3DComponent>(rbase)); 00377 members.push_back(rutz::shared_ptr<Obj3DComponent>(r1)); 00378 members.push_back(rutz::shared_ptr<Obj3DComponent>(c1)); 00379 members.push_back(rutz::shared_ptr<Obj3DComponent>(c2)); 00380 std::vector<CartesianPosition > offsets; 00381 offsets.push_back(CartesianPosition(0,0,-1,0,0,0)); 00382 offsets.push_back(CartesianPosition(0,-30,0,0,0,0)); 00383 offsets.push_back(CartesianPosition(20,30,0,0,0,0)); 00384 offsets.push_back(CartesianPosition(-20,30,0,0,0,0)); 00385 Obj3DComposite *comp = new Obj3DComposite(vp,z,PixRGB<byte>(0,0,0),members,offsets); 00386 return rutz::shared_ptr<Obj3DComponent>(comp); 00387 } 00388 00389 int main(int argc, char *argv[]){ 00390 00391 ModelManager manager("Test Object World"); 00392 00393 nub::ref<OutputFrameSeries> ofs(new OutputFrameSeries(manager)); 00394 manager.addSubComponent(ofs); 00395 00396 // Parse command-line: 00397 if (manager.parseCommandLine(argc, argv, "", 0, 0) == false) return(1); 00398 // let's get all our ModelComponent instances started: 00399 manager.start(); 00400 00401 //Normal operation 00402 00403 rutz::shared_ptr<ViewPort3D> vp = rutz::shared_ptr<ViewPort3D>(new ViewPort3D(320,240, false, true, false)); 00404 //ViewPort3D vp(320,240); 00405 vp->setCamera(Point3D<float>(0,0,350), Point3D<float>(0,0,0)); 00406 00407 CartesianPosition trajVel(2,2,0,0,0,0); 00408 rutz::shared_ptr<Obj3DComponent> obj1 = initObject1(vp); 00409 CartesianPosition boundSize(100,100,4,0,0,0); 00410 CartesianPosition z(0,0,0,0,0,0); 00411 Box bounds = Box(z,boundSize); 00412 ObjTrajectory traj1 = ObjTrajectory(bounds,z,trajVel); 00413 int rot = 0; 00414 while(1) 00415 { 00416 vp->initFrame(); 00417 00418 rot = ((rot +1)%360); 00419 00420 std::vector<Point2D<float> > contour; 00421 00422 Point3D<float> ctr = Point3D<float>(60,60,0); 00423 00424 traj1.update(); 00425 obj1->setPosition(traj1.getPosition()); 00426 obj1->draw(); 00427 00428 00429 Image<PixRGB<byte> > img = flipVertic(vp->getFrame()); 00430 ofs->writeRGB(img, "ViewPort3D", FrameInfo("ViewPort3D", SRC_POS)); 00431 usleep(10000); 00432 } 00433 00434 00435 exit(0); 00436 00437 } 00438 00439