source: flair-src/trunk/lib/FlairSimulator/src/SimuCameraGL.cpp@ 10

Last change on this file since 10 was 10, checked in by Sanahuja Guillaume, 8 years ago

lic

File size: 7.2 KB
Line 
1// %flair:license{
2// This file is part of the Flair framework distributed under the
3// CECILL-C License, Version 1.0.
4// %flair:license}
5// created: 2014/03/07
6// filename: SimuCameraGL.cpp
7//
8// author: Guillaume Sanahuja
9// Copyright Heudiasyc UMR UTC/CNRS 7253
10// pbo code from Song Ho Ahn (song.ahn@gmail.com)
11//
12// version: $Id: $
13//
14// purpose: Class for a simulation camera
15//
16//
17/*********************************************************************/
18#ifdef GL
19
20#include "SimuCameraGL.h"
21#include "Model.h"
22#include <SharedMem.h>
23#include <TabWidget.h>
24#include <Tab.h>
25#include <DoubleSpinBox.h>
26#include <Vector3DSpinBox.h>
27#include <Gui.h>
28#include <Euler.h>
29
30#include <ISceneManager.h>
31#include <ICameraSceneNode.h>
32#include <IVideoDriver.h>
33
34#define PBO_COUNT 2
35
36using namespace irr;
37using namespace irr::scene;
38using namespace irr::core;
39using namespace flair::core;
40using namespace flair::gui;
41using namespace flair::simulator;
42
43namespace flair
44{
45namespace sensor
46{
47
48SimuCameraGL::SimuCameraGL(const Model* parent,std::string name,int width,int height,int x,int y,int dev_id) :SimuCamera(parent,name,width,height,3,dev_id),SensorGL(parent)
49{
50 smgr=getGui()->getSceneManager();
51 camera=smgr->addCameraSceneNode();
52 camera->addAnimator(this);
53 camera->setAspectRatio(4.0f/3.0f);//on force a cause du view port
54
55 this->width=width;
56 this->height=height;
57 this->x=x;
58 this->y=y;
59
60 index = 0;
61
62 buffer=(char*)malloc(width*height*3);
63
64 //user interface
65 Tab* setup_tab=new Tab(parent->GetTabWidget(),name);
66 position=new Vector3DSpinBox(setup_tab->NewRow(),"position",-2,2,.01);
67 direction=new Vector3DSpinBox(setup_tab->NewRow(),"direction",-2,2,.01);
68 up=new Vector3DSpinBox(setup_tab->NewRow(),"up",-2,2,.01);
69 fov=new DoubleSpinBox(setup_tab->NewRow(),"fov:",0,180,5);
70
71 if(strcmp((char*)glGetString(GL_VENDOR),"Intel Open Source Technology Center")==0) {
72 Thread::Warn("disabling cameras output for Intel card (bug with PBO)\n");
73 disable_output=true;
74 } else {
75 disable_output=false;
76 }
77
78 if(isGlExtensionSupported("GL_ARB_pixel_buffer_object"))
79 {
80 use_pbo=true;
81 // create 2 pixel buffer objects, you need to delete them when program exits.
82 // glBufferDataARB with NULL pointer reserves only memory space.
83 pboIds=(GLuint*)malloc(PBO_COUNT*sizeof(GLuint));
84 glGenBuffersARB(PBO_COUNT, pboIds);
85 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[0]);
86 glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, width*height*3, 0, GL_STREAM_READ_ARB);
87 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[1]);
88 glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, width*height*3, 0, GL_STREAM_READ_ARB);
89
90 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
91 }
92 else
93 {
94 use_pbo=false;
95 Thread::Warn("GL_ARB_pixel_buffer_object is not suppoorted\n");
96 }
97 if(isGlExtensionSupported("GL_PACK_INVERT_MESA"))
98 {
99 invert_pixel=false;
100 Thread::Warn("GL_PACK_INVERT_MESA is suppoorted\n");
101 }
102 else
103 {
104 invert_pixel=true;
105 }
106}
107
108SimuCameraGL::~SimuCameraGL()
109{
110 free(buffer);
111
112 if(use_pbo)
113 {
114 glDeleteBuffersARB(PBO_COUNT, pboIds);
115 free(pboIds);
116 }
117}
118
119void SimuCameraGL::setNearValue(float zn) {
120 camera->setNearValue(zn);
121}
122
123
124void SimuCameraGL::setFarValue(float zf) {
125 camera->setFarValue(zf);
126}
127
128
129void SimuCameraGL::UpdateFrom(const io_data *data)
130{
131 if(noGui()==false && data==NULL)
132 {
133 smgr->setActiveCamera(camera);
134 smgr->getVideoDriver()->setViewPort(rect<s32>(x,y,x+width,y+height));
135 smgr->drawAll();
136 //use_pbo=false;
137 getImage();
138 }
139}
140
141void SimuCameraGL::getImage(void)
142{
143 if(disable_output) return;
144 //convert from irrlicht top left origin to gl bottom left origin
145 int y=smgr->getVideoDriver()->getScreenSize().Height-height-this->y;
146
147 // We want to read the front buffer to get the latest render finished.
148 Time a=GetTime();
149 glReadBuffer(GL_FRONT);
150 if(use_pbo) // with PBO
151 {
152 // increment current index first then get the next index
153 // "index" is used to read pixels from a framebuffer to a PBO
154 // "nextIndex" is used to process pixels in the other PBO
155 index = (index + 1) % PBO_COUNT;
156 int nextIndex = (index + 1) % PBO_COUNT;
157
158 // copy pixels from framebuffer to PBO
159 // Use offset instead of pointer.
160 // OpenGL should perform asynch DMA transfer, so glReadPixels() will return immediately.
161 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[index]);
162 glReadPixels(x,y,width,height, GL_BGR, GL_UNSIGNED_BYTE, 0);
163
164 // map the PBO that contain framebuffer pixels before processing it
165 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[nextIndex]);
166 GLubyte* src = (GLubyte*)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB,GL_READ_WRITE_ARB);//GL_READ_ONLY_ARB);
167 if(src)
168 {
169 putImage((char*)src);
170 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); // release pointer to the mapped buffer
171 }
172 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
173 }
174 else
175 {
176 glReadPixels(x,y,width,height, GL_BGR, GL_UNSIGNED_BYTE, buffer);
177 putImage(buffer);
178 }
179
180 glReadBuffer(GL_BACK);
181 Time b=GetTime();
182 Time c=b-a;
183 //printf("%s %f\n",Thread::ObjectName().c_str(),(float)(c/1000000.));
184}
185
186void SimuCameraGL::putImage(char* buf)
187{
188 if(invert_pixel==true)
189 {
190 // opengl images are horizontally flipped, so we have to fix that here.
191 const s32 pitch=width*3;
192 char* pixels = buf;
193 char* p2 = pixels + (height - 1) * pitch;
194 char* tmpBuffer = new char[pitch];
195 for (int i=0; i < height; i += 2)
196 {
197 memcpy(tmpBuffer, pixels, pitch);
198 memcpy(pixels, p2, pitch);
199 memcpy(p2, tmpBuffer, pitch);
200 pixels += pitch;
201 p2 -= pitch;
202 }
203 delete [] tmpBuffer;
204 }
205
206 shmem->Write(buf,width*height*3);
207}
208
209void SimuCameraGL::animateNode(ISceneNode* node, u32 timeMs)
210{
211 ICameraSceneNode* camera = static_cast<ICameraSceneNode*>(node);
212
213 matrix4 m;
214 m.setRotationDegrees(Node()->getRotation());
215
216 // transform forward vector of camera
217 vector3df frv =ToIrrlichtCoordinates(direction->Value());
218 m.transformVect(frv);
219
220 // transform upvector of camera
221 vector3df upv =ToIrrlichtCoordinates(up->Value());
222 m.transformVect(upv);
223
224 // transform camera offset (thanks to Zeuss for finding it was missing)
225 vector3df offset = ToIrrlichtCoordinates(position->Value());
226 m.transformVect(offset);
227
228 // set camera
229 camera->setPosition(Node()->getPosition() + offset); //position camera in front of the ship
230 camera->setUpVector(upv); //set up vector of camera >> Zeuss - tested with +node->getPostion() and it didnt work, but this works fine.
231 camera->setTarget(Node()->getPosition() + offset+frv); //set target of camera (look at point) >> Zeuss - Dont forget to add the node positiob
232
233 camera->setFOV(Euler::ToRadian(fov->Value()));
234}
235
236ISceneNodeAnimator* SimuCameraGL::createClone(ISceneNode* node,
237 ISceneManager* newManager)
238{
239 return NULL;
240}
241
242} // end namespace sensor
243} // end namespace flair
244#endif
Note: See TracBrowser for help on using the repository browser.