Author: phoudoin Date: 2010-01-30 12:14:16 +0100 (Sat, 30 Jan 2010) New Revision: 35341 Changeset: http://dev.haiku-os.org/changeset/35341/haiku Added: haiku/trunk/src/apps/3dmov/Application.cpp haiku/trunk/src/apps/3dmov/GLUtility.cpp haiku/trunk/src/apps/3dmov/GLUtility.h haiku/trunk/src/apps/3dmov/MainWindow.cpp haiku/trunk/src/apps/3dmov/MainWindow.h haiku/trunk/src/apps/3dmov/Video.cpp haiku/trunk/src/apps/3dmov/Video.h haiku/trunk/src/apps/3dmov/ViewBook.cpp haiku/trunk/src/apps/3dmov/ViewBook.h haiku/trunk/src/apps/3dmov/ViewCube.cpp haiku/trunk/src/apps/3dmov/ViewCube.h haiku/trunk/src/apps/3dmov/ViewObject.cpp haiku/trunk/src/apps/3dmov/ViewObject.h haiku/trunk/src/apps/3dmov/ViewSphere.cpp haiku/trunk/src/apps/3dmov/ViewSphere.h haiku/trunk/src/apps/3dmov/instructions.png Modified: haiku/trunk/src/apps/3dmov/3dmov.rdef haiku/trunk/src/apps/3dmov/Jamfile Log: Import Zenja Solaja's 3DMov over fran?\195?\131?\194?\167ois skeleton. Modified: haiku/trunk/src/apps/3dmov/3dmov.rdef =================================================================== --- haiku/trunk/src/apps/3dmov/3dmov.rdef 2010-01-30 08:23:37 UTC (rev 35340) +++ haiku/trunk/src/apps/3dmov/3dmov.rdef 2010-01-30 11:14:16 UTC (rev 35341) @@ -1,37 +1,11 @@ /* - * Copyright 2004-2009, Haiku Inc. All rights reserved. + * Copyright 2009, Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: - * François Revol <revol@xxxxxxx> + * Zenja Solaja */ -resource(1, "BEOS:APP_FLAGS") (#'APPF') $"00000000"; +resource app_signature "application/x-vnd.Haiku-3DMov"; -resource(1, "BEOS:APP_VERSION") #'APPV' array { - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"000000000000000000000000000000000000000080031200FC105760EC111000" - $"EC088BC800000000FC1057808003220080052980800294408000600380032200" - $"8005298000000002FC1057C0FC105A7C000000018003E7800000000280032200" - $"800529808002944080006003EC02ECB88005298000000000FC1057D0EC111000" - $"EC01BE200000000200000000FC105A7C000000018003E7800000000280006003" - $"000000028001DEE88001DEF8EC02ECB88004B38000000000FC1058108003E780" - $"EC01BE20EC02ECB8FC105810EC111000EC01BE7C00000001FC10582000000000" - $"EC02ECBCFFFFFFFFEC05B434FC1058B88005298080029440FC10585080019244" - $"FC1059B8EC02ECB8FC105850EC111000EC01BE7C8002A680FC105870EC111000" - $"80052980FFFFFFFFEC05B434FC10593800000004000201DC800060038003E780" - $"8005298000000000FC105890420C0000EC019C080000010043300000EC111000" - $"8004B38000000000" -}; - -resource(1, "BEOS:APP_SIG") (#'MIMS') "application/x-vnd.Haiku-3DMov"; - +resource(1, "instructions.png") #'PNG ' import "instructions.png"; Added: haiku/trunk/src/apps/3dmov/Application.cpp =================================================================== --- haiku/trunk/src/apps/3dmov/Application.cpp (rev 0) +++ haiku/trunk/src/apps/3dmov/Application.cpp 2010-01-30 11:14:16 UTC (rev 35341) @@ -0,0 +1,63 @@ +/* PROJECT: 3Dmov + AUTHORS: Zenja Solaja + COPYRIGHT: 2009 Haiku Inc + DESCRIPTION: Haiku version of the famous BeInc demo 3Dmov + + There is an issue in Haiku when creating a 2nd BGLView which doesn't exist in Zeta + (see MainWindow.cpp for details). Until that issue is resolved, + I've allowed specifying of shape type (0-2) as a command line argument. +*/ + +#include <Application.h> + +#include "MainWindow.h" + +/***************************** + Main application +******************************/ +class MainApp : public BApplication +{ +public: + MainApp(MainWindow::SHAPE shape); + +private: + MainWindow *fWindow; +}; + +/* FUNCTION: MainApp :: MainApp + ARGS: none + RETURN: n/a + DESCRIPTION: Application constructor +*/ +MainApp :: MainApp(MainWindow::SHAPE shape) + : BApplication("application/x_vnd.Haiku") +{ + BRect frame(50, 50, 50+400, 50+300); + fWindow = new MainWindow(frame, shape); +} + +/****************************** + Program entry point +*******************************/ + +/* FUNCTION: main + ARGS: arc number of command line arguments + argv vector to arguments + RETURN: Exit status + DESCRIPTION: main program entry point +*/ +int main(int argc, char **argv) +{ + // Check if shape specified on command line + MainWindow::SHAPE shape = MainWindow::BOOK; + if (argc > 1) + { + int value = *argv[1] - '0'; + if (value >= 0 && value < MainWindow::NUMBER_OF_SHAPES) + shape = (MainWindow::SHAPE) value; + } + + MainApp *app = new MainApp(shape); + app->Run(); + delete app; +} Added: haiku/trunk/src/apps/3dmov/GLUtility.cpp =================================================================== --- haiku/trunk/src/apps/3dmov/GLUtility.cpp (rev 0) +++ haiku/trunk/src/apps/3dmov/GLUtility.cpp 2010-01-30 11:14:16 UTC (rev 35341) @@ -0,0 +1,244 @@ +/* PROJECT: 3Dmov + AUTHORS: Zenja Solaja + COPYRIGHT: 2009 Haiku Inc + DESCRIPTION: Haiku version of the famous BeInc demo 3Dmov + Just drag'n'drop media files to the 3D objects +*/ + +#include <GL/gl.h> +#include <string.h> + +#include "GLUtility.h" + +// Local definitions + +// Local functions + +// Local variables + +/* FUNCTION: GLCreateIdentityMatrix + ARGUMENTS: m destination matrix + RETURN: n/a + DESCRIPTION: Create identity matrix +*/ +void GLCreateIdentityMatrix(float *m) +{ + const float kIdentity[16] = + { + 1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1, + }; + memcpy(m, kIdentity, 16*sizeof(float)); +} + +/* FUNCTION: GLMatrixMultiply + ARGUMENTS: product + m1, m2 + RETURN: product + DESCRIPTION: Perform a 4x4 matrix multiplication (product = m1 x m2) +*/ +void GLMatrixMultiply(float *product, float *m1, float *m2) +{ + product[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3]; + product[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3]; + product[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3]; + product[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3]; + + product[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7]; + product[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7]; + product[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7]; + product[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7]; + + product[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11]; + product[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11]; + product[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11]; + product[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11]; + + product[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15]; + product[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15]; + product[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15]; + product[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15]; +} + +/* FUNCTION: GLCreatePerspectiveMatrix + ARGUMENTS: m destination matrix + fov field of view + aspect aspect ratio + znear near plane + zfar far plane + RETURN: n/a + DESCRIPTION: Same as gluPerspective +*/ +void GLCreatePerspectiveMatrix(float *m, float fov, float aspect, float znear, float zfar) +{ + const float h = 1.0f/tand(fov/2.0f); + float neg_depth = znear-zfar; + + m[0] = h / aspect; + m[1] = 0; + m[2] = 0; + m[3] = 0; + + m[4] = 0; + m[5] = h; + m[6] = 0; + m[7] = 0; + + m[8] = 0; + m[9] = 0; + m[10] = (zfar + znear)/neg_depth; + m[11] = -1; + + m[12] = 0; + m[13] = 0; + m[14] = 2.0f*(znear*zfar)/neg_depth; + m[15] = 0; +} + +/* FUNCTION: GLCreateModelViewMatrix + ARGUMENTS: m destination matrix + x,y,z position + yaw compass direction, 0-north, 90-east, 180-south, 270-west + pitch azimuth, -90 down, 0 forwad, 90 up + roll rotation around forward axis + RETURN: n/a + DESCRIPTION: Position camera +*/ +void GLCreateModelViewMatrix(float *m, float x, float y, float z, float yaw, float pitch, float roll) +{ + // same as gluLookAt + Quaternion q, qDir, qAzim; + qAzim.GenerateLocalRotation(pitch + 90.0f, -1.0f, 0.0f, 0.0f); + qDir.GenerateLocalRotation(yaw, 0.0f, 0.0f, 1.0f); + q = qAzim * qDir; + + if (roll != 0) + { + Quaternion qTilt; + qTilt.GenerateLocalRotation(roll, 0, 0, 1); + q = qTilt * q; + } + q.CreateRotatedQuaternion(m); + + // move camera + float mov[16]; + GLCreateIdentityMatrix(mov); + mov[12] = -x; + mov[13] = -y; + mov[14] = -z; + GLMatrixMultiply(m, m, mov); +} + +/************************** + Quaternion class +***************************/ + +/* FUNCTION: Quaternion + ARGUMENTS: none + RETURN: n/a + DESCRIPTION: Constructor. No rotation. +*/ +Quaternion :: Quaternion() +{ + x = y = z = 0.0f; + w = 1.0f; +} + +/* FUNCTION: Quaternion :: GenerateLocalRotation + ARGUMENTS: angle + x_axis, y_axis, z_axis axis of rotation + RETURN: n/a + DESCRIPTION: Create unit quaterion corresponding to a rotation through angle <angle> + about axis <a,b,c>. + q = cos (angle/2) + A(a,b,c)*sin(angle/2) + +*/ +void Quaternion :: GenerateLocalRotation(float angle, float x_axis, float y_axis, float z_axis) +{ + float temp = sind(0.5f*angle); + + w = cosd(0.5f*angle); + x = x_axis * temp; + y = y_axis * temp; + z = z_axis * temp; +} + +/* FUNCTION: Quaternion :: GenerateFromEuler + ARGUMENTS: roll (degrees) + pitch (degrees) + yaw (degrees) + RETURN: n/a + DESCRIPTION: Creates quaternion from euler angles. Borowed from Bullet +*/ +void Quaternion :: GenerateFromEuler(float roll, float pitch, float yaw) +{ + float halfYaw = 0.5f * yaw; + float halfPitch = 0.5f * pitch; + float halfRoll = 0.5f * roll; + float cosYaw = cosd(halfYaw); + float sinYaw = sind(halfYaw); + float cosPitch = cosd(halfPitch); + float sinPitch = sind(halfPitch); + float cosRoll = cosd(halfRoll); + float sinRoll = sind(halfRoll); + + x = sinRoll*cosPitch*cosYaw - cosRoll*sinPitch*sinYaw; + y = cosRoll*sinPitch*cosYaw + sinRoll*cosPitch*sinYaw; + z = cosRoll*cosPitch*sinYaw - sinRoll*sinPitch*cosYaw; + w = cosRoll*cosPitch*cosYaw + sinRoll*sinPitch*sinYaw; +} + +/* FUNCTION: Quaternion :: CreateRotatedQuaternion + ARGUMENTS: matrix + RETURN: n/a + DESCRIPTION: Creates rotated quaterion. Always call GenerateLocalRotation() prior + to calling this method +*/ +void Quaternion :: CreateRotatedQuaternion(float *matrix) +{ + if (!matrix) + return; + + // first row + matrix[0] = 1.0f - 2.0f*(y*y + z*z); + matrix[1] = 2.0f*(x*y + w*z); + matrix[2] = 2.0f*(x*z - w*y); + matrix[3] = 0.0f; + + // second row + matrix[4] = 2.0f*(x*y - w*z); + matrix[5] = 1.0f - 2.0f*(x*x + z*z); + matrix[6] = 2.0f*(y*z + w*x); + matrix[7] = 0.0f; + + // third row + matrix[8] = 2.0f*(x*z + w*y); + matrix[9] = 2.0f*(y*z - w*x); + matrix[10] = 1.0f - 2.0f*(x*x + y*y); + matrix[11] = 0.0f; + + // forth row + matrix[12] = 0; + matrix[13] = 0; + matrix[14] = 0; + matrix[15] = 1.0f; +} + +/* FUNCTION: operator * + ARGUMENTS: q + RETURN: multiplied quaternion + DESCRIPTION: Creates rotated quaternion +*/ +const Quaternion Quaternion::operator *(Quaternion q) +{ + Quaternion p; + + p.x = w*q.x + x*q.w + y*q.z - z*q.y; // (w1x2 + x1w2 + y1z2 - z1y2)i + p.y = w*q.y - x*q.z + y*q.w + z*q.x; // (w1y2 - x1z2 + y1w2 + z1x2)j + p.z = w*q.z + x*q.y - y*q.x + z*q.w; // (w1z2 + x1y2 - y1x2 + z1w2)k + p.w = w*q.w - x*q.x - y*q.y - z*q.z; // (w1w2 - x1x2 - y1y2 - z1z2) + + return(p); +} Added: haiku/trunk/src/apps/3dmov/GLUtility.h =================================================================== --- haiku/trunk/src/apps/3dmov/GLUtility.h (rev 0) +++ haiku/trunk/src/apps/3dmov/GLUtility.h 2010-01-30 11:14:16 UTC (rev 35341) @@ -0,0 +1,58 @@ +/* PROJECT: 3Dmov + AUTHORS: Zenja Solaja + COPYRIGHT: 2009 Haiku Inc + DESCRIPTION: Haiku version of the famous BeInc demo 3Dmov + Just drag'n'drop media files to the 3D objects +*/ + +#ifndef _GL_UTILITY_H_ +#define _GL_UTILITY_H_ + +#include <cmath> + +/************************** + Definitions +***************************/ +#define Y_PI 3.14159265358979323846f +#define Y_PI_DIV_180 (Y_PI/180.0f) + + +/************************** + Macros +***************************/ +#define sind(a) (sinf((a) * Y_PI_DIV_180)) +#define cosd(a) (cosf((a) * Y_PI_DIV_180)) +#define tand(a) (tanf((a) * Y_PI_DIV_180)) + +/************************** + Functions +***************************/ +void GLCreateIdentityMatrix(float *m); +void GLMatrixMultiply(float *destination, float *matrix_a, float *matrix_b); +void GLCreatePerspectiveMatrix(float *m, float fov, float aspect, float znear, float zfar); +void GLCreateModelViewMatrix(float *m, float x, float y, float z, float yaw, float pitch, float roll=0.0f); + +/************************** + Quaternion class +***************************/ +class Quaternion +{ +public: + Quaternion(); + + void GenerateLocalRotation(float angle, float x_axis, float y_axis, float z_axis); + void CreateRotatedQuaternion(float *matrix); + void GenerateFromEuler(float roll, float pitch, float yaw); + + // Operators + inline const Quaternion operator+=(const Quaternion &q) {x += q.x; y += q.y; z += q.z; w += q.w; return *this;} + inline const Quaternion operator-=(const Quaternion &q) {x -= q.x; y -= q.y; z -= q.z; w -= q.w; return *this;} + const Quaternion operator *(Quaternion q); + +private: + float x; + float y; + float z; + float w; +}; +#endif //#ifndef _GL_UTILITY_H_ Modified: haiku/trunk/src/apps/3dmov/Jamfile =================================================================== --- haiku/trunk/src/apps/3dmov/Jamfile 2010-01-30 08:23:37 UTC (rev 35340) +++ haiku/trunk/src/apps/3dmov/Jamfile 2010-01-30 11:14:16 UTC (rev 35341) @@ -3,10 +3,14 @@ SetSubDirSupportedPlatformsBeOSCompatible ; Application 3DMov : - CubeView.cpp - GLMovApp.cpp - GLMovView.cpp - GLMovWindow.cpp - : be GL game $(TARGET_LIBSUPC++) + Application.cpp + MainWindow.cpp + ViewObject.cpp + Video.cpp + ViewBook.cpp + ViewCube.cpp + ViewSphere.cpp + GLUtility.cpp + : be GL game media translation $(TARGET_LIBSUPC++) : 3dmov.rdef ; Added: haiku/trunk/src/apps/3dmov/MainWindow.cpp =================================================================== --- haiku/trunk/src/apps/3dmov/MainWindow.cpp (rev 0) +++ haiku/trunk/src/apps/3dmov/MainWindow.cpp 2010-01-30 11:14:16 UTC (rev 35341) @@ -0,0 +1,248 @@ +/* PROJECT: 3Dmov + AUTHORS: Zenja Solaja + COPYRIGHT: 2009 Haiku Inc + DESCRIPTION: Haiku version of the famous BeInc demo 3Dmov. + + TODO: + There is a bug in Haiku which doesn't allow a 2nd BGLView to be created. + Originally I tried AddChild(new BGLView), however nothing would be drawn in the view. + On Zeta, both AddChild(new BGLView) and new MainWindow work without any problems. +*/ + +#include <InterfaceKit.h> +#include <GLView.h> +#include <Messenger.h> + +#include "MainWindow.h" +#include "ViewObject.h" +#include "ViewBook.h" +#include "ViewCube.h" +#include "ViewSphere.h" + +// Local definitions +static const float MENU_BAR_HEIGHT = 19; + +static const unsigned int MSG_FILE_OPEN = 'fopn'; +static const unsigned int MSG_ABOUT = 'info'; +static const unsigned int MSG_SHAPE_BOOK = 'spbk'; +static const unsigned int MSG_SHAPE_CUBE = 'spcb'; +static const unsigned int MSG_SHAPE_SPHERE = 'spsp'; +static const unsigned int MSG_OPTION_WIREFRAME = 'opwf'; +static const unsigned int MSG_FULLSCREEN = 'full'; + +static const char *ABOUT_TEXT = "\ +Drag and drop media files (pictures and videos) onto the 3D shapes. \ +Use your mouse to interact with the 3D shape.\n\ +Pick up your jaw from the floor.\n\n\ +Inspired by the original BeInc 3dmov demo.\n\ +Written by Zenja Solaja, 2009"; + + +// Local functions +static int32 animation_thread(void *cookie); + +// Local variables +static int sMainWindowCount = 0; // keep track of number of spawned windows + +/* FUNCTION: MainWindow :: MainWindow + ARGUMENTS: frame + shape + RETURN: n/a + DESCRIPTION: Constructor +*/ +MainWindow :: MainWindow(BRect frame, SHAPE shape) + : BDirectWindow(frame, "3Dmov", B_TITLED_WINDOW, 0) +{ + sMainWindowCount++; + + fOptionWireframe = false; + + // Add menu bar + frame.OffsetTo(B_ORIGIN); + BRect aRect = frame; + aRect.bottom = MENU_BAR_HEIGHT; + frame.top = MENU_BAR_HEIGHT; + SetupMenuBar(aRect); + + // Add book view + switch (shape) + { + case BOOK: AddChild(fCurrentView = new ViewBook(frame)); break; + case CUBE: AddChild(fCurrentView = new ViewCube(frame)); break; + case SPHERE: AddChild(fCurrentView = new ViewSphere(frame)); break; + } + + //AddShortcut('f', B_COMMAND_KEY, new BMessage(MSG_FULLSCREEN)); + + // Window should never be larger than 2048 + SetSizeLimits(40.0, 2047.0, 40.0, 2047.0); + Show(); + + fAnimationThreadID = spawn_thread(animation_thread, "Animation Thread", B_NORMAL_PRIORITY, fCurrentView); + resume_thread(fAnimationThreadID); +} + +/* FUNCTION: MainWindow :: ~MainWindow + ARGUMENTS: n/a + RETURN: n/a + DESCRIPTION: Destructor +*/ +MainWindow :: ~MainWindow() +{ + kill_thread(fAnimationThreadID); + RemoveChild(fCurrentView); + delete fCurrentView; + + sMainWindowCount--; + if (sMainWindowCount == 0) + be_app->PostMessage(B_QUIT_REQUESTED); +} + +/* FUNCTION: MainWindow :: SetupMenuBar + ARGUMENTS: frame + RETURN: n/a + DESCRIPTION: Initialise menu bar +*/ +void MainWindow :: SetupMenuBar(BRect frame) +{ + // File + BMenu *menu_file = new BMenu("File"); + //menu_file->AddItem(new BMenuItem("Open", new BMessage(MSG_FILE_OPEN), 'N')); + menu_file->AddItem(new BMenuItem("About", new BMessage(MSG_ABOUT))); + menu_file->AddItem(new BMenuItem("Exit", new BMessage(B_QUIT_REQUESTED))); + + // Shape + BMenu *menu_shape = new BMenu("Shape"); + menu_shape->AddItem(new BMenuItem("Book", new BMessage(MSG_SHAPE_BOOK), '1')); + menu_shape->AddItem(new BMenuItem("Cube", new BMessage(MSG_SHAPE_CUBE), '2')); + menu_shape->AddItem(new BMenuItem("Sphere", new BMessage(MSG_SHAPE_SPHERE), '3')); + + // Options + BMenu *menu_options = new BMenu("Options"); + menu_options->AddItem(new BMenuItem("Wireframe", new BMessage(MSG_OPTION_WIREFRAME), 'S')); + //menu_options->AddItem(new BMenuItem("Fullscreen", new BMessage(MSG_FULLSCREEN), 'F')); + + // Menu bar + fMenuBar = new BMenuBar(frame, "menubar"); + fMenuBar->AddItem(menu_file); + fMenuBar->AddItem(menu_shape); + fMenuBar->AddItem(menu_options); + AddChild(fMenuBar); +} + +/* FUNCTION: MainWindow :: MessageReceived + ARGUMENTS: message + RETURN: n/a + DESCRIPTION: Called by BeOS +*/ +void MainWindow :: MessageReceived(BMessage *message) +{ + switch (message->what) + { + case MSG_FULLSCREEN: + SetFullScreen(!IsFullScreen()); + break; + + case MSG_ABOUT: + { + BAlert *about = new BAlert("3Dmov", ABOUT_TEXT, "Wow"); + about->SetShortcut(0, B_ESCAPE); + about->Go(NULL); + break; + } + + /* TODO - Due to a bug when creating a 2nd BGLView in Haiku, I've decided to spawn a new window + instead of creating a new BGLView (and using AddChild(new_view) / RemoveChild(old_view). + Under Zeta, there is no problem replacing the current view with a new view. + */ + + case MSG_SHAPE_BOOK: + new MainWindow(BRect(50, 50, 400+50, 300+50), BOOK); + break; + + case MSG_SHAPE_CUBE: + new MainWindow(BRect(50, 50, 400+50, 300+50), CUBE); + break; + + case MSG_SHAPE_SPHERE: + new MainWindow(BRect(50, 50, 400+50, 300+50), SPHERE); + break; + + case MSG_OPTION_WIREFRAME: + fOptionWireframe = !fOptionWireframe; + fCurrentView->ToggleWireframe(fOptionWireframe); + break; + + case 'DATA': // user drag/dropped file from Tracker + { + BPoint point; + message->FindPoint("_drop_point_", &point); + BRect frame = Frame(); + point.x -= frame.left; + point.y -= frame.top; + + entry_ref aRef; + message->FindRef("refs", &aRef); + + fCurrentView->DragDrop(&aRef, point.x, point.y); + break; + } + + default: + BDirectWindow::MessageReceived(message); + break; + } +} + +/* FUNCTION: MainWindow :: QuitRequested + ARGUMENTS: none + RETURN: true if success + DESCRIPTION: Called when window closed +*/ +bool MainWindow :: QuitRequested() +{ + //be_app->PostMessage(B_QUIT_REQUESTED); + return true; +} + +/* FUNCTION: MainWindow :: DirectConnected + ARGUMENTS: info + RETURN: n/a + DESCRIPTION: Hook functions called when full screen mode toggled +*/ +void MainWindow :: DirectConnected(direct_buffer_info *info) +{ + switch (info->buffer_state & B_DIRECT_MODE_MASK) + { + // start a direct screen connection. + case B_DIRECT_START : + break; + // stop a direct screen connection. + case B_DIRECT_STOP : + break; + // modify the state of a direct screen connection. + case B_DIRECT_MODIFY : + break; + default : + break; + } +} + +/* FUNCTION: animation_thread + ARGUMENTS: cookie + RETURN: exit status + DESCRIPTION: Main rendering thread +*/ +#include <stdio.h> +static int32 animation_thread(void *cookie) +{ + ViewObject *view = (ViewObject *) cookie; + while (1) + { + view->Render(); + view->GLCheckError(); + snooze(1); + } + return B_OK; // keep compiler happy +} + Added: haiku/trunk/src/apps/3dmov/MainWindow.h =================================================================== --- haiku/trunk/src/apps/3dmov/MainWindow.h (rev 0) +++ haiku/trunk/src/apps/3dmov/MainWindow.h 2010-01-30 11:14:16 UTC (rev 35341) @@ -0,0 +1,46 @@ +/* PROJECT: 3Dmov + AUTHORS: Zenja Solaja + COPYRIGHT: 2009 Haiku Inc + DESCRIPTION: Haiku version of the famous BeInc demo 3Dmov + Just drag'n'drop media files to the 3D objects +*/ + +#ifndef _MAIN_WINDOW_H_ +#define _MAIN_WINDOW_H_ + +#include "DirectWindow.h" + +class BMenuBar; +class ViewObject; + +/************************************ + Main application window +*************************************/ +class MainWindow : public BDirectWindow +{ +public: + enum SHAPE + { + BOOK, + CUBE, + SPHERE, + NUMBER_OF_SHAPES + }; + + MainWindow(BRect frame, SHAPE shape); + ~MainWindow(); + + void MessageReceived(BMessage *message); + void DirectConnected(direct_buffer_info *info); + bool QuitRequested(); + +private: + void SetupMenuBar(BRect frame); + + BMenuBar *fMenuBar; + bool fOptionWireframe; + int32 fAnimationThreadID; + ViewObject *fCurrentView; +}; + +#endif Added: haiku/trunk/src/apps/3dmov/Video.cpp =================================================================== --- haiku/trunk/src/apps/3dmov/Video.cpp (rev 0) +++ haiku/trunk/src/apps/3dmov/Video.cpp 2010-01-30 11:14:16 UTC (rev 35341) @@ -0,0 +1,208 @@ +/* PROJECT: 3Dmov + AUTHORS: Zenja Solaja + COPYRIGHT: 2009 Haiku Inc + DESCRIPTION: Haiku version of the famous BeInc demo 3Dmov + This file handles video playback for ViewObject base class. +*/ + +#include <stdio.h> +#include <Bitmap.h> +#include <Screen.h> + +#include "ViewObject.h" +#include "Video.h" + +/* FUNCTION: Video :: Video + ARGUMENTS: ref + RETURN: n/a + DESCRIPTION: Constructor +*/ +Video :: Video(entry_ref *ref) +{ + fMediaFile = 0; + fVideoTrack = 0; + fBitmap = 0; + fVideoThread = 0; + + fMediaFile = new BMediaFile(ref, B_MEDIA_FILE_BIG_BUFFERS); + fStatus = fMediaFile->InitCheck(); + if (fStatus != B_OK) + return; + + int32 num_tracks = fMediaFile->CountTracks(); + for (int32 i=0; i < num_tracks; i++) + { + BMediaTrack *track = fMediaFile->TrackAt(i); + if (track == NULL) + { + fMediaFile->ReleaseAllTracks(); + printf("Media file claims to have %ld tracks, cannot find track %ld\n", num_tracks, i); + fVideoTrack = 0; + return; + } + + media_format mf; + fStatus = track->EncodedFormat(&mf); + if (fStatus == B_OK) + { + switch (mf.type) + { + case B_MEDIA_ENCODED_VIDEO: + case B_MEDIA_RAW_VIDEO: + if (fVideoTrack == 0) + { + fVideoTrack = track; + InitPlayer(&mf); + } + else + printf("Multiple video tracks not supported\n"); + break; + default: + fStatus = B_ERROR; + } + } + + if (fStatus != B_OK) + fMediaFile->ReleaseTrack(track); + } + + if (fVideoTrack) + fStatus = B_OK; +} + +/* FUNCTION: Video :: ~Video + ARGUMENTS: n/a + RETURN: n/a + DESCRIPTION: Destructor +*/ +Video :: ~Video() +{ + if (fVideoThread > 0) + kill_thread(fVideoThread); + delete fMediaFile; + delete fBitmap; +} + +/* FUNCTION: Video :: InitPlayer + ARGUMENTS: format + RETURN: n/a + DESCRIPTION: Create frame buffer and init decoder +*/ +void Video :: InitPlayer(media_format *format) +{ + BRect frame(0, 0, + format->u.encoded_video.output.display.line_width - 1.0f, + format->u.encoded_video.output.display.line_count - 1.0f); + + BScreen screen; + color_space cs = screen.ColorSpace(); + + // Loop asking the track for a format we can deal with + for (;;) + { + fBitmap = new BBitmap(frame, cs); + + media_format mf, old_mf; + memset(&mf, 0, sizeof(media_format)); + media_raw_video_format *rvf = &mf.u.raw_video; + rvf->last_active = (uint32)(frame.Height() - 1.0f); + rvf->orientation = B_VIDEO_TOP_LEFT_RIGHT; + rvf->pixel_width_aspect = 1; + rvf->pixel_height_aspect = 3; + rvf->display.format = cs; + rvf->display.line_width = (int32)frame.Width(); + rvf->display.line_count = (int32)frame.Height(); + rvf->display.bytes_per_row = fBitmap->BytesPerRow(); + + old_mf = mf; + fVideoTrack->DecodedFormat(&mf); + // check if match found + if (old_mf.u.raw_video.display.format == mf.u.raw_video.display.format) + break; + + // otherwise, change colour space + cs = mf.u.raw_video.display.format; + delete fBitmap; + } + + media_header mh; + fVideoTrack->SeekToTime(0); + int64 dummy_num_frames; + fVideoTrack->ReadFrames((char *)fBitmap->Bits(), &dummy_num_frames, &mh); + fVideoTrack->SeekToTime(0); +} + +/* FUNCTION: Video :: Start + ARGUMENTS: none + RETURN: n/a + DESCRIPTION: Start playing video +*/ +void Video :: Start() +{ + fVideoThread = spawn_thread(Video::VideoThread, "Video thread", B_NORMAL_PRIORITY, this); + if (fVideoThread > 0) + resume_thread(fVideoThread); +} + +/* FUNCTION: Video :: ShowNextFrame + ARGUMENTS: none + RETURN: status + DESCRIPTION: Read next frame, update texture +*/ +status_t Video :: ShowNextFrame() +{ + status_t err; + media_header mh; + int64 dummy = 0; + + fBitmap->LockBits(); + err = fVideoTrack->ReadFrames((char *)fBitmap->Bits(), &dummy, &mh); + fBitmap->UnlockBits(); + + if (err != B_OK) + { + // restart video + fVideoTrack->SeekToTime(0); + return B_OK; + } + + fMediaSource->mOwner->UpdateFrame(fMediaSource); + return B_OK; +} + +/* FUNCTION: Video :: VideoThread + ARGUMENTS: cookie + RETURN: thread exit status + DESCRIPTION: Video playback thread +*/ +int32 Video :: VideoThread(void *cookie) +{ + Video *video = (Video *) cookie; + if (video->fVideoTrack == NULL) + { + exit_thread(B_ERROR); + return B_ERROR; + } + + float frames_per_second = (float)video->fVideoTrack->CountFrames() / (float)video->fVideoTrack->Duration() * 1000000.0f; + bigtime_t frame_time = (bigtime_t) (1000000.0f / frames_per_second); + video->fPerformanceTime = real_time_clock_usecs() + frame_time; + status_t err = B_OK; + printf("frame_rate = %f\n", frames_per_second); + + while (1) + { + err = video->ShowNextFrame(); + bigtime_t zzz = video->fPerformanceTime - real_time_clock_usecs(); + if (zzz < 0) + zzz = 1; + video->fPerformanceTime += frame_time; + snooze(zzz); + } + exit_thread(err); + return err; +} + + + + \ No newline at end of file Added: haiku/trunk/src/apps/3dmov/Video.h =================================================================== --- haiku/trunk/src/apps/3dmov/Video.h (rev 0) +++ haiku/trunk/src/apps/3dmov/Video.h 2010-01-30 11:14:16 UTC (rev 35341) @@ -0,0 +1,45 @@ +/* PROJECT: 3Dmov + AUTHORS: Zenja Solaja + COPYRIGHT: 2009 Haiku Inc + DESCRIPTION: Haiku version of the famous BeInc demo 3Dmov + Media playback support. +*/ + +#ifndef _VIDEO_H_ +#define _VIDEO_H_ + +#include <MediaKit.h> + +class BBitmap; +class MediaSource; + +/***************************** + Video class handles media playback +******************************/ +class Video [... truncated: 1879 lines follow ...]