From mmeising@at.ac.uni-linz.risc Thu Jun 23 11:20:38 1994
Received: from festival.ed.ac.uk (festival.edinburgh.ac.uk) by aiai.ed.ac.uk; Thu, 23 Jun 94 11:20:27 BST
Received: from melmac.risc.uni-linz.ac.at by festival.ed.ac.uk id aa25373;
          23 Jun 94 11:15 BST
Received: by melmac.risc.uni-linz.ac.at id AA01739
  (Sendmail 5.65c/IDA-1.4.4 for J.Smart@ed.ac.uk); Thu, 23 Jun 1994 12:14:37 +0200
Date: Thu, 23 Jun 1994 12:14:37 +0200
From: Markus Meisinger <Markus.Meisinger@at.ac.uni-linz.risc>
Message-Id: <199406231014.AA01739@melmac.risc.uni-linz.ac.at>
To: J.Smart@ed
Subject: animation demo
Status: REO

Dear Mr Julian Smart

I have written a short animation demo using wxWindows, because people asked
me how to program moving objects using wxWindows. I have tested it under
LINUX and MS-Windows.

If you find it worthy you may add it to the sample programs in further
versions of wxWindows or make it available by FTP.

Please contact me if their are some questions or problems.

Markus F. Meisinger
email: Markus.Meisinger@risc.uni-linz.ac.at
RISC-Linz
Research Institute for Symbolic Computation
Johannes Kepler University
A-4040 Linz, Austria

----------------------------------- cut here -------------------------------
/*
 * File:        anim.h
 * Purpose:     wxWindow animation demo
 * Author:      Markus Franz Meisinger
 * e-mail:      Markus.Meisinger@risc.uni-linz.ac.at
 * Created:     June 1994
 * Updated:     
 * Copyright:   
 */

#include "tool3d.h"

class baseObject: public object3D
{ public:
    wxBrush    *faceBrush[10];

    baseObject(void);
    ~baseObject(void);
    void Draw(wxDC &dc);
};

class cube: public baseObject
{ public:
    cube(void);
};

class ufo: public baseObject
{ public:
    ufo(void);
};

// Define a new application type
class AnimApp: public wxApp
{ public:
    AnimApp(void);
    wxFrame *OnInit(void);
};

// Define a new canvas
class objCanvas: public wxCanvas
{ private:
    float      fXMax, fYMax;
    int        xOfs, yOfs;
    wxMemoryDC memDC;
    wxBitmap   *memBmp;

  public:
    int        xRot, yRot, zRot;
    int        xInc, yInc, zInc;
    int        zDist;
    cube       myCube;
    ufo        myUfo;

    objCanvas(wxFrame *frame,
              int x, int y, int w, int h, int style = wxRETAINED,
              float fMaxX = 0.0, float fMaxY = 0.0);
    ~objCanvas(void);
    void OnPaint(void);
    void Draw(wxDC &dc);
    void AnimationStep(void);
    void SetMaxXY(float fMaxX, float fMaxY);
};

// Define an own timer for animation
class animationTimer: public wxTimer
{ public:
    void Notify(void);
};

// Define a new main frame type
class AnimFrame: public wxFrame
{ public:
    wxPanel          *panel;
    objCanvas        *drawArea;
    animationTimer   animation;

    AnimFrame(wxFrame *frame, char *title, int x, int y, int w, int h);
    ~AnimFrame(void);
    void OnMenuCommand(int id);
    void OnSize(int w, int h);
    Bool OnClose(void);
};

// IDs for the menu commands
#define ANIMATION_QUIT  101

----------------------------------- cut here -------------------------------
/*
 * File:        anim.cc
 * Purpose:     wxWindow animation demo
 * Author:      Markus Franz Meisinger
 * e-mail:      Markus.Meisinger@risc.uni-linz.ac.at
 * Created:     June 1994
 * Updated:     
 * Copyright:   
 */

static const char sccsid[] = "%W% %G%";

#include <wx.h>
#include <wx_timer.h>
#include <stdio.h>
#include <malloc.h>

// include class definitions
#include "anim.h"

// ----------------------------------------------------------------------------
// data declaration 
// ----------------------------------------------------------------------------

// global application variables used in different objects
AnimFrame *frame = NULL;          // main frame

