1/*
2
3	ChartWindow.h
4
5	by Pierre Raynaud-Richard.
6
7*/
8
9/*
10	Copyright 1999, Be Incorporated.   All Rights Reserved.
11	This file may be used under the terms of the Be Sample Code License.
12*/
13
14#ifndef CHART_WINDOW_H
15#define CHART_WINDOW_H
16
17#include <DirectWindow.h>
18#include <OS.h>
19#include <Locker.h>
20#include <StringView.h>
21#include <PictureButton.h>
22
23#include "ChartRender.h"
24#include "ChartView.h"
25
26/* This window can be used in 3 modes : window mode is just a
27   normal window (that you move and resize freely), fullscreen
28   resize the window to adjust its content area to the full
29   size of the screen. Demo mode resize the window to have the
30   animate part of it fit the full screen. */
31enum {
32	WINDOW_MODE		= 0,
33	FULLSCREEN_MODE	= 1,
34	FULLDEMO_MODE	= 2
35};
36
37/* Special animation mode. Comet create 2 comets flying around
38   randomaly. Novas add a couple start with flashing burst of
39   light. Battle was never implemented... */
40enum {
41	SPECIAL_NONE	= 0,
42	SPECIAL_COMET	= 1,
43	SPECIAL_NOVAS	= 2,
44	SPECIAL_BATTLE	= 3
45};
46
47/* Three types of display mode : line is supposed to use line
48   array to draw pixel (but is not currently implemented). Bitmap
49   use an offscreen BBitmap and DrawBitmap for each frame. Direct
50   use the DirectWindow API to draw directly on the screen. */
51enum {
52	DISPLAY_OFF		= 0,
53	DISPLAY_LINE	= 1,
54	DISPLAY_BITMAP	= 2,
55	DISPLAY_DIRECT	= 3
56};
57
58/* Five ways of moving the camera around : not at all, simple
59   rotation around the center of the starfield, slow straight
60   move, fast straight move, and a random move (flying around). */
61enum {
62	ANIMATION_OFF		= 0,
63	ANIMATION_ROTATE	= 1,
64	ANIMATION_SLOW_MOVE	= 2,
65	ANIMATION_FAST_MOVE = 3,
66	ANIMATION_FREE_MOVE = 4
67};
68
69/* Three types of star field. A new random starfield is created
70   everytime you change the starfield type. The first will just
71   put stars randomly in space. The second will concentrate
72   star in 10 places. The last one will put half the star in a
73   big spiral galaxy, and the other one in a few amas. */
74enum {
75	SPACE_CHAOS		= 0,
76	SPACE_AMAS		= 1,
77	SPACE_SPIRAL	= 2
78};
79
80/* All messages exchanged between the UI and the engine. */
81enum {
82	ANIM_OFF_MSG		= 1000,
83	ANIM_SLOW_ROT_MSG	= 1001,
84	ANIM_SLOW_MOVE_MSG	= 1002,
85	ANIM_FAST_MOVE_MSG	= 1003,
86	ANIM_FREE_MOVE_MSG	= 1004,
87	DISP_OFF_MSG		= 2000,
88	DISP_LINE_MSG		= 2001,
89	DISP_BITMAP_MSG		= 2002,
90	DISP_DIRECT_MSG		= 2003,
91	OPEN_COLOR_MSG		= 3000,
92	OPEN_DENSITY_MSG	= 3100,
93	OPEN_REFRESH_MSG	= 3200,
94	SPACE_CHAOS_MSG		= 3300,
95	SPACE_AMAS_MSG		= 3301,
96	SPACE_SPIRAL_MSG	= 3302,
97	FULL_SCREEN_MSG		= 4000,
98	AUTO_DEMO_MSG		= 4100,
99	BACK_DEMO_MSG		= 4101,
100	SECOND_THREAD_MSG	= 4200,
101	COLORS_RED_MSG		= 5000,
102	COLORS_GREEN_MSG	= 5001,
103	COLORS_BLUE_MSG		= 5002,
104	COLORS_YELLOW_MSG	= 5003,
105	COLORS_ORANGE_MSG	= 5004,
106	COLORS_PINK_MSG		= 5005,
107	COLORS_WHITE_MSG	= 5006,
108	SPECIAL_NONE_MSG	= 6000,
109	SPECIAL_COMET_MSG	= 6001,
110	SPECIAL_NOVAS_MSG	= 6002,
111	SPECIAL_BATTLE_MSG	= 6003,
112	COLOR_PALETTE_MSG	= 7000,
113	STAR_DENSITY_MSG	= 8000,
114	REFRESH_RATE_MSG	= 9000
115};
116
117enum {
118	/* Number of star used to generate the special animation */
119	SPECIAL_COUNT_MAX	= 512,
120	/* Number of keypoint used for the "random" animation */
121	KEY_POINT_MAX		= 16
122};
123
124/* Basic 3D point/vector class, used for basic vectorial
125   operations. */
126class TPoint {
127public:
128	float   	x;
129	float   	y;
130	float   	z;
131
132	TPoint		operator* (const float k) const;
133	TPoint		operator- (const TPoint& v2) const;
134	TPoint		operator+ (const TPoint& v2) const;
135	TPoint		operator^ (const TPoint& v2) const;
136	float		Length() const;
137};
138
139/* Basic 3x3 matrix used for 3D transform. */
140class TMatrix {
141public:
142	float 		m[3][3];
143
144	TPoint		operator* (const TPoint& v) const;
145	TPoint		Axis(int32 index);
146	TMatrix		Transpose() const;
147	void		Set(const float alpha, const float theta, const float phi);
148};
149
150
151class BBox;
152class BView;
153
154/* The main window class, encapsulating both UI and engine. */
155class ChartWindow : public BDirectWindow {
156public:
157		/* standard constructor and destructor */
158				ChartWindow(BRect frame, const char *name);
159virtual			~ChartWindow();
160
161		/* standard window members */
162virtual	bool	QuitRequested();
163virtual	void	MessageReceived(BMessage *message);
164virtual void	ScreenChanged(BRect screen_size, color_space depth);
165virtual	void	FrameResized(float new_width, float new_height);
166
167		/* this struct embedded all user settable parameters that
168		   can be set by the UI. The idea is to solve all possible
169		   synchronisation problem between the UI settings and the
170		   engine (when using DirectWindow mode) by defining a
171		   current setting state and a next setting state. The UI
172		   touches only the next setting state, never the one
173		   currently use by the engine. This way the engine doesn't
174		   have to be synchronised with the UI. */
175		struct setting {
176			/* do we want to use the second thread ? */
177			bool		second_thread;
178			/* which ones of the 7 star colors are we using ? */
179			bool		colors[7];
180			/* what window configuration mode are we using ? */
181			int32		fullscreen_mode;
182			/* what special mode are we using ? */
183			int32		special;
184			/* what display mode are we using ? */
185			int32		display;
186			/* what starfield model are we using ? */
187			int32		space_model;
188			/* what camera animation are we using ? */
189			int32		animation;
190			/* what is the density of the current starfield
191			   model ? */
192			int32		star_density;
193			/* what's the current required refresh rate ? */
194			float		refresh_rate;
195			/* what's the current background color for the animated
196			   view ? */
197			rgb_color	back_color;
198			/* what's the current color_space of the screen ? */
199			color_space	depth;
200			/* what's the current dimension of the content area of
201			   the window ? */
202			int32		width, height;
203
204			/* used to copy a whole setting in another. */
205			void		Set(setting *master);
206		};
207
208		/* this union is used to store special animation information
209		   that are defined per star. */
210		typedef union {
211			/* for the comet, it's a speed vector and to
212			   counters to define how long the star will
213			   continue before disappearing. */
214			struct {
215				float		dx;
216				float		dy;
217				float		dz;
218				int32		count;
219				int32		count0;
220			} comet;
221			/* for the novas, just counters to define the
222			   pulse cycle of the star. */
223			struct {
224				float		count;
225				int32		count0;
226			} nova;
227			/* battle was not implemented. */
228			struct {
229				int32		count;
230			} battle;
231		} special;
232
233	/* public instance members */
234		/* the current instantenuous potential frame/rate
235		   as display by the vue-meter. */
236		int32			fInstantLoadLevel;
237		/* the offscreen Bitmap used, if any. */
238		BBitmap			*fOffscreen;
239		/* the current active setting used by the engine */
240		setting			fCurrentSettings;
241
242
243
244/* the private stuff... */
245private:
246	/* User Interface related stuff. */
247		BBox		*fStatusBox;
248		BBox		*fColorsBox;
249		BBox		*fSpecialBox;
250
251		BView		*fLeftView;
252		BView		*fTopView;
253
254		/* Find a window by its name if already opened. */
255static	BWindow		*GetAppWindow(const char *name);
256		/* Used to set the content of PictureButton. */
257		BPicture	*ButtonPicture(bool active, int32 button_type);
258		/* Those function create and handle the other settings
259		   floating windows, for the background color, the star
260		   density and the refresh rate. */
261		void		OpenColorPalette(BPoint here);
262		void		OpenStarDensity(BPoint here);
263		void		OpenRefresh(BPoint here);
264		/* Draw the state of the instant-load vue-meter */
265		void		DrawInstantLoad(float frame_per_second);
266		/* Print the performances numbers, based on the real framerate. */
267		void		PrintStatNumbers(float fps);
268
269	/* Engine setting related functions. */
270		/* Init the geometry engine of the camera at startup. */
271		void		InitGeometry();
272		/* Check and apply changes between a new setting state
273		   and the currently used one. */
274		void		ChangeSetting(setting new_set);
275		/* Initialise a new starfield of the specified model. */
276		void		InitStars(int32 model);
277		/* Fill a star list with random stars in [0-1]x[0-1]x[0-1]. */
278		void		FillStarList(star *list, int32 count);
279		/* Init a new special animation of a specific type. */
280		void		InitSpecials(int32 code);
281		/* Change the star field colors depending a new set of
282		   selected colors. */
283		void		SetStarColors(int32	*color_list, int32 color_count);
284		/* Change the global geometry of the camera when the
285		   viewing area is resized. */
286		void		SetGeometry(int32 dh, int32 dv);
287		/* Change the color_space configuration of a buffer */
288		void		SetColorSpace(buffer *buf, color_space depth);
289		/* Used to sync the pre-offset matrix pointer whenever the buffer
290		   bits pointer changes. */
291		void		SetPatternBits(buffer *buf);
292
293	/* Engine processing related functions. */
294		/* those functions are the two processing threads launcher */
295static	int32		Animation(void *data);
296static	int32		Animation2(void *data);
297		/* After every camera move or rotation, reprocess the torus
298		   cycle of the starfield to maintain the pyramid of vision
299		   of the camera completly inside a 1x1x1 iteration of the
300		   starfield. */
301		void		SetCubeOffset();
302		/* Process the camera animation for a specified time step */
303		void		CameraAnimation(float time_factor);
304		/* Used by the random move camera animation. */
305		void		SelectNewTarget();
306		void		FollowTarget();
307		/* Process the special animation for a specified time step */
308		void		AnimSpecials(float time_step);
309		/* Sync the embedded camera state with the window class camera
310		   state (before calling the embedded C-engine in ChartRender.c */
311		void		SyncGeo();
312		/* Control the star processing (done by 1 or 2 threads) and
313		   executed by the embedded C-engine in ChartRender.c */
314		void		RefreshStars(buffer *buf, float time_step);
315
316	/* Offscreen bitmap configuration related functions. */
317		/* Used to update the state of the offscreen Bitmap to stay
318		   in sync with the current settings. */
319		void		CheckBitmap(color_space depth, int32 width, int32 height);
320		/* Set the basic clipping of the offscreen Bitmap (everything
321		   visible) */
322		void		SetBitmapClipping(int32 width, int32 height);
323		/* Draw the offscreen bitmap background. */
324		void		SetBitmapBackGround();
325
326	/* DirectWindow related functions */
327		/* Process a change of state in the direct access to the
328		   frame buffer. */
329		void		SwitchContext(direct_buffer_info *info);
330public:
331		/* this is the hook controling direct screen connection */
332virtual void		DirectConnected(direct_buffer_info *info);
333
334
335private:
336	/* Pseudo-random generator state and increment function. */
337		int32		fCrcAlea;
338inline	void		CrcStep();
339
340
341	/* Various private instance variables. */
342		/* the next setting, as modified by the UI */
343		setting			fNextSettings;
344
345
346		/* the buffer descriptors for the offscreen bitmap and
347		   the DirectWindow buffer. */
348		buffer			fBitmapBuffer;
349		buffer			fDirectBuffer;
350
351		/* current maximal dimensions of the offscreen Bitmap buffer */
352		int32			fMaxWidth, fMaxHeight;
353
354		/* memorize previous state for switch between fullscreen
355		   and window mode */
356		BRect			fPreviousFrame;
357		int32			fPreviousFullscreenMode;
358
359		/* cycling threshold for the cubic torus starfield, that
360		   guarantees that the 1x1x1 sample will contain the full
361		   pyramid of vision. */
362		TPoint			fCut;
363
364		/* maximal depth of the pyramid of vision */
365		float			fDepthRef;
366
367		int32			fBackColorIndex;
368
369		/* target frame duration, in microsecond. */
370		bigtime_t		fFrameDelay;
371
372		/* various UI object that we need to reach directly. */
373		BButton			*fOffwindowButton;
374		ChartView		*fChartView;
375		BStringView		*fCpuLoadView, *fFramesView;
376		InstantView		*fInstantLoad;
377		BPictureButton	*fColorButton, *fDensityButton, *fRefreshButton;
378
379		/* states used to describe the camera position, rotation
380		   and dynamic (in other case than free move). */
381		float			fCameraAlpha, fCameraTheta, fCameraPhi;
382		float			fDynamicAlpha;
383		float			fDynamicTheta;
384		float			fDynamicPhi;
385		int32			fCountAlpha, fCountTheta, fCountPhi;
386		TPoint			fOrigin;
387		TMatrix			fCamera;
388		TMatrix			fCameraInvert;
389
390		/* the camera geometry descriptor required by the embedded
391		   C-engine (just a copy of part of the previous states) */
392		geometry		fGeometry;
393
394		/* states used by the free move camera animation */
395		int32			fTrackingTarget;
396		int32			fKeyPointCount;
397		float			fSpeed, fTargetSpeed;
398		float			fLastDynamicDelay;
399		TPoint			fKeyPoints[KEY_POINT_MAX];
400
401		/* main starfield. */
402		star_packet		fStars;
403
404		/* used for the special animation */
405		TPoint			fComet[2];
406		TPoint			fDeltaComet[2];
407		special			*fSpecialList;
408		star_packet		fSpecials;
409
410		/* the two processing threads. */
411		thread_id		fAnimationThread;
412		thread_id		fSecondAnimationThread;
413
414		/* context of the second processing thread (when used). */
415		float			fSecondThreadThreshold;
416		buffer			*fSecondThreadBuffer;
417		sem_id			fSecondThreadLock;
418		sem_id			fSecondThreadRelease;
419		bigtime_t			fSecondThreadDelay;
420		star_packet		fStars2;
421		star_packet		fSpecials2;
422
423		/* Flag used to terminate the processing threads */
424		bool			fKillThread;
425
426		/* Direct connection status */
427		bool			fDirectConnected;
428
429		/* used to synchronise the star animation drawing. */
430		sem_id			fDrawingLock;
431};
432
433#endif
434