/*
  Maze editor: 3D visualizer class
  Copyright (C) 1998 by Jorrit Tyberghein
  Written by Andrew Zabolotny <bit@eltech.ru>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free
  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef __ME_3D_H__
#define __ME_3D_H__

#include "csws/csws.h"
#include "mazed.h"

/// Indicices into mzDraftEditor's palette
#define CSPAL_DRAFT_BACKGROUND	0
#define CSPAL_DRAFT_VERTEX	1
#define CSPAL_DRAFT_INACTVERTEX	2
#define CSPAL_DRAFT_SELVERTEX	3
#define CSPAL_DRAFT_POLY	4
#define CSPAL_DRAFT_ACTPOLY	5
#define CSPAL_DRAFT_SELPOLY	6
#define CSPAL_DRAFT_AXIS	7
#define CSPAL_DRAFT_AXISNAME	8
#define CSPAL_DRAFT_GRID	9
#define CSPAL_DRAFT_SELRECT	10
#define CSPAL_DRAFT_MODIFYAXIS	11
#define CSPAL_DRAFT_MODIFIED	12
#define CSPAL_DRAFT_SCRATCHPAD	13


///
class mz3DWindow : public csWindow
{
public:
  /// Create the Draft Editor window (frame etc)
  mz3DWindow (csComponent *iParent, char *iTitle);
  /// Position our additional window controls when window changes
  virtual bool SetRect (int xmin, int ymin, int xmax, int ymax);

};

///
class mzCameraView : public csComponent
{
public:
  /// Create the Draft Editor view
  mzCameraView (csComponent *iParent);

  /// Draw the component (only dirty rectangle should be redrawn)
  virtual void Draw ();

  /// Handle camera view events
  virtual bool HandleEvent (csEvent &Event);

protected:
  friend class mz3DModel;
  /**
   * We keep view vector as two angles: phi and theta. They are the
   * dirtection of vector in polar coordinates, phi being the angle of
   * rotation around vertical (Y) axis and theta being the angle of rotation
   * around horizontal axis that is perpendicular to Y.
   */
  float phi, theta;
  /**
   * We also keep the scale of ortogonal projection<p>
   * The scale is expressed as the medium distance between
   * horizontal and vertical window bounds. For example, if scale is 1
   * and we have a square window, and the center point of window (pos)
   * is at (0,0,0), and we have a XOY plane projection matrix this means
   * that we'll see in window the square (-0.5, -0.5, 0)...(+0.5, +0.5, 0)
   */
  float scale;
  /// Current 3D transform matrix resulting from above, and its inverse
  csMatrix3 w2c, c2w;
  /// ... and the position of camera
  csVector3 pos;
  /// Mouse coordinates in previous frame when dragging etc
  int oldMouseX, oldMouseY;
  /// Used when dragging a rectangle
  int dragMouseX, dragMouseY;
  /// Equations of four planes that cuts visible space
  struct { double A, B, C, D; } clip_eq [4];
  /// Minimal and maximal coordinates within view frustum
  float xmin, ymin, zmin, xmax, ymax, zmax;
  /// Coordinates of four viewport corners in world space
  mz3DVertex clip_corner [4];
  
  /// render view 
  csRenderView* rview;
  csBoxClipper* bc;
  csCamera* cam;

public:
  /// Call this routine after changing phi, theta, scale or pos
  void UpdateMatrix ();
  /// Convert a point from world space to window space
  void world2win (csVector3 &v, int &x, int &y);
  /// Same but without translation
  void world2win (csVector3 &v, csVector3 &dest);
  /// Convert a point from window space to world space
  void win2world (int x, int y, float z, csVector3 &v);
  /// Same but given floating-point coordinates
  void win2world (float x, float y, float z, csVector3 &v);
  /// Call UpdateMatrix () when window size changes
  virtual bool SetRect (int xmin, int ymin, int xmax, int ymax);
  /// Set viewing angles
  void SetViewAngles (float iPhi, float iTheta);

};

#endif // __ME_3D_H__
