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 <assert.h>
10
11#include <Bitmap.h>
12#include <TranslationUtils.h>
13
14#include "GLUtility.h"
15#include "ViewSphere.h"
16
17//	Local definitions
18
19// 	Local functions
20
21//	Local variables
22
23/********************************
24	Sphere scene
25*********************************/
26class Sphere
27{
28public:
29			Sphere(const float radius, const int stacks = 10, const int slices = 10);
30			~Sphere();
31	void	Render();
32	void	SetMediaSource(MediaSource *source) {fMediaSource = source;}
33	void	SetAngle(float angle_y, float angle_z);
34
35private:
36	MediaSource		*fMediaSource;
37	int				fNumberVertices;
38	float			*fGeometry;
39	float			*fTextureCoords;
40	float			fRotationY, fRotationZ;
41};
42
43/*	FUNCTION:		Sphere :: Sphere
44	ARGUMENTS:		radius
45					stacks		vertical stacks
46					slices		horizontal slices
47	RETURN:			n/a
48	DESCRIPTION:	Constructor
49*/
50Sphere :: Sphere(const float radius, const int stacks, const int slices)
51{
52	fGeometry = 0;
53	fTextureCoords = 0;
54	fMediaSource = 0;
55	fRotationY = 0;
56	fRotationZ = 0;
57
58	fNumberVertices = 2*stacks*(slices+1);
59	fGeometry = new float [fNumberVertices*3];
60	fTextureCoords = new float [fNumberVertices*2];
61
62	float *v = fGeometry;
63	float *t = fTextureCoords;
64
65	float z0, z1, r0, r1;
66	float x, y, z;
67	//YVector3 normal;	 // not used in 3Dmov, but useful to know
68
69	for (int i=0; i < stacks; i++)
70	{
71		z0 = (float)i/(float)stacks;
72		z1 = (float)(i+1)/(float)stacks;
73		r0 = radius * sind(180 * (float)i/(float)stacks);
74		r1 = radius * sind(180 * (float)(i+1)/(float)stacks);
75
76		for (int j=0; j < (slices + 1); j++)
77		{
78			x = sind(360.0f * (float)j/(float)slices);
79			y = cosd(360.0f * (float)j/(float)slices);
80			z = radius * cosd(180*z0);
81
82			//	Vertices
83			*v++ = x * r0;
84			*v++ = -y * r0;
85			*v++ = z;
86			//	Normal not used in 3Dmov, but if you ever need it
87			//normal.Set(x*r0, -y*r0, z);
88			//normal.Normalise();
89			//	Textures
90			*t++ = (float)j/(float)slices;
91			*t++ = z0;
92
93			z = radius * cosd(180*z1);
94			//	Vertices
95			*v++ = x * r1;
96			*v++ = -y * r1;
97			*v++ = z;
98			//	Normals not used in 3Dmov, but if you ever need it
99			//normal.Set(x*r1, -y*r1, z);
100			//normal.Normalise();
101			//	Textures
102			*t++ = (float)j/(float)slices;
103			*t++ = z1;
104		}
105	}
106}
107
108/*	FUNCTION:		Sphere :: ~Sphere
109	ARGUMENTS:		n/a
110	RETURN:			n/a
111	DESCRIPTION:	Destructor.  fMediaSource destroyed by ViewSphere
112*/
113Sphere :: ~Sphere()
114{
115	delete [] fGeometry;
116	delete [] fTextureCoords;
117}
118
119/*	FUNCTION:		Sphere :: SetAngle
120	ARGUMENTS:		angle_y
121					angle_z
122	RETURN:			n/a
123	DESCRIPTION:	Rotate sphere by Euler angles
124*/
125void Sphere :: SetAngle(float angle_y, float angle_z)
126{
127	fRotationY = angle_y;
128	fRotationZ = angle_z;
129}
130
131/*	FUNCTION:		Sphere :: Render
132	ARGUMENTS:		none
133	RETURN:			n/a
134	DESCRIPTION:	Draw sphere
135*/
136void Sphere :: Render()
137{
138	glColor4f(1,1,1,1);
139	glBindTexture(GL_TEXTURE_2D, fMediaSource->mTextureID);
140
141	glPushMatrix();
142	glRotatef(-30, 1, 0, 0);
143	glRotatef(fRotationY, 0, 1, 0);
144	glRotatef(fRotationZ, 0, 0, 1);
145	glTexCoordPointer(2, GL_FLOAT, 0, fTextureCoords);
146	glVertexPointer(3, GL_FLOAT, 0, fGeometry);
147	glDrawArrays(GL_TRIANGLE_STRIP, 0, fNumberVertices);
148	glPopMatrix();
149}
150
151/********************************
152	ViewSphere
153*********************************/
154
155/*	FUNCTION:		ViewSphere :: ViewSphere
156	ARGUMENTS:		frame
157	RETURN:			n/a
158	DESCRIPTION:	Constructor
159*/
160ViewSphere :: ViewSphere(BRect frame)
161	: ViewObject(frame)
162{
163	fStartTime = real_time_clock_usecs();
164	fSphere = 0;
165	fMediaSource = 0;
166	fSpeedZ = 10.0f;
167	fSpeedY = 0.0f;
168	fAngleY = 0;
169	fAngleZ = 0;
170}
171
172/*	FUNCTION:		ViewSphere :: ~ViewSphere
173	ARGUMENTS:		n/a
174	RETURN:			n/a
175	DESCRIPTION:	Destructor
176*/
177ViewSphere :: ~ViewSphere()
178{
179	delete fSphere;
180	if (fMediaSource != GetDefaultMediaSource())
181		delete fMediaSource;
182}
183
184/*	FUNCTION:		ViewSphere :: AttachedToWindow
185	ARGUMENTS:		none
186	RETURN:			n/a
187	DESCRIPTION:	Hook function called when view attached to window (looper)
188*/
189void ViewSphere :: AttachedToWindow(void)
190{
191	ViewObject::AttachedToWindow();
192
193	LockGL();
194	glClearColor(0,0,0,1);
195
196	fSphere = new Sphere(0.1f, 10, 10);
197	fMediaSource = GetDefaultMediaSource();
198	fSphere->SetMediaSource(fMediaSource);
199
200	UnlockGL();
201}
202
203/*	FUNCTION:		ViewSphere :: Render
204	ARGUMENTS:		none
205	RETURN:			n/a
206	DESCRIPTION:	Draw view contents
207*/
208void ViewSphere :: Render(void)
209{
210	LockGL();
211
212	bigtime_t	current_time = real_time_clock_usecs();
213	bigtime_t	delta = current_time - fStartTime;
214	fStartTime = current_time;
215
216	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
217
218	fAngleY += fSpeedY*(float)delta/1000000.0f;
219	fAngleZ += fSpeedZ*(float)delta/1000000.0f;
220	fSphere->SetAngle(fAngleY, fAngleZ);
221
222	glPushMatrix();
223	glTranslatef(0.0f, 0.0f, 0.15f);
224	fSphere->Render();
225	glPopMatrix();
226
227	glFlush();
228	SwapBuffers();
229
230	//	Display frame rate
231	/*
232	static int fps = 0;
233	static int time_delta = 0;
234	fps++;
235	time_delta += delta;
236	if (time_delta > 1000000)
237	{
238		printf("%d fps\n", fps);
239		fps = 0;
240		time_delta = 0;
241	}
242	*/
243	UnlockGL();
244}
245
246/*	FUNCTION:		ViewSphere :: MouseDown
247	ARGUMENTS:		p
248	RETURN:			n/a
249	DESCRIPTION:	Hook function called when mouse down detected
250*/
251void ViewSphere :: MouseDown(BPoint p)
252{
253	//	Determine mouse button
254	BMessage* msg = Window()->CurrentMessage();
255	uint32 buttons;
256
257	msg->FindInt32("buttons", (int32*)&buttons);
258
259	if (buttons & B_PRIMARY_MOUSE_BUTTON)
260	{
261		SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY);
262		fMouseTracking = true;
263		fMousePosition = p;
264	}
265}
266
267/*	FUNCTION:		ViewSphere :: MouseMoved
268	ARGUMENTS:		p
269					transit
270					message
271	RETURN:			n/a
272	DESCRIPTION:	Hook function called when mouse move detected.
273					This demo is succeptable to Gimbal lock, but it doesn't really matter.
274*/
275void ViewSphere :: MouseMoved(BPoint p, uint32 transit, const BMessage *message)
276{
277	if (fMouseTracking)
278	{
279		if (transit == B_INSIDE_VIEW)
280		{
281			fSpeedY = 5*(p.y - fMousePosition.y);
282			fSpeedZ = 5*(p.x - fMousePosition.x);
283			fMousePosition = p;
284		}
285	}
286}
287
288/*	FUNCTION:		ViewSphere :: MouseUp
289	ARGUMENTS:		p
290	RETURN:			n/a
291	DESCRIPTION:	Hook function called when mouse up detected
292*/
293void ViewSphere :: MouseUp(BPoint p)
294{
295	fMouseTracking = false;
296}
297
298/*	FUNCTION:		ViewSphere :: DragDropImage
299	ARGUMENTS:		texture_id
300					mouse_x
301					mouse_y
302	RETURN:			true if source ownership acquired
303	DESCRIPTION:	Hook function called when user drags/drops image to app window
304*/
305bool ViewSphere :: SurfaceUpdate(MediaSource *source, float mouse_x, float mouse_y)
306{
307	LockGL();
308
309	if (fMediaSource != GetDefaultMediaSource())
310		delete fMediaSource;
311	fMediaSource = source;
312	fSphere->SetMediaSource(source);
313
314	UnlockGL();
315
316	return true;
317
318}
319
320
321
322
323