1/* PROJECT: 3Dmov 2 AUTHORS: Zenja Solaja 3 COPYRIGHT: 2009 Haiku Inc 4 DESCRIPTION: Haiku version of the famous BeInc demo 3Dmov 5 Just drag'n'drop media files to the 3D objects 6*/ 7 8#include <stdio.h> 9#include <string.h> 10#include <assert.h> 11 12#include <Bitmap.h> 13#include <TranslationUtils.h> 14 15#include "GLUtility.h" 16#include "ViewCube.h" 17 18// Local definitions 19 20// Local functions 21 22// Local variables 23 24/******************************** 25 Cube scene 26*********************************/ 27class Cube 28{ 29public: 30 enum FACE 31 { 32 FACE_RIGHT, 33 FACE_LEFT, 34 FACE_FRONT, 35 FACE_BACK, 36 FACE_TOP, 37 FACE_BOTTOM, 38 NUMBER_CUBE_FACES, 39 }; 40 Cube(const float half_extent); 41 ~Cube(); 42 void Render(); 43 void SetMediaSource(FACE face, MediaSource *source) {fMediaSources[face] = source;} 44 void SetAngle(float angle_x, float angle_y, float angle_z); 45 46private: 47 MediaSource *fMediaSources[NUMBER_CUBE_FACES]; 48 float fRotationX, fRotationY, fRotationZ; 49 float *fGeometry; 50}; 51 52/* FUNCTION: Cube :: Cube 53 ARGUMENTS: half_extent 54 RETURN: n/a 55 DESCRIPTION: Constructor 56*/ 57Cube :: Cube(const float half_extent) 58{ 59 for (int i=0; i < NUMBER_CUBE_FACES; i++) 60 fMediaSources[i] = 0; 61 fRotationX = fRotationY = fRotationZ = 0; 62 63 const float kVertices[NUMBER_CUBE_FACES][4][3] = 64 { 65 { // FACE_RIGHT 66 {half_extent, -half_extent, -half_extent}, 67 {half_extent, half_extent, -half_extent}, 68 {half_extent, -half_extent, half_extent}, 69 {half_extent, half_extent, half_extent}, 70 }, 71 { // FACE_LEFT 72 {-half_extent, half_extent, -half_extent}, 73 {-half_extent, -half_extent, -half_extent}, 74 {-half_extent, half_extent, half_extent}, 75 {-half_extent, -half_extent, half_extent}, 76 }, 77 { // FACE_FRONT 78 {-half_extent, -half_extent, -half_extent}, 79 {half_extent, -half_extent, -half_extent}, 80 {-half_extent, -half_extent, half_extent}, 81 {half_extent, -half_extent, half_extent}, 82 }, 83 { // FACE_BACK 84 {half_extent, half_extent, -half_extent}, 85 {-half_extent, half_extent, -half_extent}, 86 {half_extent, half_extent, half_extent}, 87 {-half_extent, half_extent, half_extent}, 88 }, 89 { // FACE_TOP 90 {-half_extent, -half_extent, half_extent}, 91 {half_extent, -half_extent, half_extent}, 92 {-half_extent, half_extent, half_extent}, 93 {half_extent, half_extent, half_extent}, 94 }, 95 { // FACE_BOTTOM 96 {-half_extent, half_extent, -half_extent}, 97 {half_extent, half_extent, -half_extent}, 98 {-half_extent, -half_extent, -half_extent}, 99 {half_extent, -half_extent, -half_extent}, 100 }, 101 }; 102 fGeometry = new float [sizeof(kVertices)/sizeof(float)]; 103 memcpy(fGeometry, kVertices, sizeof(kVertices)); 104} 105 106/* FUNCTION: Cube :: ~Cube 107 ARGUMENTS: n/a 108 RETURN: n/a 109 DESCRIPTION: Destructor - fMediaSources owned by ViewCube 110*/ 111Cube :: ~Cube() 112{ 113 delete [] fGeometry; 114} 115 116/* FUNCTION: Cube :: SetAngle 117 ARGUMENTS: angle_x 118 angle_y 119 angle_z 120 RETURN: n/a 121 DESCRIPTION: Rotate cube by Euler angles 122*/ 123void Cube :: SetAngle(float angle_x, float angle_y, float angle_z) 124{ 125 fRotationX = angle_x; 126 fRotationY = angle_y; 127 fRotationZ = angle_z; 128} 129 130/* FUNCTION: Cube :: Render 131 ARGUMENTS: none 132 RETURN: n/a 133 DESCRIPTION: Draw sphere 134*/ 135void Cube :: Render() 136{ 137 const float kTextureCoords[4*2] = 138 { 139 0.0f, 1.0f, 140 1.0f, 1.0f, 141 0.0f, 0.0f, 142 1.0f, 0.0f, 143 }; 144 145 glPushMatrix(); 146 glRotatef(fRotationX, 1, 0, 0); 147 glRotatef(fRotationY, 0, 1, 0); 148 glRotatef(fRotationZ, 0, 0, 1); 149 150 glColor4f(1,1,1,1); 151 for (int i=0; i < NUMBER_CUBE_FACES; i++) 152 { 153 glBindTexture(GL_TEXTURE_2D, fMediaSources[i]->mTextureID); 154 glTexCoordPointer(2, GL_FLOAT, 0, kTextureCoords); 155 glVertexPointer(3, GL_FLOAT, 0, fGeometry + i*3*4); 156 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 157 } 158 glPopMatrix(); 159} 160 161/******************************** 162 ViewCube 163*********************************/ 164 165/* FUNCTION: ViewCube :: ViewCube 166 ARGUMENTS: frame 167 RETURN: n/a 168 DESCRIPTION: Constructor 169*/ 170ViewCube :: ViewCube(BRect frame) 171 : ViewObject(frame) 172{ 173 fStartTime = real_time_clock_usecs(); 174 175 for (int i=0; i < NUMBER_FACES; i++) 176 fMediaSources[i] = 0; 177 fCube = 0; 178 fSpeed = 10; 179 fMouseTracking = false; 180} 181 182/* FUNCTION: ViewCube :: ~ViewCube 183 ARGUMENTS: n/a 184 RETURN: n/a 185 DESCRIPTION: Destructor 186*/ 187ViewCube :: ~ViewCube() 188{ 189 delete fCube; 190 for (int i=0; i < NUMBER_FACES; i++) 191 { 192 if (fMediaSources[i] != GetDefaultMediaSource()) 193 delete fMediaSources[i]; 194 } 195} 196 197/* FUNCTION: ViewCube :: ViewCube 198 ARGUMENTS: none 199 RETURN: n/a 200 DESCRIPTION: Hook function called when view attached to window (looper) 201*/ 202void ViewCube :: AttachedToWindow(void) 203{ 204 ViewObject::AttachedToWindow(); 205 206 LockGL(); 207 glClearColor(0,0,0,1); 208 209 fCube = new Cube(0.075f); 210 211 for (int i=0; i < NUMBER_FACES; i++) 212 { 213 fMediaSources[i] = GetDefaultMediaSource(); 214 fCube->SetMediaSource((Cube::FACE) i, fMediaSources[i]); 215 } 216 217 UnlockGL(); 218} 219 220/* FUNCTION: ViewCube :: Render 221 ARGUMENTS: none 222 RETURN: n/a 223 DESCRIPTION: Draw view contents 224*/ 225void ViewCube :: Render(void) 226{ 227 LockGL(); 228 229 bigtime_t current_time = real_time_clock_usecs(); 230 bigtime_t delta = current_time - fStartTime; 231 fStartTime = current_time; 232 233 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 234 235 fCubeAngle += fSpeed*(float)delta/1000000.0f; 236 fCube->SetAngle(0, 0, fCubeAngle); 237 238 glPushMatrix(); 239 glTranslatef(0.0f, 0.0f, 0.15f); 240 fCube->Render(); 241 glPopMatrix(); 242 243 glFlush(); 244 SwapBuffers(); 245 246 // Display frame rate 247 /* 248 static int fps = 0; 249 static int time_delta = 0; 250 fps++; 251 time_delta += delta; 252 if (time_delta > 1000000) 253 { 254 printf("%d fps\n", fps); 255 fps = 0; 256 time_delta = 0; 257 } 258 */ 259 UnlockGL(); 260} 261 262/* FUNCTION: ViewCube :: MouseDown 263 ARGUMENTS: p 264 RETURN: n/a 265 DESCRIPTION: Hook function called when mouse down detected 266*/ 267void ViewCube :: MouseDown(BPoint p) 268{ 269 // Determine mouse button 270 BMessage* msg = Window()->CurrentMessage(); 271 uint32 buttons; 272 273 msg->FindInt32("buttons", (int32*)&buttons); 274 275 if (buttons & B_PRIMARY_MOUSE_BUTTON) 276 { 277 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY); 278 fMouseTracking = true; 279 fMousePosition = p; 280 } 281} 282 283/* FUNCTION: ViewCube :: MouseMoved 284 ARGUMENTS: p 285 transit 286 message 287 RETURN: n/a 288 DESCRIPTION: Hook function called when mouse move detected 289*/ 290void ViewCube :: MouseMoved(BPoint p, uint32 transit, const BMessage *message) 291{ 292 if (fMouseTracking) 293 { 294 if (transit == B_INSIDE_VIEW) 295 { 296 fSpeed = 5.0f*(p.x - fMousePosition.x); 297 fMousePosition = p; 298 } 299 } 300 301} 302 303/* FUNCTION: ViewSphere :: MouseUp 304 ARGUMENTS: p 305 RETURN: n/a 306 DESCRIPTION: Hook function called when mouse up detected 307*/ 308void ViewCube :: MouseUp(BPoint p) 309{ 310 fMouseTracking = false; 311} 312 313/* FUNCTION: ViewSphere :: DragDropImage 314 ARGUMENTS: texture_id 315 mouse_x 316 mouse_y 317 RETURN: true if source ownership acquired 318 DESCRIPTION: Hook function called when user drags/drops image to app window. 319 TODO - actually determine exact face where refs received. For this 320 release, we only rely on current fCubeAngle. 321*/ 322bool ViewCube :: SurfaceUpdate(MediaSource *source, float mouse_x, float mouse_y) 323{ 324 // determine face 325 BRect frame = Bounds(); 326 Cube::FACE face = Cube::NUMBER_CUBE_FACES; 327 328 if (mouse_y < frame.Height()*0.33f) 329 face = Cube::FACE_TOP; 330 else 331 { 332 if (fCubeAngle < 45) 333 face = Cube::FACE_FRONT; 334 else if (fCubeAngle < 135) 335 face = Cube::FACE_LEFT; 336 else if (fCubeAngle < 225) 337 face = Cube::FACE_BACK; 338 else if (fCubeAngle < 315) 339 face = Cube::FACE_RIGHT; 340 else 341 face = Cube::FACE_FRONT; 342 } 343 if (fMediaSources[face] != GetDefaultMediaSource()) 344 delete fMediaSources[face]; 345 fMediaSources[face] = source; 346 fCube->SetMediaSource(face, source); 347 348 return true; 349} 350 351 352 353 354