// ----------------------------------------------------------------------------
// method implementation part of defined classes
// ----------------------------------------------------------------------------

// anim main frame constructor; some initialization will be done
AnimFrame::AnimFrame(wxFrame *frame, char *title, int x, int y, int w, int h):
  wxFrame(frame, title, x, y, w, h)
{
  panel    = NULL;
  drawArea = NULL;
  animation.Start(100);
}

// anim main frame destructor
AnimFrame::~AnimFrame(void)
{
  animation.Stop();
}

// each menu selection invoces this main frame method
void AnimFrame::OnMenuCommand(int id)
{
  switch (id) {
    case ANIMATION_QUIT:
      OnClose();
      delete this;
    break;
  }
}

// Size the subwindowssss when the frame is resized
void AnimFrame::OnSize(int w, int h)
{
  if (panel && drawArea) {
    int width, height;
    GetClientSize(&width, &height);
    panel->SetSize(0, 0, width, (int)(height/2));
    drawArea->SetSize(0, (int)(height/2), width, (int)(height/2));
    drawArea->SetMaxXY((float)width, (float)(height/2));
  }
}

Bool AnimFrame::OnClose(void)
{
  return (TRUE);
}

// Define a constructor for my canvas
objCanvas::objCanvas(wxFrame *frame, 
                   int x, int y, int w, int h, int style,
                   float fMaxX, float fMaxY):
 wxCanvas(frame, x, y, w, h, style)
{
  fXMax = fMaxX;
  fYMax = fMaxY;

  // create a bitmap of canvas size and select it into the memory dc
  memBmp = new wxBitmap((int)(fXMax+1), (int)(fYMax+1));
  memDC.SelectObject(memBmp);

  xOfs = (int)(fXMax / 2);
  yOfs = (int)(fYMax / 2);
  xRot = yRot = zRot = 0;
  xInc = 6;
  yInc = -9;
  zInc = 12;
  zDist = -130;
}

// Define the destructor; delete all dynamic data
objCanvas::~objCanvas(void)
{
  delete memBmp;
}

// Define the repainting behaviour
void objCanvas::OnPaint(void)
{
  BeginDrawing();

  Draw(memDC);                                 // first, draw in memory dc
  (*GetDC()).Blit(0.0, 0.0, fXMax, fYMax,      // second, copy memory dc to
		  &memDC, 0.0 ,0.0, wxCOPY);   // display (to avoid flickering)

  EndDrawing();
}

void objCanvas::Draw(wxDC &dc)
{
  dc.Clear();
  myCube.Rotate(xRot, yRot, zRot);
  myCube.Translate(0, 0, zDist+60);
  myCube.Project(xOfs, yOfs, 10, 10, 500);
  myCube.Draw(dc);
  myUfo.Rotate(xRot, yRot, zRot);
  myUfo.Translate(0, 0, zDist);
  myUfo.Project(xOfs, yOfs, 10, 10, 500);
  myUfo.Draw(dc);
}

void objCanvas::AnimationStep(void)
{
  xRot = (xRot + xInc) % 360;
  if (xRot < 0) { xRot += 360; }
  yRot = (yRot + yInc) % 360;
  if (yRot < 0) { yRot += 360; }
  zRot = (zRot + zInc) % 360;
  if (zRot < 0) { zRot += 360; }
  //printf("alpha: %d, beta: %d, gamma: %d\n", xRot, yRot, zRot);
}

void objCanvas::SetMaxXY(float fMaxX, float fMaxY)
{
  delete memBmp;                                         // resize memory bitmap
  memBmp = new wxBitmap((int)(fXMax+1), (int)(fYMax+1));
  memDC.SelectObject(memBmp);

  xOfs = (int)(fXMax / 2);
  yOfs = (int)(fYMax / 2);
}

// Implemention of the notification method
void animationTimer::Notify(void)
{
  frame->drawArea->AnimationStep();
  frame->drawArea->OnPaint();
}

