+ MI_IS_DRAWN(mi) = True;
+
+ /* Calculate circling POV [Chalky]*/
+ sp->circle[1] = sp->circle[0];
+ sp->circle[0].x = sp->size * 2 * sin(sp->count / 100.0) *
+ (-0.6 + 0.4 *cos(sp->count / 500.0)) + sp->mid.x;
+ sp->circle[0].y = sp->size * 2 * cos(sp->count / 100.0) *
+ (0.6 + 0.4 *cos(sp->count / 500.0)) + sp->mid.y;
+ sp->circle[0].z = sp->size * 2 * sin(sp->count / 421.0) + sp->mid.z;
+
+ /* Timed chase instead of Chalkie's Bistable oscillator [TDA] */
+ if(rotatep && ridep) {
+ if(sp->chaseto == BEE && NRAND(1000) == 0){
+ sp->chaseto = ORBIT;
+ sp->chasetime = 100;
+ }else if(NRAND(4000) == 0){
+ sp->chaseto = BEE;
+ sp->chasetime = 100;
+ }
+ }
+
+ /* Set up orientation matrix */
+ {
+ double x[3], p[3], x2=0, xp=0;
+ int j;
+
+ /* Chasetime is here to guarantee the camera makes it all the
+ way to the target in a finite number of steps. */
+ if(sp->chasetime > 1)
+ sp->chasetime--;
+
+ if(sp->chaseto == BEE){
+ /* Camera Head targets bee 0 */
+ sp->cam[0].x += (X(0, 0) - sp->cam[0].x)/sp->chasetime;
+ sp->cam[0].y += (Y(0, 0) - sp->cam[0].y)/sp->chasetime;
+ sp->cam[0].z += (Z(0, 0) - sp->cam[0].z)/sp->chasetime;
+
+ /* Camera Tail targets previous position of bee 0 */
+ sp->cam[1].x += (X(1, 0) - sp->cam[1].x)/sp->chasetime;
+ sp->cam[1].y += (Y(1, 0) - sp->cam[1].y)/sp->chasetime;
+ sp->cam[1].z += (Z(1, 0) - sp->cam[1].z)/sp->chasetime;
+
+ /* Camera Wing targets bee 1 */
+ sp->cam[2].x += (X(0, 1) - sp->cam[2].x)/sp->chasetime;
+ sp->cam[2].y += (Y(0, 1) - sp->cam[2].y)/sp->chasetime;
+ sp->cam[2].z += (Z(0, 1) - sp->cam[2].z)/sp->chasetime;
+ } else {
+ /* Camera Head targets Orbiter */
+ sp->cam[0].x += (sp->circle[0].x - sp->cam[0].x)/sp->chasetime;
+ sp->cam[0].y += (sp->circle[0].y - sp->cam[0].y)/sp->chasetime;
+ sp->cam[0].z += (sp->circle[0].z - sp->cam[0].z)/sp->chasetime;
+
+ /* Camera Tail targets diametrically opposite the middle
+ of the bounding box from the Orbiter */
+ sp->cam[1].x +=
+ (2*sp->circle[0].x - sp->mid.x - sp->cam[1].x)/sp->chasetime;
+ sp->cam[1].y +=
+ (2*sp->circle[0].y - sp->mid.y - sp->cam[1].y)/sp->chasetime;
+ sp->cam[1].z +=
+ (2*sp->circle[0].z - sp->mid.z - sp->cam[1].z)/sp->chasetime;
+ /* Camera Wing targets previous position of Orbiter */
+ sp->cam[2].x += (sp->circle[1].x - sp->cam[2].x)/sp->chasetime;
+ sp->cam[2].y += (sp->circle[1].y - sp->cam[2].y)/sp->chasetime;
+ sp->cam[2].z += (sp->circle[1].z - sp->cam[2].z)/sp->chasetime;
+ }
+
+ /* Viewpoint from Tail of camera */
+ sp->centre.x=sp->cam[1].x;
+ sp->centre.y=sp->cam[1].y;
+ sp->centre.z=sp->cam[1].z;
+
+ /* forward vector */
+ x[0] = sp->cam[0].x - sp->cam[1].x;
+ x[1] = sp->cam[0].y - sp->cam[1].y;
+ x[2] = sp->cam[0].z - sp->cam[1].z;
+
+ /* side */
+ p[0] = sp->cam[2].x - sp->cam[1].x;
+ p[1] = sp->cam[2].y - sp->cam[1].y;
+ p[2] = sp->cam[2].z - sp->cam[1].z;
+
+
+ /* So long as X and P don't collide, these can be used to form
+ three mutually othogonal axes: X, (X x P) x X and X x P.
+ After being normalised to unit length, these form the
+ Orientation Matrix. */
+
+ for(i=0; i<3; i++){
+ x2+= x[i]*x[i]; /* X . X */
+ xp+= x[i]*p[i]; /* X . P */
+ M[0][i] = x[i]; /* X */
+ }
+
+ for(i=0; i<3; i++) /* (X x P) x X */
+ M[1][i] = x2*p[i] - xp*x[i]; /* == (X . X) P - (X . P) X */
+
+ M[2][0] = x[1]*p[2] - x[2]*p[1]; /* X x P */
+ M[2][1] = -x[0]*p[2] + x[2]*p[0];
+ M[2][2] = x[0]*p[1] - x[1]*p[0];
+
+ /* normalise axes */
+ for(j=0; j<3; j++){
+ double A=0;
+ for(i=0; i<3; i++) A+=M[j][i]*M[j][i]; /* sum squares */
+ A=sqrt(A);
+ if(A>0)
+ for(i=0; i<3; i++) M[j][i]/=A;
+ }
+
+ if(sp->chaseto == BEE) {
+ X(0, 1)=X(0, 0)+M[1][0]*sp->step; /* adjust neighbour */
+ Y(0, 1)=Y(0, 0)+M[1][1]*sp->step;
+ Z(0, 1)=Z(0, 0)+M[1][2]*sp->step;
+ }
+ }
+
+ /* <=- Bounding Box -=> */
+ if(boxp) {
+ for (b = 0; b < BOX_L; b++) {
+
+ /* Chalky's clipping code, Only used for the box */
+ /* clipping trails is slow and of little benefit. [TDA] */
+ int p1 = lines[b][0];
+ int p2 = lines[b][1];
+ dvector A1, A2;
+ double x1=box[p1][0]* sp->size/2 + sp->mid.x - sp->centre.x;
+ double y1=box[p1][1]* sp->size/2 + sp->mid.y - sp->centre.y;
+ double z1=box[p1][2]* sp->size/2 + sp->mid.z - sp->centre.z;
+ double x2=box[p2][0]* sp->size/2 + sp->mid.x - sp->centre.x;
+ double y2=box[p2][1]* sp->size/2 + sp->mid.y - sp->centre.y;
+ double z2=box[p2][2]* sp->size/2 + sp->mid.z - sp->centre.z;
+
+ A1.x=M[0][0]*x1 + M[0][1]*y1 + M[0][2]*z1;
+ A1.y=M[1][0]*x1 + M[1][1]*y1 + M[1][2]*z1;
+ A1.z=M[2][0]*x1 + M[2][1]*y1 + M[2][2]*z1 + EYEHEIGHT * sp->size;
+ A2.x=M[0][0]*x2 + M[0][1]*y2 + M[0][2]*z2;
+ A2.y=M[1][0]*x2 + M[1][1]*y2 + M[1][2]*z2;
+ A2.z=M[2][0]*x2 + M[2][1]*y2 + M[2][2]*z2 + EYEHEIGHT * sp->size;
+
+ /* Clip in 3D before projecting down to 2D. A 2D clip
+ after projection wouldn't be able to handle lines that
+ cross x=0 */
+ if (clip(1, 0, 0,-1, &A1, &A2) || /* Screen */
+ clip(1, 2, 0, 0, &A1, &A2) || /* Left */
+ clip(1,-2, 0, 0, &A1, &A2) || /* Right */
+ clip(1,0, 2.0*MI_WIDTH(mi)/MI_HEIGHT(mi), 0, &A1, &A2)||/*UP*/
+ clip(1,0,-2.0*MI_WIDTH(mi)/MI_HEIGHT(mi), 0, &A1, &A2))/*Down*/
+ continue;
+
+ /* Colour according to bee */
+ col = b % (MI_NPIXELS(mi) - 1);
+
+ sp->csegs[IX(col)].x1 = MI_WIDTH(mi)/2 + MI_WIDTH(mi) * A1.y/A1.x;
+ sp->csegs[IX(col)].y1 = MI_HEIGHT(mi)/2 + MI_WIDTH(mi) * A1.z/A1.x;
+ sp->csegs[IX(col)].x2 = MI_WIDTH(mi)/2 + MI_WIDTH(mi) * A2.y/A2.x;
+ sp->csegs[IX(col)].y2 = MI_HEIGHT(mi)/2 + MI_WIDTH(mi) * A2.z/A2.x;
+ sp->cnsegs[col]++;
+ }
+ }
+