1 /*
2  * $RCSfile: CompressionStreamNormal.java,v $
3  *
4  * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * - Redistribution of source code must retain the above copyright
11  *   notice, this list of conditions and the following disclaimer.
12  *
13  * - Redistribution in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  *
18  * Neither the name of Sun Microsystems, Inc. or the names of
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * This software is provided "AS IS," without a warranty of any
23  * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
24  * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
25  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
26  * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
27  * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
28  * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
29  * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
30  * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
31  * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
32  * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
33  * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGES.
35  *
36  * You acknowledge that this software is not designed, licensed or
37  * intended for use in the design, construction, operation or
38  * maintenance of any nuclear facility.
39  *
40  * $Revision: 1.3 $
41  * $Date: 2007/02/09 17:20:22 $
42  * $State: Exp $
43  */
44 
45 package com.sun.j3d.utils.geometry.compression;
46 
47 import javax.vecmath.Vector3f;
48 
49 /**
50  * This class represents a normal in a compression stream. It maintains both
51  * floating-point and quantized representations.  This normal may be bundled
52  * with a vertex or exist separately as a global normal.
53  */
54 class CompressionStreamNormal extends CompressionStreamElement {
55     private int u, v ;
56     private int specialOctant, specialSextant ;
57     private float normalX, normalY, normalZ ;
58 
59     int octant, sextant ;
60     boolean specialNormal ;
61     int uAbsolute, vAbsolute ;
62 
63     /**
64      * Create a CompressionStreamNormal.
65      *
66      * @param stream CompressionStream associated with this element
67      * @param normal floating-point representation to be encoded
68      */
CompressionStreamNormal(CompressionStream stream, Vector3f normal)69     CompressionStreamNormal(CompressionStream stream, Vector3f normal) {
70 	this.normalX = normal.x ;
71 	this.normalY = normal.y ;
72 	this.normalZ = normal.z ;
73 	stream.byteCount += 12 ;
74     }
75 
76     //
77     // Normal Encoding Parameterization
78     //
79     // A floating point normal is quantized to a desired number of bits by
80     // comparing it to candidate entries in a table of every possible normal
81     // at that quantization and finding the closest match.  This table of
82     // normals is indexed by the following encoding:
83     //
84     // First, points on a unit radius sphere are parameterized by two angles,
85     // th and psi, using usual spherical coordinates. th is the angle about
86     // the y axis, psi is the inclination to the plane containing the point.
87     // The mapping between rectangular and spherical coordinates is:
88     //
89     // x = cos(th)*cos(psi)
90     // y = sin(psi)
91     // z = sin(th)*cos(psi)
92     //
93     // Points on sphere are folded first by octant, and then by sort order
94     // of xyz into one of six sextants. All the table encoding takes place in
95     // the positive octant, in the region bounded by the half spaces:
96     //
97     // x >= z
98     // z >= y
99     // y >= 0
100     //
101     // This triangular shaped patch runs from 0 to 45 degrees in th, and
102     // from 0 to as much as 0.615479709 (MAX_Y_ANG) in psi. The xyz bounds
103     // of the patch is:
104     //
105     // (1, 0, 0)  (1/sqrt(2), 0, 1/sqrt(2))  (1/sqrt(3), 1/sqrt(3), 1/sqrt(3))
106     //
107     // When dicing this space up into discrete points, the choice for y is
108     // linear quantization in psi.  This means that if the y range is to be
109     // divided up into n segments, the angle of segment j is:
110     //
111     // psi(j) = MAX_Y_ANG*(j/n)
112     //
113     // The y height of the patch (in arc length) is *not* the same as the xz
114     // dimension. However, the subdivision quantization needs to treat xz and
115     // y equally. To achieve this, the th angles are re-parameterized as
116     // reflected psi angles.  That is, the i-th point's th is:
117     //
118     // th(i) = asin(tan(psi(i))) = asin(tan(MAX_Y_ANG*(i/n)))
119     //
120     // To go the other direction, the angle th corresponds to the real index r
121     // (in the same 0-n range as i):
122     //
123     // r(th) = n*atan(sin(th))/MAX_Y_ANG
124     //
125     // Rounded to the nearest integer, this gives the closest integer index i
126     // to the xz angle th. Because the triangle has a straight edge on the
127     // line x=z, it is more intuitive to index the xz angles in reverse
128     // order.  Thus the two equations above are replaced by:
129     //
130     // th(i) = asin(tan(psi(i))) = asin(tan(MAX_Y_ANG*((n-i)/n)))
131     //
132     // r(th) = n*(1 - atan(sin(th))/MAX_Y_ANG)
133     //
134     // Each level of quantization subdivides the triangular patch twice as
135     // densely.  The case in which only the three vertices of the triangle are
136     // present is the first logical stage of representation, but because of
137     // how the table is encoded the first usable case starts one level of
138     // sub-division later.  This three point level has an n of 2 by the above
139     // conventions.
140     //
141     private static final int MAX_UV_BITS = 6 ;
142     private static final int MAX_UV_ENTRIES = 64 ;
143 
144     private static final double cgNormals[][][][] =
145 	new double[MAX_UV_BITS+1][MAX_UV_ENTRIES+1][MAX_UV_ENTRIES+1][3] ;
146 
147     private static final double MAX_Y_ANG = 0.615479709 ;
148     private static final double UNITY_14 = 16384.0 ;
149 
computeNormals()150     private static void computeNormals() {
151 	int inx, iny, inz, n ;
152 	double th, psi, qnx, qny, qnz ;
153 
154 	for (int quant = 0 ; quant <= MAX_UV_BITS ; quant++) {
155 	    n = 1 << quant ;
156 
157 	    for (int j = 0 ; j <= n ; j++) {
158 		for (int i = 0 ; i <= n ; i++) {
159 		    if (i+j > n) continue ;
160 
161 		    psi = MAX_Y_ANG*(j/((double) n)) ;
162 		    th = Math.asin(Math.tan(MAX_Y_ANG*((n-i)/((double) n)))) ;
163 
164 		    qnx = Math.cos(th)*Math.cos(psi) ;
165 		    qny = Math.sin(psi) ;
166 		    qnz = Math.sin(th)*Math.cos(psi) ;
167 
168 		    // The normal table uses 16-bit components and must be
169 		    // able to represent both +1.0 and -1.0, so convert the
170 		    // floating point normal components to fixed point with 14
171 		    // fractional bits, a unity bit, and a sign bit (s1.14).
172 		    // Set them back to get the float equivalent.
173 		    qnx = qnx*UNITY_14 ; inx = (int)qnx ;
174 		    qnx = inx ; qnx = qnx/UNITY_14 ;
175 
176 		    qny = qny*UNITY_14 ; iny = (int)qny ;
177 		    qny = iny ; qny = qny/UNITY_14 ;
178 
179 		    qnz = qnz*UNITY_14 ; inz = (int)qnz ;
180 		    qnz = inz ; qnz = qnz/UNITY_14 ;
181 
182 		    cgNormals[quant][j][i][0] = qnx ;
183 		    cgNormals[quant][j][i][1] = qny ;
184 		    cgNormals[quant][j][i][2] = qnz ;
185 		}
186 	    }
187 	}
188     }
189 
190     //
191     // An inverse sine table is used for each quantization level to take the Y
192     // component of a normal (which is the sine of the inclination angle) and
193     // obtain the closest quantized Y angle.
194     //
195     // At any level of compression, there are a fixed number of different Y
196     // angles (between 0 and MAX_Y_ANG).  The inverse table is built to have
197     // slightly more than twice as many entries as y angles at any particular
198     // level; this ensures that the inverse look-up will get within one angle
199     // of the right one.  The size of the table should be as small as
200     // possible, but with its delta sine still smaller than the delta sine
201     // between the last two angles to be encoded.
202     //
203     // Example: the inverse sine table has a maximum angle of 0.615479709.  At
204     // the maximum resolution of 6 bits there are 65 discrete angles used,
205     // but twice as many are needed for thresholding between angles, so the
206     // delta angle is 0.615479709/128. The difference then between the last
207     // two angles to be encoded is:
208     // sin(0.615479709*128.0/128.0) - sin(0.615479709*127.0/128.0) = 0.003932730
209     //
210     // Using 8 significent bits below the binary point, fixed point can
211     // represent sines in increments of 0.003906250, just slightly smaller.
212     // However, because the maximum Y angle sine is 0.577350269, only 148
213     // instead of 256 table entries are needed.
214     //
215     private static final short inverseSine[][] = new short[MAX_UV_BITS+1][] ;
216 
217     // UNITY_14 * sin(MAX_Y_ANGLE)
218     private static final short MAX_SIN_14BIT = 9459 ;
219 
computeInverseSineTables()220     private static void computeInverseSineTables() {
221 	int intSin, deltaSin, intAngle ;
222 	double floatSin, floatAngle ;
223 	short sin14[] = new short[MAX_UV_ENTRIES+1] ;
224 
225 	// Build table of sines in s1.14 fixed point for each of the
226 	// discrete angles used at maximum resolution.
227 	for (int i = 0 ; i <= MAX_UV_ENTRIES ; i++) {
228 	    sin14[i] = (short)(UNITY_14*Math.sin(i*MAX_Y_ANG/MAX_UV_ENTRIES)) ;
229 	}
230 
231 	for (int quant = 0 ; quant <= MAX_UV_BITS ; quant++) {
232 	    switch (quant) {
233 	    default:
234 	    case 6:
235 		// Delta angle: MAX_Y_ANGLE/128.0
236 		// Bits below binary point for fixed point delta sine: 8
237 		// Integer delta sine: 64
238 		// Inverse sine table size: 148 entries
239 		deltaSin = 1 << (14 - 8) ;
240 		break ;
241 	    case 5:
242 		// Delta angle: MAX_Y_ANGLE/64.0
243 		// Bits below binary point for fixed point delta sine: 7
244 		// Integer delta sine: 128
245 		// Inverse sine table size: 74 entries
246 		deltaSin = 1 << (14 - 7) ;
247 		break ;
248 	    case 4:
249 		// Delta angle: MAX_Y_ANGLE/32.0
250 		// Bits below binary point for fixed point delta sine: 6
251 		// Integer delta sine: 256
252 		// Inverse sine table size: 37 entries
253 		deltaSin = 1 << (14 - 6) ;
254 		break ;
255 	    case 3:
256 		// Delta angle: MAX_Y_ANGLE/16.0
257 		// Bits below binary point for fixed point delta sine: 5
258 		// Integer delta sine: 512
259 		// Inverse sine table size: 19 entries
260 		deltaSin = 1 << (14 - 5) ;
261 		break ;
262 	    case 2:
263 		// Delta angle: MAX_Y_ANGLE/8.0
264 		// Bits below binary point for fixed point delta sine: 4
265 		// Integer delta sine: 1024
266 		// Inverse sine table size: 10 entries
267 		deltaSin = 1 << (14 - 4) ;
268 		break ;
269 	    case 1:
270 		// Delta angle: MAX_Y_ANGLE/4.0
271 		// Bits below binary point for fixed point delta sine: 3
272 		// Integer delta sine: 2048
273 		// Inverse sine table size: 5 entries
274 		deltaSin = 1 << (14 - 3) ;
275 		break ;
276 	    case 0:
277 		// Delta angle: MAX_Y_ANGLE/2.0
278 		// Bits below binary point for fixed point delta sine: 2
279 		// Integer delta sine: 4096
280 		// Inverse sine table size: 3 entries
281 		deltaSin = 1 << (14 - 2) ;
282 		break ;
283 	    }
284 
285 	    inverseSine[quant] = new short[(MAX_SIN_14BIT/deltaSin) + 1] ;
286 
287 	    intSin = 0 ;
288 	    for (int i = 0 ; i < inverseSine[quant].length ; i++) {
289 		// Compute float representation of integer sine with desired
290 		// number of fractional bits by effectively right shifting 14.
291 		floatSin = intSin/UNITY_14 ;
292 
293 		// Compute the angle with this sine value and quantize it.
294 		floatAngle = Math.asin(floatSin) ;
295 		intAngle = (int)((floatAngle/MAX_Y_ANG) * (1 << quant)) ;
296 
297 		// Choose the closest of the three nearest quantized values
298 		// intAngle-1, intAngle, and intAngle+1.
299 		if (intAngle > 0) {
300 		    if (Math.abs(sin14[intAngle << (6-quant)] - intSin) >
301 			Math.abs(sin14[(intAngle-1) << (6-quant)] - intSin))
302 			intAngle = intAngle-1 ;
303 		}
304 
305 		if (intAngle < (1 << quant)) {
306 		    if (Math.abs(sin14[intAngle << (6-quant)] - intSin) >
307 			Math.abs(sin14[(intAngle+1) << (6-quant)] - intSin))
308 			intAngle = intAngle+1 ;
309 		}
310 
311 		inverseSine[quant][i] = (short)intAngle ;
312 		intSin += deltaSin ;
313 	    }
314 	}
315     }
316 
317     /**
318      * Compute static tables needed for normal quantization.
319      */
320     static {
computeNormals()321 	computeNormals() ;
computeInverseSineTables()322 	computeInverseSineTables() ;
323     }
324 
325     /**
326      * Quantize the floating point normal to a 6-bit octant/sextant plus u,v
327      * components of [0..6] bits.  Full resolution is 18 bits and the minimum
328      * is 6 bits.
329      *
330      * @param stream CompressionStream associated with this element
331      * @param table HuffmanTable for collecting data about the quantized
332      * representation of this element
333      */
quantize(CompressionStream stream, HuffmanTable huffmanTable)334     void quantize(CompressionStream stream, HuffmanTable huffmanTable) {
335 	double nx, ny, nz, t ;
336 
337 	// Clamp UV quantization.
338 	int quant =
339 	    (stream.normalQuant < 0? 0 :
340 	     (stream.normalQuant > 6? 6 : stream.normalQuant)) ;
341 
342 	nx = normalX ;
343 	ny = normalY ;
344 	nz = normalZ ;
345 
346 	octant = 0 ;
347 	sextant = 0 ;
348 	u = 0 ;
349 	v = 0 ;
350 
351 	// Normalize the fixed point normal to the positive signed octant.
352 	if (nx < 0.0) {
353 	    octant |= 4 ;
354 	    nx = -nx ;
355 	}
356 	if (ny < 0.0) {
357 	    octant |= 2 ;
358 	    ny = -ny ;
359 	}
360 	if (nz < 0.0) {
361 	    octant |= 1 ;
362 	    nz = -nz ;
363 	}
364 
365 	// Normalize the fixed point normal to the proper sextant of the octant.
366 	if (nx < ny) {
367 	    sextant |= 1 ;
368 	    t = nx ;
369 	    nx = ny ;
370 	    ny = t ;
371 	}
372 	if (nz < ny) {
373 	    sextant |= 2 ;
374 	    t = ny ;
375 	    ny = nz ;
376 	    nz = t ;
377 	}
378 	if (nx < nz) {
379 	    sextant |= 4 ;
380 	    t = nx ;
381 	    nx = nz ;
382 	    nz = t ;
383 	}
384 
385 	// Convert the floating point y component to s1.14 fixed point.
386 	int yInt = (int)(ny * UNITY_14) ;
387 
388 	// The y component of the normal is the sine of the y angle.  Quantize
389 	// the y angle by using the fixed point y component as an index into
390 	// the inverse sine table of the correct size for the quantization
391 	// level.  (12 - quant) bits of the s1.14 y normal component are
392 	// rolled off with a right shift; the remaining bits then match the
393 	// number of bits used to represent the delta sine of the table.
394 	int yIndex = inverseSine[quant][yInt >> (12-quant)] ;
395 
396 	// Search the two xz rows near y for the best match.
397 	int ii = 0 ;
398 	int jj = 0 ;
399 	int n = 1 << quant ;
400 	double dot, bestDot = -1 ;
401 
402 	for (int j = yIndex-1 ; j < yIndex+1 && j <= n ; j++) {
403 	    if (j < 0)
404 		continue ;
405 
406 	    for (int i = 0 ; i <= n ; i++) {
407 		if (i+j > n)
408 		    continue ;
409 
410 		dot = nx * cgNormals[quant][j][i][0] +
411 		      ny * cgNormals[quant][j][i][1] +
412 		      nz * cgNormals[quant][j][i][2] ;
413 
414 		if (dot > bestDot) {
415 		    bestDot = dot ;
416 		    ii = i ;
417 		    jj = j ;
418 		}
419 	    }
420 	}
421 
422 	// Convert u and v to standard grid form.
423 	u = ii << (6 - quant) ;
424 	v = jj << (6 - quant) ;
425 
426 	// Check for special normals and specially encode them.
427 	specialNormal = false ;
428 	if (u == 64 && v ==  0) {
429 	    // six coordinate axes case
430 	    if (sextant == 0 || sextant == 2) {
431 		// +/- x-axis
432 		specialSextant = 0x6 ;
433 		specialOctant = ((octant & 4) != 0)? 0x2 : 0 ;
434 
435 	    } else if (sextant == 3 || sextant == 1) {
436 		// +/- y-axis
437 		specialSextant = 0x6 ;
438 		specialOctant = 4 | (((octant & 2) != 0)? 0x2 : 0) ;
439 
440 	    } else if (sextant == 5 || sextant == 4) {
441 		// +/- z-axis
442 		specialSextant = 0x7 ;
443 		specialOctant = ((octant & 1) != 0)? 0x2 : 0 ;
444 	    }
445 	    specialNormal = true ;
446 	    u = v = 0 ;
447 
448 	} else if (u ==  0 && v == 64) {
449 	    // eight mid point case
450 	    specialSextant = 6 | (octant >> 2) ;
451 	    specialOctant = ((octant & 0x3) << 1) | 1 ;
452 	    specialNormal = true ;
453 	    u = v = 0 ;
454 	}
455 
456 	// Compute deltas if possible.
457 	// Use the non-normalized ii and jj indices.
458 	int du = 0 ;
459 	int dv = 0 ;
460 	int uv64 = 64 >> (6 - quant) ;
461 
462 	absolute = false ;
463 	if (stream.firstNormal || stream.normalQuantChanged ||
464 	    stream.lastSpecialNormal || specialNormal) {
465 	    // The first normal by definition is absolute, and normals cannot
466 	    // be represented as deltas to or from special normals, nor from
467 	    // normals with a different quantization.
468 	    absolute = true ;
469 	    stream.firstNormal = false ;
470 	    stream.normalQuantChanged = false ;
471 
472 	} else if (stream.lastOctant == octant &&
473 		   stream.lastSextant == sextant) {
474 	    // Deltas are always allowed within the same sextant/octant.
475 	    du = ii - stream.lastU ;
476 	    dv = jj - stream.lastV ;
477 
478 	} else if (stream.lastOctant != octant &&
479 		   stream.lastSextant == sextant &&
480 		   (((sextant == 1 || sextant == 5) &&
481 		     (stream.lastOctant & 3) == (octant & 3)) ||
482 		    ((sextant == 0 || sextant == 4) &&
483 		     (stream.lastOctant & 5) == (octant & 5)) ||
484 		    ((sextant == 2 || sextant == 3) &&
485 		     (stream.lastOctant & 6) == (octant & 6)))) {
486 	    // If the sextants are the same, the octants can differ only when
487 	    // they are bordering each other on the same edge that the
488 	    // sextant has.
489 	    du =  ii - stream.lastU ;
490 	    dv = -jj - stream.lastV ;
491 
492 	    // Can't delta by less than -64.
493 	    if (dv < -uv64) absolute = true ;
494 
495 	    // Can't delta doubly defined points.
496 	    if (jj == 0) absolute = true ;
497 
498 	} else if (stream.lastOctant == octant &&
499 		   stream.lastSextant != sextant &&
500 		   ((sextant == 0 && stream.lastSextant == 4) ||
501 		    (sextant == 4 && stream.lastSextant == 0) ||
502 		    (sextant == 1 && stream.lastSextant == 5) ||
503 		    (sextant == 5 && stream.lastSextant == 1) ||
504 		    (sextant == 2 && stream.lastSextant == 3) ||
505 		    (sextant == 3 && stream.lastSextant == 2))) {
506 	    // If the octants are the same, the sextants must border on
507 	    // the i side (this case) or the j side (next case).
508 	    du = -ii - stream.lastU ;
509 	    dv =  jj - stream.lastV ;
510 
511 	    // Can't delta by less than -64.
512 	    if (du < -uv64) absolute = true ;
513 
514 	    // Can't delta doubly defined points.
515 	    if (ii == 0) absolute = true ;
516 
517 	} else if (stream.lastOctant == octant &&
518 		   stream.lastSextant != sextant &&
519 		   ((sextant == 0 && stream.lastSextant == 2) ||
520 		    (sextant == 2 && stream.lastSextant == 0) ||
521 		    (sextant == 1 && stream.lastSextant == 3) ||
522 		    (sextant == 3 && stream.lastSextant == 1) ||
523 		    (sextant == 4 && stream.lastSextant == 5) ||
524 		    (sextant == 5 && stream.lastSextant == 4))) {
525 	    // If the octants are the same, the sextants must border on
526 	    // the j side (this case) or the i side (previous case).
527 	    if (((ii + jj ) != uv64) && (ii != 0) && (jj != 0)) {
528 		du = uv64 - ii - stream.lastU ;
529 		dv = uv64 - jj - stream.lastV ;
530 
531 		// Can't delta by greater than +63.
532 		if ((du >= uv64) || (dv >= uv64))
533 		    absolute = true ;
534 	    } else
535 		// Can't delta doubly defined points.
536 		absolute = true ;
537 
538 	} else
539 	    // Can't delta this normal.
540 	    absolute = true ;
541 
542 	if (absolute == false) {
543 	    // Convert du and dv to standard grid form.
544 	    u = du << (6 - quant) ;
545 	    v = dv << (6 - quant) ;
546 	}
547 
548 	// Compute length and shift common to all components.
549 	computeLengthShift(u, v) ;
550 
551 	if (absolute && length > 6) {
552 	    // Absolute normal u, v components are unsigned 6-bit integers, so
553 	    // truncate the 0 sign bit for values > 0x001f.
554 	    length = 6 ;
555 	}
556 
557 	// Add this element to the Huffman table associated with this stream.
558 	huffmanTable.addNormalEntry(length, shift, absolute) ;
559 
560 	// Save current normal as last.
561 	stream.lastSextant = sextant ;
562 	stream.lastOctant = octant ;
563 	stream.lastU = ii ;
564 	stream.lastV = jj ;
565 	stream.lastSpecialNormal = specialNormal ;
566 
567 	// Copy and retain absolute normal for mesh buffer lookup.
568 	uAbsolute = ii ;
569 	vAbsolute = jj ;
570     }
571 
572     /**
573      * Output a setNormal command.
574      *
575      * @param table HuffmanTable mapping quantized representations to
576      * compressed encodings
577      * @param output CommandStream for collecting compressed output
578      */
outputCommand(HuffmanTable table, CommandStream output)579     void outputCommand(HuffmanTable table, CommandStream output) {
580 	outputNormal(table, output, CommandStream.SET_NORM, 8) ;
581     }
582 
583     /**
584      * Output a normal subcommand.
585      *
586      * @param table HuffmanTable mapping quantized representations to
587      * compressed encodings
588      * @param output CommandStream for collecting compressed output
589      */
outputSubcommand(HuffmanTable table, CommandStream output)590     void outputSubcommand(HuffmanTable table, CommandStream output) {
591 	outputNormal(table, output, 0, 6) ;
592     }
593 
594     //
595     // Output the final compressed bits to the output command stream.
596     //
outputNormal(HuffmanTable table, CommandStream output, int header, int headerLength)597     private void outputNormal(HuffmanTable table, CommandStream output,
598 			      int header, int headerLength) {
599 
600  	HuffmanNode t ;
601 
602 	// Look up the Huffman token for this compression stream element.
603 	t = table.getNormalEntry(length, shift, absolute) ;
604 
605 	// Construct the normal subcommand.
606 	int componentLength = t.dataLength - t.shift ;
607 	int subcommandLength = 0 ;
608 	long normalSubcommand = 0 ;
609 
610 	if (absolute) {
611 	    // A 3-bit sextant and a 3-bit octant are always present.
612 	    subcommandLength = t.tagLength + 6 ;
613 
614 	    if (specialNormal)
615 		// Use the specially-encoded sextant and octant.
616 		normalSubcommand =
617 		    (t.tag << 6) | (specialSextant << 3) | specialOctant ;
618 	    else
619 		// Use the general encoding rule.
620 		normalSubcommand =
621 		    (t.tag << 6) | (sextant << 3) | octant ;
622 	} else {
623 	    // The tag is immediately followed by the u and v delta components.
624 	    subcommandLength = t.tagLength ;
625 	    normalSubcommand = t.tag ;
626 	}
627 
628 	// Add the u and v values to the subcommand.
629 	subcommandLength += (2 * componentLength) ;
630 
631 	u = (u >> t.shift) & (int)lengthMask[componentLength] ;
632 	v = (v >> t.shift) & (int)lengthMask[componentLength] ;
633 
634 	normalSubcommand =
635 	    (normalSubcommand << (2 * componentLength)) |
636 	    (u                << (1 * componentLength)) |
637 	    (v                << (0 * componentLength)) ;
638 
639 	if (subcommandLength < 6) {
640 	    // The header will have some empty bits. The Huffman tag
641 	    // computation will prevent this if necessary.
642 	    header |= (int)(normalSubcommand << (6 - subcommandLength)) ;
643 	    subcommandLength = 0 ;
644 	}
645 	else {
646 	    // Move the 1st 6 bits of the subcommand into the header.
647 	    header |= (int)(normalSubcommand >>> (subcommandLength - 6)) ;
648 	    subcommandLength -= 6 ;
649 	}
650 
651 	// Add the header and body to the output buffer.
652 	output.addCommand(header, headerLength,
653 			  normalSubcommand, subcommandLength)  ;
654     }
655 
toString()656     public String toString() {
657 	String fixed ;
658 
659 	if (specialNormal)
660 	    fixed = " special normal, sextant " + specialSextant +
661 		    " octant " + specialOctant ;
662 
663 	else if (absolute)
664 	    fixed = " sextant " + sextant + " octant " + octant +
665 		    " u " + u + " v " + v ;
666 	else
667 	    fixed = " du " + u + " dv " + v ;
668 
669 	return
670 	    "normal: " + normalX + " " + normalY + " " + normalZ + "\n"
671 	    + fixed + "\n" + " length " + length + " shift " + shift +
672 	    (absolute? " absolute" : " relative") ;
673     }
674 }
675