baseObject::baseObject(void)
{
  faceBrush[0] = new wxBrush("RED", wxSOLID);
  faceBrush[1] = new wxBrush("YELLOW", wxSOLID);
  faceBrush[2] = new wxBrush("BLUE", wxSOLID);
  faceBrush[3] = new wxBrush("WHITE", wxSOLID);
  faceBrush[4] = new wxBrush("GREEN", wxSOLID);
  faceBrush[5] = new wxBrush("CYAN", wxSOLID);
  faceBrush[6] = new wxBrush("BROWN", wxSOLID);
  faceBrush[7] = new wxBrush("VIOLET", wxSOLID);
  faceBrush[8] = new wxBrush("PURPLE", wxSOLID);
  faceBrush[9] = new wxBrush("CORAL", wxSOLID);
  
}

baseObject::~baseObject(void)
{
  int i;

  for (i = 0; i < 10; i++) {
    delete faceBrush[i];
  }
}
void baseObject::Draw(wxDC &dc)
{
  int i, j, noPts;
  struct faceStruct *face;
  struct point2D pt;
  wxPoint points[8];

  for (i = 0; i < faces.no; i++) {                         // for all faces
    face = (faces.points+i);
    noPts = face->noPts;
    if (face->visible) {                                   //   if visible
      //printf("Normal %d: (%d,%d,%d)\n", i+1, face->normal.x, face->normal.y, face->normal.z);
      for (j = 0; j < noPts; j++) {                
        pt  = *((face->projected)+j);
        points[j].x = (float)pt.x;
        points[j].y = (float)pt.y;
      }
      dc.SetBrush(faceBrush[i]);
      dc.DrawPolygon(noPts, points, 0, 0, wxODDEVEN_RULE); //     draw face
    }
  }
}

ufo::ufo(void)
{
  int x1Pts[8] = { 0, -17, -25, -17, 0, 17, 25, 17 };
  int x2Pts[8] = { 0, -25, -35, -25, 0, 25, 35, 25 };
  struct point3D ufoPt[16], *pt, p, s, w, ps, sw;
  int i, bytes;
  struct faceStruct *face;

  faces.no = 10;
  bytes = sizeof(struct faceStruct) * faces.no;
  faces.points = (struct faceStruct *)malloc(bytes);

  for (i = 0; i < 8; i++) {
    ufoPt[i].x = x1Pts[i];
    ufoPt[i].y = x1Pts[(i+6) % 8];
    ufoPt[i].z = -10;
    ufoPt[i+8].x = x2Pts[i];
    ufoPt[i+8].y = x2Pts[(i+6) % 8];
    ufoPt[i+8].z = 10;
  }

  for (i = 0; i < 7; i++) {
    face = (faces.points+i);
    face->noPts = 4;
    face->origPoint = (struct point3D *)malloc(sizeof(struct point3D) * 4);
    face->point     = (struct point3D *)malloc(sizeof(struct point3D) * 4);
    face->projected = (struct point2D *)malloc(sizeof(struct point2D) * 4);
    
    pt  = (face->origPoint+0);
    *pt = ufoPt[i];
    pt  = (face->origPoint+1);
    *pt = ufoPt[i+8];
    pt  = (face->origPoint+2);
    *pt = ufoPt[(i+8) + 1];
    pt  = (face->origPoint+3);
    *pt = ufoPt[i+1];
  }

  face = (faces.points+i);
  face->noPts = 4;
  face->origPoint = (struct point3D *)malloc(sizeof(struct point3D) * 4);
  face->point     = (struct point3D *)malloc(sizeof(struct point3D) * 4);
  face->projected = (struct point2D *)malloc(sizeof(struct point2D) * 4);
  pt  = (face->origPoint+0);
  *pt = ufoPt[7];
  pt  = (face->origPoint+1);
  *pt = ufoPt[15];
  pt  = (face->origPoint+2);
  *pt = ufoPt[8];
  pt  = (face->origPoint+3);
  *pt = ufoPt[0];

  face = (faces.points+8);
  face->noPts = 8;
  face->origPoint = (struct point3D *)malloc(sizeof(struct point3D) * 8);
  face->point     = (struct point3D *)malloc(sizeof(struct point3D) * 8);
  face->projected = (struct point2D *)malloc(sizeof(struct point2D) * 8);
  for (i=0; i < 8; i++) {
    pt = (face->origPoint+i);
    *pt = ufoPt[i];
  }
  face = (faces.points+9);
  face->noPts = 8;
  face->origPoint = (struct point3D *)malloc(sizeof(struct point3D) * 8);
  face->point     = (struct point3D *)malloc(sizeof(struct point3D) * 8);
  face->projected = (struct point2D *)malloc(sizeof(struct point2D) * 8);
  for (i=0; i < 8; i++) {
    pt = (face->origPoint+i);
    *pt = ufoPt[15-i];
  }

  for (i = 0; i < faces.no; i++) {
    face = (faces.points+i);
    p = *(face->origPoint+0);
    s = *(face->origPoint+1);
    w = *(face->origPoint+2);
    ps.x = s.x - p.x;
    ps.y = s.y - p.y;
    ps.z = s.z - p.z;
    sw.x = w.x - s.x;
    sw.y = w.y - s.y;
    sw.z = w.z - s.z;
    face->origNormal.x = sw.y * ps.z - sw.z * ps.y;
    face->origNormal.y = sw.z * ps.x - sw.x * ps.z;
    face->origNormal.z = sw.x * ps.y - sw.y * ps.x;
  }
}

