1 #include <stdio.h>
2 
3 #include "G-Force_Proj.h"
4 
5 #include "WaveShape.h"
6 
7 #include <math.h>
8 #include <stdlib.h>
9 #include <time.h>
10 
11 #include "ArgList.h"
12 #include "UtilStr.h"
13 #include "EgOSUtils.h"
14 #include "PixPort.h"
15 
16 
17 long		WaveShape::sXY[ 2 * MAX_WAVES_PER_SHAPE ];
18 long		WaveShape::sStartXY[ 2 * MAX_WAVES_PER_SHAPE ];
19 float		WaveShape::sS;
20 
21 
WaveShape(float * inTPtr)22 WaveShape::WaveShape( float* inTPtr ) {
23 	UtilStr str;
24 
25 	mNumWaves = 0;
26 	mMouseX = 0;
27 	mMouseY = 0;
28 
29 	mNumFFTBins = 255;
30 
31 	mDict.AddVar( "S", &sS );
32 	mDict.AddVar( "T", inTPtr );
33 	mDict.AddVar( "NUM_SAMPLE_BINS", &mNumSampleBins );
34 	// FIXME, use fft here!
35 	mDict.AddVar( "NUM_FFT_BINS", &mNumFFTBins );
36 	mDict.AddVar( "MOUSEX", &mMouseX );
37 	mDict.AddVar( "MOUSEY", &mMouseY );
38 
39 	mTPtr = inTPtr;
40 	mPI = 3.14159265358979;
41 
42 	mDict.AddVar( "PI", &mPI );
43 }
44 
45 
46 
SetMagFcn(ExprUserFcn ** inMagFcn)47 void WaveShape::SetMagFcn( ExprUserFcn** inMagFcn ) {
48 
49 	mDict.AddFcn( "MAG", inMagFcn );
50 }
51 
SetFFTFcn(ExprUserFcn ** inFFTFcn)52 void WaveShape::SetFFTFcn( ExprUserFcn** inFFTFcn ) {
53 
54 	mDict.AddFcn( "FFT", inFFTFcn );
55 }
56 #define _assignOrig( field )  field##Orig = field;
57 
58 
59 
Load(ArgList & inArgs,long inDefaultNumSteps)60 void WaveShape::Load( ArgList& inArgs, long inDefaultNumSteps ) {
61 	UtilStr str;
62 
63 	// Mix up the rnd seed
64 	srand( clock() );
65 
66 	// Calculate mNumSampleBins -- How many pieces we chop the 0-1 s interval into
67 	inArgs.GetArg( 'Stps', str );
68 
69 	mNum_S_Steps.Compile( str, mDict );
70 	CalcNumS_Steps( 0, inDefaultNumSteps );
71 
72 	// Compile and link all the temp exprs.  By their spec, A vars can be evaluated now
73 	mA.Compile( inArgs, 'A', mDict );
74 	mA.Evaluate();
75 	mB.Compile( inArgs, 'B', mDict );
76 	mC.Compile( inArgs, 'C', mDict );
77 
78 	// The intensity fcn allows drawing of arbitrary intensity
79 	if ( ! inArgs.GetArg( 'Pen', str ) )
80 		str.Assign( "1" );
81 	mIntensity.Compile( str, mDict );
82 
83 	// If a user doesn't enter a line widh for a wave, assume width 1
84 	if ( ! inArgs.GetArg( 'LWdt', str ) )
85 		str.Assign( "1" );
86 	mLineWidth.Compile( str, mDict );
87 
88 	mPen_Dep_S			= mIntensity.IsDependent( "s" ) || mIntensity.IsDependent( "c" ) || mIntensity.IsDependent( "rnd" );
89 	mLineWidth_Dep_S	= mLineWidth.IsDependent( "s" ) || mLineWidth.IsDependent( "c" ) || mLineWidth.IsDependent( "rnd" );
90 
91 	// Compile and link waves
92 	mWaveX.Compile( inArgs, 'X', mDict );
93 	mWaveY.Compile( inArgs, 'Y', mDict );
94 
95 	// Init all the wave shape var counters
96 	mNumWaves = mWaveX.Count();
97 
98 	mConnectBins		= inArgs.GetArg( 'ConB' );
99 	mConnectFirstLast	= inArgs.GetArg( 'ConB' ) > 1;
100 
101 	// Make copies/save original values (morph will write over the nonOrg vars)
102 	_assignOrig( mConnectBins )
103 	_assignOrig( mConnectFirstLast )
104 
105 	mAspect1to1 = inArgs.GetArg( 'Aspc' );
106 }
107 
108 
109 
110 /*
111 void WaveShape::SetSize( long inWidth, long inHeight ) {
112 
113 	mXScale = inWidth / 2;
114 	mYScale = inHeight / 2;
115 
116 	if ( mAspect1to1 ) {
117 
118 		// Keep the xy aspect ratio to 1, change the dim that will get stretched
119 		if ( mYScale < mXScale )
120 			mXScale = mYScale;
121 		else
122 			mYScale = mXScale;
123 	}
124 }
125 */
126 
127 
SetupTransition(WaveShape * inDest)128 void WaveShape::SetupTransition( WaveShape* inDest ) {
129 
130 	mIntensity.Weight( inDest -> mIntensity, &mShapeTrans, 0 );
131 	mLineWidth.Weight( inDest -> mLineWidth, &mShapeTrans, 0 );
132 
133 	mPen_Dep_S			= mPen_Dep_S || inDest -> mPen_Dep_S;
134 	mLineWidth_Dep_S	= mLineWidth_Dep_S|| inDest -> mLineWidth_Dep_S;
135 }
136 
137 
138 
139 #define __evalIntensity( var )		clr = 65535.0 * mIntensity.Evaluate() * inFader;	\
140 									var = clr;											\
141 									if ( clr < 0 )				var = 0;				\
142 									else if ( clr > 0xFFFF )	var = 0xFFFF;
143 
144 
145 
CalcNumS_Steps(WaveShape * inWave2,long inDefaultNumBins)146 void WaveShape::CalcNumS_Steps( WaveShape* inWave2, long inDefaultNumBins ) {
147 	int n;
148 
149 	// See if this shape has an overriding number of s steps
150 	mNumSampleBins = inDefaultNumBins;
151 	mNumSampleBins = mNum_S_Steps.Evaluate();
152 	if ( mNumSampleBins <= 0 )
153 		mNumSampleBins = inDefaultNumBins;
154 
155 
156 	if ( inWave2 ) {
157 		n = inWave2 -> mNum_S_Steps.Evaluate();
158 		if ( n <= 0 )
159 			n = inDefaultNumBins;
160 
161 		mNumSampleBins = ( 1 - mShapeTrans ) * n + mShapeTrans * mNumSampleBins;
162 	}
163 }
164 
165 
Draw(long inNumSteps,PixPort & inDest,float inFader,WaveShape * inWave2,float inMorphPct)166 void WaveShape::Draw( long inNumSteps, PixPort& inDest, float inFader, WaveShape* inWave2, float inMorphPct ) {
167 	long i, x, y;
168 	long xoff = inDest.GetX() >> 1;
169 	long yoff = inDest.GetY() >> 1;
170 	long maxWaves, w2Waves, clr;
171 	float dialate, tx, ty, stepSize;
172 	float xscale, yscale, xscaleW2, yscaleW2 ;
173 	RGBColor	rgb, rgbPrev, rgbStart;
174 
175 	// Calc the x and y scale factors
176 	xscale = xoff;
177 	yscale = yoff;
178 	if ( mAspect1to1 ) {
179 		if ( yscale < xscale )
180 			xscale = yscale;
181 		else
182 			yscale = xscale;
183 	}
184 
185 	// See if this shape has an overriding number of s steps
186 	CalcNumS_Steps( inWave2, inNumSteps );
187 
188 	// Setup default step size--inv of how many bins are available
189 	if ( mNumSampleBins > 1 )
190 		stepSize = 1.0 / ( mNumSampleBins - 1.0 );
191 	else
192 		stepSize = 1;
193 
194 	// If we're not in a transition/morph
195 	if ( ! inWave2 ) {
196 		dialate = 1;
197 		maxWaves = mNumWaves;
198 		w2Waves = 0;
199 	}
200 
201 	// If we're transitioning from one waveshape to another
202 	else {
203 		w2Waves = inWave2 -> mNumWaves;
204 		dialate = inMorphPct;
205 		mShapeTrans = pow( dialate, SHAPE_MORPH_ALPHA );
206 		SetupFrame( inWave2, mShapeTrans );
207 
208 		if ( mNumWaves > w2Waves ) {
209 			maxWaves = mNumWaves;
210 			dialate = 1.0 - dialate; }
211 		else
212 			maxWaves = w2Waves;
213 
214 		// Set the wave scale factor to the wave leaving/arriving
215 		dialate = 20.0 * pow( dialate, 4.0 ) + 1.0;
216 
217 		// Calc the x and y scale factors for wave 2
218 		xscaleW2 = xoff;
219 		yscaleW2 = yoff;
220 		if ( inWave2 -> mAspect1to1 ) {
221 			if ( yscaleW2 < xscaleW2 )
222 				xscaleW2 = yscaleW2;
223 			else
224 				yscaleW2 = xscaleW2;
225 		}
226 	}
227 
228 	// Setup/store the mouse position for possible virtual machine access
229 	Point mousePt;
230 	EgOSUtils::GetMouse( mousePt );
231 	mMouseX = ( (float) mousePt.h ) / xscale;
232 	mMouseY = ( (float) mousePt.v ) / yscale;
233 
234 	// Evaluate the expressions dependent on 't'/the current frame
235 	mB.Evaluate();
236 	if ( inWave2 )
237 		inWave2 -> mB.Evaluate();
238 
239 	// Calc linewidth, add a little to make .999 into 1.  If it's not dep on s, we can evaluate it now
240 	if ( ! mLineWidth_Dep_S )
241 		inDest.SetLineWidth( mLineWidth.Evaluate() + 0.001 );
242 
243 	// Calc pen intensity.  If it's not dep on s, we can evaluate it now.
244 	if ( ! mPen_Dep_S ) {
245 		__evalIntensity( rgb.red );
246 		rgbPrev = rgb;
247 	}
248 
249 	// Step thru s (the xy exprs will give us the cords)
250 	for ( sS = 0; sS <= 1.0; sS += stepSize ) {
251 
252 		// Evaluate the expressions dependent on 's'
253 		mC.Evaluate();
254 		if ( inWave2 )
255 			inWave2 -> mC.Evaluate();
256 
257 		// Calc linewidth, add a little to make .999 into 1.
258 		if ( mLineWidth_Dep_S )
259 			inDest.SetLineWidth( mLineWidth.Evaluate() + 0.001 );
260 
261 		// Calc pen intensity
262 		if ( mPen_Dep_S ) {
263 			rgbPrev = rgb;
264 			__evalIntensity( rgb.red );
265 		}
266 
267 		// Draw all the waves
268 		for ( i = 0; i < maxWaves; i++ ) {
269 
270 			if ( i < mNumWaves ) {
271 
272 				// Find the cords for waveshape1, wave number i
273 				tx = xscale * mWaveX.Evaluate( i );
274 				ty = yscale * mWaveY.Evaluate( i );
275 
276 				// If we have two waves to mix...
277 				if ( i < w2Waves ) {
278 					tx = mShapeTrans * tx + ( 1.0 - mShapeTrans ) * xscaleW2 * inWave2 -> mWaveX.Evaluate( i );
279 					ty = mShapeTrans * ty + ( 1.0 - mShapeTrans ) * yscaleW2 * inWave2 -> mWaveY.Evaluate( i ); }
280 				else {
281 					tx *= dialate;
282 					ty *= dialate;
283 				} }
284 			else {
285 
286 				// Find the cords for waveshape2, wave number i
287 				tx = dialate * xscaleW2 * inWave2 -> mWaveX.Evaluate( i );
288 				ty = dialate * yscaleW2 * inWave2 -> mWaveY.Evaluate( i );
289 			}
290 
291 			// Switch to screen cords, baby, and draw the line segment
292 			x = xoff + tx;
293 			y = yoff - ty;
294 
295 			if ( mConnectBins ) {
296 				if ( sS > 0 )
297 					inDest.Line( sXY[ 2 * i ], sXY[ 2 * i + 1 ], x, y, rgbPrev, rgb );
298 				else {
299 					sStartXY[ 2 * i ]		= x;
300 					sStartXY[ 2 * i + 1 ]	= y;
301 					rgbStart = rgb;
302 				}
303 				sXY[ 2 * i ] = x;
304 				sXY[ 2 * i + 1 ] = y;  }
305 			else
306 				inDest.Line( x, y, x, y, rgb, rgb );
307 		}
308 	}
309 
310 	// Draw all the first-last segments for each wave
311 	if ( mConnectFirstLast ) {
312 		for ( i = 0; i < maxWaves; i++ )
313 			inDest.Line( sXY[ 2 * i ], sXY[ 2 * i + 1 ], sStartXY[ 2 * i ], sStartXY[ 2 * i + 1 ], rgb, rgbStart );
314 	}
315 
316 	// Make sure we restore a random seed (one of the virtual machines could be seeding to the same value)
317 	srand( *((long*) mTPtr) );
318 
319 }
320 
321 
322 
323 
324 #define __weightFLT( field ) field = ( inW * ( (float) field##Orig ) + w1 * ( (float) inDest -> field ) );
325 #define __weightINT( field ) field = ( 0.5 + inW * ( (float) field##Orig ) + w1 * ( (float) inDest -> field ) );
326 #define __weightBOL( field ) field = .5 < ( inW * ( field##Orig ? 1.0 : 0.0 ) + w1 * ( inDest -> field ? 1.0 : 0.0 ) );
327 
328 
SetupFrame(WaveShape * inDest,float inW)329 void WaveShape::SetupFrame( WaveShape* inDest, float inW ) {
330 	float w1 = 1.0 - inW;
331 
332 	__weightBOL( mConnectBins )
333 	__weightBOL( mConnectFirstLast )
334 }
335 
336