cube::cube(void)
{
  int bytes;
  struct faceStruct *face;
  struct point3D    *pt;

  faces.no = 6;
  bytes = sizeof(struct faceStruct) * faces.no;
  faces.points = (struct faceStruct *)malloc(bytes);

//  for (i = 0; i < faces.no; i++) {

    face = (faces.points+0);
    face->noPts = 4;
    face->origPoint = (struct point3D *)malloc(sizeof(struct point3D) * 4);
    face->point     = (struct point3D *)malloc(sizeof(struct point3D) * 4);
    face->projected = (struct point2D *)malloc(sizeof(struct point2D) * 4);

    face->origNormal.x = 0;
    face->origNormal.y = 0;
    face->origNormal.z = -16384;

    pt  = (face->origPoint+0);
    pt->x = -50; pt->y =  50; pt->z = -50; // P
    pt  = (face->origPoint+1);
    pt->x = -50; pt->y = -50; pt->z = -50; // Q
    pt  = (face->origPoint+2);
    pt->x =  50; pt->y = -50; pt->z = -50; // R
    pt  = (face->origPoint+3);
    pt->x =  50; pt->y =  50; pt->z = -50; // S

    face = (faces.points+1);
    face->noPts = 4;
    face->origPoint = (struct point3D *)malloc(sizeof(struct point3D) * 4);
    face->point     = (struct point3D *)malloc(sizeof(struct point3D) * 4);
    face->projected = (struct point2D *)malloc(sizeof(struct point2D) * 4);

    face->origNormal.x = 0;
    face->origNormal.y = 16384;
    face->origNormal.z = 0;

    pt  = (face->origPoint+0);
    pt->x = -50; pt->y =  50; pt->z = -50; // P
    pt  = (face->origPoint+1);
    pt->x =  50; pt->y =  50; pt->z = -50; // S
    pt  = (face->origPoint+2);
    pt->x =  50; pt->y =  50; pt->z =  50; // W
    pt  = (face->origPoint+3);
    pt->x = -50; pt->y =  50; pt->z =  50; // T

    face = (faces.points+2);
    face->noPts = 4;
    face->origPoint = (struct point3D *)malloc(sizeof(struct point3D) * 4);
    face->point     = (struct point3D *)malloc(sizeof(struct point3D) * 4);
    face->projected = (struct point2D *)malloc(sizeof(struct point2D) * 4);

    face->origNormal.x = 16384;
    face->origNormal.y = 0;
    face->origNormal.z = 0;

    pt  = (face->origPoint+0);
    pt->x =  50; pt->y =  50; pt->z = -50; // S
    pt  = (face->origPoint+1);
    pt->x =  50; pt->y = -50; pt->z = -50; // R
    pt  = (face->origPoint+2);
    pt->x =  50; pt->y = -50; pt->z =  50; // V
    pt  = (face->origPoint+3);
    pt->x =  50; pt->y =  50; pt->z =  50; // W

    face = (faces.points+3);
    face->noPts = 4;
    face->origPoint = (struct point3D *)malloc(sizeof(struct point3D) * 4);
    face->point     = (struct point3D *)malloc(sizeof(struct point3D) * 4);
    face->projected = (struct point2D *)malloc(sizeof(struct point2D) * 4);

    face->origNormal.x = 0;
    face->origNormal.y = -16384;
    face->origNormal.z = 0;

    pt  = (face->origPoint+0);
    pt->x = -50; pt->y = -50; pt->z = -50; // Q
    pt  = (face->origPoint+1);
    pt->x = -50; pt->y = -50; pt->z =  50; // U
    pt  = (face->origPoint+2);
    pt->x =  50; pt->y = -50; pt->z =  50; // V
    pt  = (face->origPoint+3);
    pt->x =  50; pt->y = -50; pt->z = -50; // R

    face = (faces.points+4);
    face->noPts = 4;
    face->origPoint = (struct point3D *)malloc(sizeof(struct point3D) * 4);
    face->point     = (struct point3D *)malloc(sizeof(struct point3D) * 4);
    face->projected = (struct point2D *)malloc(sizeof(struct point2D) * 4);

    face->origNormal.x = -16384;
    face->origNormal.y = 0;
    face->origNormal.z = 0;

    pt  = (face->origPoint+0);
    pt->x = -50; pt->y =  50; pt->z = -50; // P
    pt  = (face->origPoint+1);
    pt->x = -50; pt->y =  50; pt->z =  50; // T
    pt  = (face->origPoint+2);
    pt->x = -50; pt->y = -50; pt->z =  50; // U
    pt  = (face->origPoint+3);
    pt->x = -50; pt->y = -50; pt->z = -50; // Q

    face = (faces.points+5);
    face->noPts = 4;
    face->origPoint = (struct point3D *)malloc(sizeof(struct point3D) * 4);
    face->point     = (struct point3D *)malloc(sizeof(struct point3D) * 4);
    face->projected = (struct point2D *)malloc(sizeof(struct point2D) * 4);

    face->origNormal.x = 0;
    face->origNormal.y = 0;
    face->origNormal.z = 16384;

    pt  = (face->origPoint+0);
    pt->x = -50; pt->y =  50; pt->z =  50; // T
    pt  = (face->origPoint+1);
    pt->x =  50; pt->y =  50; pt->z =  50; // W
    pt  = (face->origPoint+2);
    pt->x =  50; pt->y = -50; pt->z =  50; // V
    pt  = (face->origPoint+3);
    pt->x = -50; pt->y = -50; pt->z =  50; // U

//  }
}


void ObjDistance(wxSlider &slider, wxCommandEvent &event)
{
  frame->drawArea->zDist = slider.GetValue();
}

void RotateX(wxSlider &slider, wxCommandEvent &event)
{
  frame->drawArea->xInc = slider.GetValue();
}

void RotateY(wxSlider &slider, wxCommandEvent &event)
{
  frame->drawArea->yInc = slider.GetValue();
}

void RotateZ(wxSlider &slider, wxCommandEvent &event)
{
  frame->drawArea->zInc = slider.GetValue();
}

// ----------------------------------------------------------------------------
// entry point of the whole application
// ----------------------------------------------------------------------------

// this statement initializes the whole application and calls OnInit
AnimApp animApp;

// application contructor
AnimApp::AnimApp(void)
{
  // testing of ressources, this forces the program (under UNIX) to look for
  // an application default file called "Animation"
  wx_class = copystring("Animation");
}

// `Main program' equivalent, creating windows and returning main frame
wxFrame *AnimApp::OnInit(void)
{
  // used variables
  wxMenuBar *animMenu   = new wxMenuBar;
  wxMenu    *projectMenu = new wxMenu;
  int       width, height;

  // Create the main frame window
  frame = new AnimFrame(NULL, "WxWindows Animation Demo", 50, 50, 330, 400);

  // Give it an icon
#ifdef wx_msw
  frame->SetIcon(new wxIcon("aiai_ico"));
#endif
#ifdef wx_x
  frame->SetIcon(new wxIcon("aiai.xbm"));
#endif

  // Give it a status line
  frame->CreateStatusLine(1);
  frame->SetStatusText("WxWindows Animation Demo");

  // Make the menubar
  projectMenu->Append(ANIMATION_QUIT, "&Quit");

  animMenu->Append(projectMenu, "&File");

  frame->SetMenuBar(animMenu);

  // Fetch client size of main frame
  frame->GetClientSize(&width, &height);

  // Make a panel with a message just half the size of the whole main frame
  frame->panel = new wxPanel(frame, 0, 0, width, (int)(height/2));
  //(void)new wxMessage(frame->panel, "Hello! A message outside of a drawing area!");
  (void)new wxSlider(frame->panel, (wxFunction)RotateX, "rotation speed x:",
                     6, -15, 15, 300);
  frame->panel->NewLine();
  (void)new wxSlider(frame->panel, (wxFunction)RotateY, "rotation speed y:",
                     -9, -15, 15, 300);
  frame->panel->NewLine();
  (void)new wxSlider(frame->panel, (wxFunction)RotateZ, "rotation speed z:",
                     12, -15, 15, 300);
  frame->panel->NewLine();
  (void)new wxSlider(frame->panel, (wxFunction)ObjDistance, "object distance:",
                     -130, -1000, 250, 300);



  // Make a canvas with a rectangle and put in on the left space in the main frame
  frame->drawArea = new objCanvas(frame,
				 0, (int)(height/2), width, (int)(height/2),
				 wxBORDER | wxRETAINED,
                                 (float)width, (float)(height/2));

  frame->Show(TRUE);

  // Return the main frame window
  return frame;
}

----------------------------------- cut here -------------------------------
/*
 * File:        tool3d.h
 * Purpose:     class definitions for projecting 3D objects
 * Author:      Markus Franz Meisinger
 * e-mail:      Markus.Meisinger@risc.uni-linz.ac.at
 * Created:     June 1994
 * Updated:     
 * Copyright:   
 */

class object3D
{ public:
    struct point3D {
      int x, y, z;
    };
    struct longPoint3D {
      long x, y, z;
    };
    struct point2D {
      int x, y;
    };
    struct faceStruct {
      int noPts;
      int visible;
      struct point3D *origPoint;
      struct point3D *point;
      struct point2D *projected;
      struct longPoint3D origNormal;
      struct longPoint3D normal;
    };

    int sinTable[360];    
    int alpha;
    int beta;
    int gamma;
    struct facesStruct {
      int no;
      struct faceStruct *points;
    } faces;

    object3D(void);
    virtual ~object3D(void);

    long Sinus(int grad);
    long Cosinus(int grad);
    void RotateX(void);
    void RotateY(void);
    void RotateZ(void);
    virtual void Draw(void) {};
    void Project(int xOfs, int yOfs, int xEye, int yEye, int zEye);
    void Rotate(int xRot, int yRot, int zRot);
    void Translate(int x, int y, int z);
};

----------------------------------- cut here -------------------------------
/*
 * File:        tool3d.cc
 * Purpose:     class implementation for projecting 3D objects
 * Author:      Markus Franz Meisinger
 * e-mail:      Markus.Meisinger@risc.uni-linz.ac.at
 * Created:     June 1994
 * Updated:     
 * Copyright:   
 */

#include <math.h>
#include <malloc.h>
#include "tool3d.h"

object3D::object3D(void)
{
  int i;

  for (i = 0; i < 360; i++) {
    sinTable[i] = (int)(sin(i/57.29577951) * 16384);
  }

  alpha = beta = gamma = 0;

  faces.no = 0;
  faces.points = NULL;

}

object3D::~object3D(void)
{
  int i;
  struct faceStruct *face;

  for (i = 0; i < faces.no; i++) {   // for all faces
    face = (faces.points+i);         //   free each dynamic allocated data
    free(face->origPoint);
    free(face->point);
    free(face->projected);
  }
  free(faces.points);
}


// returns the sin of <grad> times 16384
long object3D::Sinus(int grad)
{
  return (sinTable[grad]);
}

// returns the cos of <grad> times 16384
long object3D::Cosinus(int grad)
{
  return (sinTable[((grad + 90) % 360)]);
}

void object3D::Project(int xOfs, int yOfs, int xEye, int yEye, int zEye)
{
  int    i, j, noPts;
  long   tmp, d;
  struct faceStruct *face;
  struct point3D *pt;

  for (i = 0; i < faces.no; i++) {                 // for all faces
    face = (faces.points+i);
    noPts = face->noPts;
    face->visible = ((long)(xEye * face->normal.x) +       //   if visible
		     (long)(yEye * face->normal.y) +
		     (long)(zEye * face->normal.z)) > 0;
    if (face->visible) {
      for (j = 0; j < noPts; j++) {                //     project each point
	pt  = ((face->point)+j);
        d   = (long)zEye;
	tmp = (long)pt->z - d;

	(*(face->projected+j)).x = xOfs - (int)((long)(pt->x * d) / tmp);
	(*(face->projected+j)).y = yOfs + (int)((long)(pt->y * d) / tmp);
      }
    }
  }
}

void object3D::RotateX(void)
{
  int i, j, noPts;
  long sinAlpha, cosAlpha;
  long y, z, yTmp, zTmp;
  struct faceStruct *face;
  struct point3D *pt;

  sinAlpha = Sinus(alpha);
  cosAlpha = Cosinus(alpha);

  for (i = 0; i < faces.no; i++) {                  // for all faces

    face = (faces.points+i);
    noPts = face->noPts;

    // restore original vector
    face->normal = face->origNormal;

    // fist, rotate normal vector
    y = (long)(face->normal.y);
    z = (long)(face->normal.z);
    yTmp = (y * cosAlpha + z * sinAlpha) >> 14;
    zTmp = (-y * sinAlpha + z * cosAlpha) >> 14;
    face->normal.y = (int)yTmp;
    face->normal.z = (int)zTmp;

    for (j = 0; j < noPts; j++) {                   //   rotate each point
      pt  = (face->point+j);

      // restore original point
      *pt = *(face->origPoint+j);

      // rotate point
      y = (long)(pt->y);
      z = (long)(pt->z);
      yTmp = (y * cosAlpha + z * sinAlpha) >> 14;
      zTmp = (-y * sinAlpha + z * cosAlpha) >> 14;
      pt->y = (int)yTmp;
      pt->z = (int)zTmp;
    }
  }
}

void object3D::RotateY(void)
{
  int i, j, noPts;
  long sinBeta, cosBeta;
  long x, z, xTmp, zTmp;
  struct faceStruct *face;
  struct point3D *pt;

  sinBeta = Sinus(beta);
  cosBeta = Cosinus(beta);

  for (i = 0; i < faces.no; i++) {                  // for all faces

    face = (faces.points+i);
    noPts = face->noPts;

    // fist, rotate normal vector
    x = (long)(face->normal.x);
    z = (long)(face->normal.z);
    xTmp = (x * cosBeta + z * sinBeta) >> 14;
    zTmp = (-x * sinBeta + z * cosBeta) >> 14;
    face->normal.x = (int)xTmp;
    face->normal.z = (int)zTmp;

    for (j = 0; j < noPts; j++) {                   // rotate each point
      pt  = (face->point+j);
      x = (long)(pt->x);
      z = (long)(pt->z);
      xTmp = (x * cosBeta + z * sinBeta) >> 14;
      zTmp = (-x * sinBeta + z * cosBeta) >> 14;
      pt->x = (int)xTmp;
      pt->z = (int)zTmp;
    }
  }
}

void object3D::RotateZ(void)
{
  int i, j, noPts;
  long sinGamma, cosGamma;
  long x, y, xTmp, yTmp;
  struct faceStruct *face;
  struct point3D *pt;

  sinGamma = Sinus(gamma);
  cosGamma = Cosinus(gamma);

  for (i = 0; i < faces.no; i++) {                  // for all faces

    face = (faces.points+i);
    noPts = face->noPts;

    // fist, rotate normal vector
    x = (long)(face->normal.x);
    y = (long)(face->normal.y);
    xTmp = (x * cosGamma + y * sinGamma) >> 14;
    yTmp = (-x * sinGamma + y * cosGamma) >> 14;
    face->normal.x = (int)xTmp;
    face->normal.y = (int)yTmp;

    for (j = 0; j < noPts; j++) {                   // rotate each point
      pt  = (face->point+j);
      x = (long)(pt->x);
      y = (long)(pt->y);
      xTmp = (x * cosGamma + y * sinGamma) >> 14;
      yTmp = (-x * sinGamma + y * cosGamma) >> 14;
      pt->x = (int)xTmp;
      pt->y = (int)yTmp;
    }
  }
}

void object3D::Rotate(int xRot, int yRot, int zRot)
{
  alpha = xRot;
  beta  = yRot;
  gamma = zRot;

  RotateX();
  RotateY();
  RotateZ();
}

void object3D::Translate(int x, int y, int z)
{
  int i, j, noPts;
  struct faceStruct *face;
  struct point3D *pt;

  for (i = 0; i < faces.no; i++) {                  // for all faces

    face = (faces.points+i);
    noPts = face->noPts;

    for (j = 0; j < noPts; j++) {                   //   translate each point
      pt  = (face->point+j);
      pt->x += x;
      pt->y += y;
      pt->z += z;
    }
  }
}
------------------------------------- cut here ------------------------------
#
# File:		makefile.unx
# Author:	Markus Franz Meisinger
# Created:	June 1994
# Updated:	
# Copyright:	
#
# "%W% %G%"
#
# Makefile for animation example (UNIX).

GUISUFFIX=_motif
CC = gcc

# Replace X include/lib directories with your own, e.g. -I/usr/openwin/include ...
XINCLUDE=-I/usr/X386/include -I/usr/openwin/include
XLIB=-L/usr/X386/lib -L/usr/openwin/lib

WXDIR = /usr/src/wx
WXINC = $(WXDIR)/include
WXLIB = $(WXDIR)/lib/libwx$(GUISUFFIX).a

INC = -I$(WXDIR)/include/base -I$(WXDIR)/include/x
OBJDIR=objects$(GUISUFFIX)

SOURCES = anim.cc tool3d.cc
HEADERS =
OBJECTS = $(OBJDIR)/anim.o $(OBJDIR)/tool3d.o

# Default is to use XView
DEBUG = #-ggdb
WARN = -Wall
OPT = -O
GUI = -Dwx_motif
XVIEW_LINK = 

CPPFLAGS =  $(XINCLUDE) $(INC) $(GUI) $(DEBUG) $(WARN)
LDFLAGS =  $(XLIB) -L$(WXDIR)/lib
LDLIBS = -lwx_motif -lXm -lXt -lX11 -lm -lg++

.SUFFIXES:

all:    $(OBJDIR) anim$(GUISUFFIX)

wx:


motif:
	cd $(WXDIR)/src/x; make  motif OPT='$(OPT)'
	make  GUI=-Dwx_motif OPT='$(OPT)' GUISUFFIX=_motif LDLIBS='-lwx_motif -lXm -lXt -lX11 -lm -lg++' XVIEW_LINK=

xview:
#	cd $(WXDIR)/src/x; make  xview OPT='$(OPT)'
	make  GUI=-Dwx_xview OPT='$(OPT)' GUISUFFIX=_ol LDLIBS='-lwx_ol -lxview -lolgx -lX11 -lm -lg++' XVIEW_LINK='$(WXDIR)/src/x/objects_ol/sb_scrol.o'

hp:
	cd $(WXDIR)/src/x; make  hp
	make  GUI=-Dwx_motif GUISUFFIX=_hp CC=CC DEBUG='' WARN='-w' \
           XINCLUDE='-I/usr/include/Motif1.2 -I/usr/include/X11R5' \
           XLIB='-L/usr/lib/Motif1.2 -L/usr/lib/X11R5' \
           XVIEW_LINK='' \
           LDLIBS='-lwx_hp -lXm -lXt -lX11 -lm'

$(OBJDIR):
	mkdir $(OBJDIR)

anim$(GUISUFFIX):	$(OBJECTS) $(WXLIB)
	$(CC) $(CPPFLAGS) $(LDFLAGS) -o anim$(GUISUFFIX) $(OBJECTS) $(XVIEW_LINK) $(LDLIBS)

$(OBJDIR)/anim.o:	anim.cc
	$(CC) -c $(CPPFLAGS) -o $@ anim.cc

$(OBJDIR)/tool3d.o:	tool3d.cc
	$(CC) -c $(CPPFLAGS) -o $@ tool3d.cc

clean_motif:
	make  GUISUFFIX=_motif cleanany

clean_ol:
	make  GUISUFFIX=_ol cleanany

clean_hp:
	make  GUISUFFIX=_hp cleanany

cleanany:
	rm -f $(OBJECTS) anim$(GUISUFFIX) core

