]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - contrib/gtkgensurf/view.cpp
more eol-style
[xonotic/netradiant.git] / contrib / gtkgensurf / view.cpp
index ff4b157219c5765f590c57e462b4361a14bb969a..9344a69e424d9c2914eb6c860d7dc3c6208feab0 100644 (file)
-/*\r
-GenSurf plugin for GtkRadiant\r
-Copyright (C) 2001 David Hyde, Loki software and qeradiant.com\r
-\r
-This library is free software; you can redistribute it and/or\r
-modify it under the terms of the GNU Lesser General Public\r
-License as published by the Free Software Foundation; either\r
-version 2.1 of the License, or (at your option) any later version.\r
-\r
-This library is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-Lesser General Public License for more details.\r
-\r
-You should have received a copy of the GNU Lesser General Public\r
-License along with this library; if not, write to the Free Software\r
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-*/\r
-\r
-#include <math.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include "gensurf.h"\r
-\r
-#undef ISOMETRIC\r
-\r
-extern double backface;\r
-extern double dh, dv;\r
-extern double xmin,xmax,ymin,ymax,zmin,zmax;\r
-\r
-double    SF, SFG;         // Graphics scale factors\r
-double    XLo, XHi, YLo, YHi, ZLo, ZHi;\r
-double    yaw,roll;\r
-double    elevation,azimuth;\r
-int       cxChar = 10, cyChar = 16;\r
-int       X0, Y0;\r
-int       X0G, Y0G;\r
-\r
-static RECT rcCoord;   // where X= Y= is drawn\r
-static RECT rcGrid;    // rectangle within rcLower that forms the border of the grid, plus\r
-                       //   a 3 pixel slop.\r
-static RECT rcLower;   // lower half of window, where plan view is drawn\r
-static RECT rcUpper;   // upper half or entire window, where isometric projection is drawn\r
-\r
-void vertex_selected ();\r
-void texfont_init ();\r
-void texfont_write (const char *text, float l, float t);\r
-\r
-#define PEN_GRID { \\r
-  g_GLTable.m_pfn_qglLineWidth (1); \\r
-  g_GLTable.m_pfn_qglColor3f (0, 1, 0); \\r
-  g_GLTable.m_pfn_qglDisable (GL_LINE_STIPPLE); }\r
-\r
-#define PEN_RED { \\r
-  g_GLTable.m_pfn_qglLineWidth (2); \\r
-  g_GLTable.m_pfn_qglColor3f (1, 0, 0); \\r
-  g_GLTable.m_pfn_qglDisable (GL_LINE_STIPPLE); }\r
-\r
-#define PEN_DASH { \\r
-  g_GLTable.m_pfn_qglLineWidth (1); \\r
-  g_GLTable.m_pfn_qglColor3f (0, 1, 0); \\r
-  g_GLTable.m_pfn_qglLineStipple (1, 0xF0F0); \\r
-  g_GLTable.m_pfn_qglEnable (GL_LINE_STIPPLE); }\r
-\r
-#define DRAW_QUAD(rc,r,g,b) { \\r
-  g_GLTable.m_pfn_qglBegin (GL_QUADS); \\r
-  g_GLTable.m_pfn_qglColor3f (0,1,0); \\r
-  g_GLTable.m_pfn_qglVertex2f (rc.left-1, rc.bottom); \\r
-  g_GLTable.m_pfn_qglVertex2f (rc.right, rc.bottom); \\r
-  g_GLTable.m_pfn_qglVertex2f (rc.right, rc.top+1); \\r
-  g_GLTable.m_pfn_qglVertex2f (rc.left-1, rc.top+1); \\r
-  g_GLTable.m_pfn_qglColor3f (r,g,b); \\r
-  g_GLTable.m_pfn_qglVertex2f (rc.left, rc.bottom+1); \\r
-  g_GLTable.m_pfn_qglVertex2f (rc.right-1, rc.bottom+1); \\r
-  g_GLTable.m_pfn_qglVertex2f (rc.right-1, rc.top); \\r
-  g_GLTable.m_pfn_qglVertex2f (rc.left, rc.top); \\r
-  g_GLTable.m_pfn_qglEnd (); }\r
-\r
-\r
-#ifndef ISOMETRIC\r
-double    D=65536.;\r
-double    ct[3],st[3];\r
-double    Hhi, Hlo, Vhi, Vlo;\r
-#endif\r
-\r
-#define SUBDIVS 6\r
-\r
-\r
-void ShowPreview ()\r
-{\r
-  if (Preview)\r
-  {\r
-    if (g_pWndPreview == NULL)\r
-      CreateViewWindow ();\r
-    gtk_widget_show (g_pWndPreview);\r
-\r
-    UpdatePreview (true);\r
-  }\r
-  else\r
-    gtk_widget_hide (g_pWndPreview);\r
-}\r
-\r
-static void draw_preview ()\r
-{\r
-  int width = g_pPreviewWidget->allocation.width, height = g_pPreviewWidget->allocation.height;\r
-\r
-  g_GLTable.m_pfn_qglClearColor (0, 0, 0, 1);\r
-  g_GLTable.m_pfn_qglViewport (0, 0, width, height);\r
-  g_GLTable.m_pfn_qglMatrixMode (GL_PROJECTION);\r
-  g_GLTable.m_pfn_qglLoadIdentity ();\r
-  g_GLTable.m_pfn_qglOrtho (0, width, 0, height, -1, 1);\r
-  g_GLTable.m_pfn_qglClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);\r
-       \r
-       // ^Fishman - Antializing for the preview window.\r
-       if (Antialiasing)\r
-       {\r
-               g_GLTable.m_pfn_qglEnable(GL_BLEND);\r
-               g_GLTable.m_pfn_qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
-               g_GLTable.m_pfn_qglEnable(GL_LINE_SMOOTH);\r
-       }\r
-       else\r
-       {\r
-               g_GLTable.m_pfn_qglDisable(GL_BLEND);\r
-               g_GLTable.m_pfn_qglDisable(GL_LINE_SMOOTH);\r
-       }\r
-\r
-  texfont_init ();\r
-\r
-  if (!ValidSurface ())\r
-    return;\r
-\r
-  rcUpper.left = 0;\r
-  rcUpper.right = width;\r
-  rcUpper.bottom = 0;\r
-  rcUpper.top = height;\r
-  rcLower.left = 0;\r
-  rcLower.right = width;\r
-  rcLower.bottom = 0;\r
-  rcLower.top = height;\r
-\r
-  if (VertexMode)\r
-  {\r
-    rcUpper.bottom = rcUpper.top/2;\r
-    DrawPreview (rcUpper);\r
-    g_GLTable.m_pfn_qglBegin (GL_LINES);\r
-    g_GLTable.m_pfn_qglVertex2f (rcUpper.left, rcUpper.bottom);\r
-    g_GLTable.m_pfn_qglVertex2f (rcUpper.right, rcUpper.bottom);\r
-    g_GLTable.m_pfn_qglEnd ();\r
-    rcLower.top = rcUpper.bottom-1;\r
-    DrawGrid (rcLower);\r
-    rcCoord.left = rcLower.left;\r
-    rcCoord.right = rcLower.right;\r
-    rcCoord.bottom = rcLower.bottom;\r
-    rcCoord.top = rcLower.top;\r
-    rcCoord.top = rcCoord.bottom+cyChar;\r
-    rcCoord.right = rcCoord.left + 15*cxChar;\r
-    rcGrid.left   = X0G - 3;\r
-    rcGrid.bottom = Y0G - 3;\r
-    rcGrid.right  = X0G + (int)(SFG*(Hur-Hll)) + 3;\r
-    rcGrid.top    = Y0G + (int)(SFG*(Vur-Vll)) + 3;\r
-  }\r
-  else\r
-    DrawPreview (rcUpper);\r
-}\r
-\r
-static gint expose (GtkWidget *widget, GdkEventExpose *event, gpointer data)\r
-{\r
-  if (event->count > 0)\r
-    return TRUE;\r
-\r
-  if (!g_UIGtkTable.m_pfn_glwidget_make_current (g_pPreviewWidget))\r
-  {\r
-    g_FuncTable.m_pfnSysPrintf ("GtkGenSurf: glMakeCurrent failed\n");\r
-    return TRUE;\r
-  }\r
-\r
-  draw_preview ();\r
-\r
-  g_UIGtkTable.m_pfn_glwidget_swap_buffers (g_pPreviewWidget);\r
-  g_GLTable.m_pfn_QE_CheckOpenGLForErrors ();\r
-\r
-  return TRUE;\r
-}\r
-\r
-static void button_press (GtkWidget *widget, GdkEventButton *event, gpointer data)\r
-{\r
-  POINT pt = { (long)event->x, widget->allocation.height - (long)event->y };\r
-  bool        Selected;\r
-  double      x,y;\r
-  int         i, j, k, ks;\r
-  int         i0, i1, j0, j1;\r
-\r
-  if ((!VertexMode) || (event->button != 1))\r
-    return;\r
-\r
-  if (!PtInRect (&rcGrid,pt))\r
-  {\r
-    gdk_beep ();\r
-    return;\r
-  }\r
-\r
-  x = Hll + (pt.x-X0G)/SFG;\r
-  y = Vur - (pt.y-Y0G)/SFG;\r
-  i = (int)(floor( (x-Hll)/dh - 0.5) + 1);\r
-  j = (int)(floor( (y-Vll)/dv - 0.5) + 1);\r
-  if (i < 0 || i > NH || j < 0 || j > NV)\r
-  {\r
-    gdk_beep ();\r
-    return;\r
-  }\r
-\r
-  if(!CanEdit(i,j))\r
-  {\r
-    gdk_beep ();\r
-    return;\r
-  }\r
-\r
-  // Control key pressed - add this point, or remove it if already selected\r
-  if ((event->state & GDK_CONTROL_MASK) != 0)\r
-  {\r
-    Selected = FALSE;\r
-    if (NumVerticesSelected)\r
-    {\r
-      for (k=0; k<NumVerticesSelected && !Selected; k++)\r
-      {\r
-        if(Vertex[k].i == i && Vertex[k].j == j)\r
-        {\r
-          Selected = TRUE;\r
-          ks = k;\r
-        }\r
-      }\r
-    }\r
-\r
-    // Already selected - unselect it.\r
-    if (Selected)\r
-    {\r
-      if (ks < NumVerticesSelected)\r
-      {\r
-        for (k=ks;k<NumVerticesSelected-1;k++)\r
-        {\r
-          Vertex[k].i = Vertex[k+1].i;\r
-          Vertex[k].j = Vertex[k+1].j;\r
-        }\r
-        NumVerticesSelected--;\r
-      }\r
-    }\r
-    else\r
-    {\r
-      Vertex[NumVerticesSelected].i = i;\r
-      Vertex[NumVerticesSelected].j = j;\r
-      NumVerticesSelected++;\r
-    }\r
-  }\r
-  else if ((event->state & GDK_SHIFT_MASK) != 0)\r
-  {\r
-    if (NumVerticesSelected)\r
-    {\r
-      NumVerticesSelected = 1;\r
-      i0 = min(Vertex[0].i, i);\r
-      i1 = max(Vertex[0].i, i);\r
-      j0 = min(Vertex[0].j, j);\r
-      j1 = max(Vertex[0].j, j);\r
-      for(i=i0; i<=i1; i++)\r
-      {\r
-        for(j=j0; j<=j1; j++)\r
-        {\r
-          if(i==0  && j==0 ) continue;\r
-          if(i==NH && j==0 ) continue;\r
-          if(i==0  && j==NV) continue;\r
-          if(i==NH && j==NV) continue;\r
-          if(i != Vertex[0].i || j != Vertex[0].j)\r
-          {\r
-            Vertex[NumVerticesSelected].i = i;\r
-            Vertex[NumVerticesSelected].j = j;\r
-            NumVerticesSelected++;\r
-          }\r
-        }\r
-      }\r
-    }\r
-    else\r
-    {\r
-      Vertex[0].i = i;\r
-      Vertex[0].j = j;\r
-      NumVerticesSelected = 1;\r
-    }\r
-  }\r
-  else\r
-  {\r
-    Vertex[0].i = i;\r
-    Vertex[0].j = j;\r
-    NumVerticesSelected = 1;\r
-  }\r
-\r
-  vertex_selected ();\r
-}\r
-\r
-static void motion (GtkWidget *widget, GdkEventMotion *event, gpointer data)\r
-{\r
-  POINT pt = { (long)event->x, widget->allocation.height - (long)event->y };\r
-\r
-  if (!VertexMode)\r
-    return;\r
-\r
-  if (!g_UIGtkTable.m_pfn_glwidget_make_current (g_pPreviewWidget))\r
-  {\r
-    g_FuncTable.m_pfnSysPrintf ("GtkGenSurf: glMakeCurrent failed\n");\r
-    return;\r
-  }\r
-\r
-  g_GLTable.m_pfn_qglEnable (GL_SCISSOR_TEST);\r
-  g_GLTable.m_pfn_qglScissor (rcCoord.left, rcCoord.bottom, rcCoord.right-rcCoord.left,\r
-                              rcCoord.top-rcCoord.bottom);\r
-  g_GLTable.m_pfn_qglClear (GL_COLOR_BUFFER_BIT);\r
-\r
-  if (PtInRect(&rcGrid,pt))\r
-  {\r
-    GdkCursor *cursor = gdk_cursor_new (GDK_CROSS);\r
-    gdk_window_set_cursor (g_pWndPreview->window, cursor);\r
-    gdk_cursor_unref (cursor);\r
-\r
-    char Text[32];\r
-    int x, y;\r
-\r
-    x = (int)(Hll + (pt.x-X0G)/SFG);\r
-    y = (int)(Vur - (pt.y-Y0G)/SFG);\r
-    switch(Plane)\r
-    {\r
-    case PLANE_XZ0:\r
-    case PLANE_XZ1:\r
-      sprintf(Text," x=%d, z=%d   ",(int)(floor(x-0.5)+1.) ,(int)(floor(y-0.5)+1.) );\r
-      break;\r
-    case PLANE_YZ0:\r
-    case PLANE_YZ1:\r
-      sprintf(Text," y=%d, z=%d   ",(int)(floor(x-0.5)+1.) ,(int)(floor(y-0.5)+1.) );\r
-      break;\r
-    default:\r
-      sprintf(Text," x=%d, y=%d   ",(int)(floor(x-0.5)+1.) ,(int)(floor(y-0.5)+1.) );\r
-    }\r
-\r
-    texfont_write (Text, rcCoord.left, rcCoord.top);\r
-  }\r
-  else\r
-  {\r
-    gdk_window_set_cursor (g_pWndPreview->window, NULL);\r
-  }\r
-\r
-  g_UIGtkTable.m_pfn_glwidget_swap_buffers (g_pPreviewWidget);\r
-  g_GLTable.m_pfn_QE_CheckOpenGLForErrors ();\r
-  g_GLTable.m_pfn_qglDisable (GL_SCISSOR_TEST);\r
-}\r
-\r
-static gint preview_close (GtkWidget *widget, gpointer data)\r
-{\r
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (g_object_get_data (G_OBJECT (g_pWnd), "main_preview")), FALSE);\r
-  return TRUE;\r
-}\r
-\r
-static void preview_focusout (GtkSpinButton *spin, GdkEventFocus *event, double *data)\r
-{\r
-  *data = DegreesToRadians ((double)(gtk_spin_button_get_value_as_int (spin) % 360));\r
-  UpdatePreview (false);\r
-}\r
-\r
-static gint doublevariable_spinfocusout(GtkWidget* widget, GdkEventFocus* event, gpointer data)\r
-{\r
-  preview_focusout(GTK_SPIN_BUTTON(widget), event, reinterpret_cast<double*>(data));\r
-  return FALSE;\r
-}\r
-\r
-static void preview_spin (GtkAdjustment *adj, double *data)\r
-{\r
-  *data = DegreesToRadians (adj->value);\r
-  UpdatePreview (false);\r
-}\r
-\r
-void CreateViewWindow ()\r
-{\r
-  GtkWidget *dlg, *vbox, *hbox, *label, *spin, *frame;\r
-  GtkObject *adj;\r
-\r
-#ifndef ISOMETRIC\r
-  elevation = PI/6.;\r
-  azimuth   = PI/6.;\r
-#endif\r
-\r
-  g_pWndPreview = dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);\r
-  gtk_window_set_title (GTK_WINDOW (dlg), "GtkGenSurf Preview");\r
-  gtk_signal_connect (GTK_OBJECT (dlg), "delete_event", GTK_SIGNAL_FUNC (preview_close), NULL);\r
-  gtk_signal_connect (GTK_OBJECT (dlg), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);\r
-  gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (g_pWnd));\r
-  gtk_window_set_default_size (GTK_WINDOW (dlg), 300, 400);\r
-\r
-  vbox = gtk_vbox_new (FALSE, 5);\r
-  gtk_widget_show (vbox);\r
-  gtk_container_add (GTK_CONTAINER (dlg), vbox);\r
-\r
-#ifndef ISOMETRIC\r
-  hbox = gtk_hbox_new (TRUE, 5);\r
-  gtk_widget_show (hbox);\r
-  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);\r
-  gtk_container_set_border_width (GTK_CONTAINER (hbox), 3);\r
-\r
-  label = gtk_label_new ("Elevation");\r
-  gtk_widget_show (label);\r
-  gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);\r
-  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);\r
-\r
-  adj = gtk_adjustment_new (30, -90, 90, 1, 10, 10);\r
-  gtk_signal_connect (adj, "value_changed", GTK_SIGNAL_FUNC (preview_spin), &elevation);\r
-  spin = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1, 0);\r
-  gtk_widget_show (spin);\r
-  gtk_box_pack_start (GTK_BOX (hbox), spin, FALSE, TRUE, 0);\r
-  g_signal_connect (G_OBJECT (spin), "focus_out_event", G_CALLBACK (doublevariable_spinfocusout), &elevation);\r
-\r
-  adj = gtk_adjustment_new (30, 0, 359, 1, 10, 10);\r
-  gtk_signal_connect (adj, "value_changed", GTK_SIGNAL_FUNC (preview_spin), &azimuth);\r
-  spin = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1, 0);\r
-  gtk_widget_show (spin);\r
-  gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spin), TRUE);\r
-  gtk_box_pack_end (GTK_BOX (hbox), spin, FALSE, TRUE, 0);\r
-\r
-  label = gtk_label_new ("Azimuth");\r
-  gtk_widget_show (label);\r
-  gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);\r
-  gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, TRUE, 0);\r
-  g_signal_connect (G_OBJECT (spin), "focus_out_event", G_CALLBACK (doublevariable_spinfocusout), &azimuth);\r
-#endif\r
-\r
-  frame = gtk_frame_new (NULL);\r
-  gtk_widget_show (frame);\r
-  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);\r
-  gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);\r
-\r
-  g_pPreviewWidget = g_UIGtkTable.m_pfn_glwidget_new (FALSE, NULL);\r
-\r
-  gtk_widget_set_events (g_pPreviewWidget, GDK_EXPOSURE_MASK|GDK_BUTTON_PRESS_MASK|GDK_POINTER_MOTION_MASK);\r
-  gtk_signal_connect (GTK_OBJECT (g_pPreviewWidget), "expose_event", GTK_SIGNAL_FUNC (expose), NULL);\r
-  gtk_signal_connect (GTK_OBJECT (g_pPreviewWidget), "motion_notify_event", GTK_SIGNAL_FUNC (motion), NULL);\r
-  gtk_signal_connect (GTK_OBJECT (g_pPreviewWidget), "button_press_event",\r
-                      GTK_SIGNAL_FUNC (button_press), NULL);\r
-\r
-  gtk_widget_show (g_pPreviewWidget);\r
-  gtk_container_add (GTK_CONTAINER (frame), g_pPreviewWidget);\r
-\r
-  if (Preview)\r
-    gtk_widget_show (g_pWndPreview);\r
-\r
-  UpdatePreview (true);\r
-}\r
-\r
-//=============================================================\r
-/* DrawPreview */\r
-void DrawPreview (RECT rc)\r
-{\r
-#define COSXA 0.8660254037844\r
-#define SINXA 0.5\r
-#define COSYA 0.8660254037844\r
-#define SINYA 0.5\r
-\r
-  double     L;\r
-  double     x,y;\r
-  int        i, j;\r
-  POINT      pt[8];\r
-  XYZ        v[8];\r
-  char axis[3][2] = {"X","Y","Z"};\r
-\r
-#ifndef ISOMETRIC\r
-  evaluate();\r
-#endif\r
-\r
-  XLo = xmin;\r
-  XHi = xmax;\r
-  YLo = ymin;\r
-  YHi = ymax;\r
-  ZLo = zmin;\r
-  ZHi = zmax;\r
-  switch (Plane)\r
-  {\r
-  case PLANE_XY1:\r
-    ZHi = backface;\r
-    break;\r
-  case PLANE_XZ0:\r
-    YLo = backface;\r
-    break;\r
-  case PLANE_XZ1:\r
-    YHi = backface;\r
-    break;\r
-  case PLANE_YZ0:\r
-    XLo = backface;\r
-    break;\r
-  case PLANE_YZ1:\r
-    XHi = backface;\r
-    break;\r
-  default:\r
-    ZLo = backface;\r
-  }\r
-\r
-\r
-\r
-  GetScaleFactor(rc);\r
-       //PEN_GRID\r
-       g_GLTable.m_pfn_qglLineWidth (1);\r
-       g_GLTable.m_pfn_qglColor3f (0, 1, 0);\r
-       g_GLTable.m_pfn_qglDisable (GL_LINE_STIPPLE);\r
-\r
-    if (Decimate > 0 && (Game != QUAKE3 || UsePatches==0) )\r
-    {\r
-      XYZ  *vv;\r
-\r
-      vv   = (XYZ *) malloc(gNumNodes * sizeof(XYZ));\r
-      for(i=0; i<gNumNodes; i++)\r
-      {\r
-        for(j=0; j<3; j++)\r
-          vv[i].p[j] = (double)(gNode[i].p[j]);\r
-        project(&vv[i]);\r
-      }\r
-\r
-      for(i=0; i<gNumTris; i++)\r
-      {\r
-        for(j=0; j<3; j++)\r
-          Scale(rc,vv[gTri[i].v[j]],&pt[j]);\r
-\r
-        g_GLTable.m_pfn_qglBegin (GL_LINE_STRIP);\r
-        g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);\r
-        g_GLTable.m_pfn_qglVertex2f (pt[1].x, pt[1].y);\r
-        g_GLTable.m_pfn_qglVertex2f (pt[2].x, pt[2].y);\r
-        g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);\r
-        g_GLTable.m_pfn_qglEnd ();\r
-      }\r
-      free(vv);\r
-    }\r
-    else if (Game==QUAKE3 && UsePatches!=0)\r
-    {\r
-      int              axis, ii, jj, k;\r
-      float    u, v;\r
-      XYZ              uv[3][3];\r
-      XYZ              Ctrl[3],out;\r
-\r
-      switch (Plane)\r
-      {\r
-      case PLANE_XY0:\r
-      case PLANE_XY1:\r
-        k = 2;\r
-        break;\r
-      case PLANE_XZ0:\r
-      case PLANE_XZ1:\r
-        k = 1;\r
-        break;\r
-      default:\r
-        k = 0;\r
-      }\r
-      for(i=0; i<NH; i+=2)\r
-      {\r
-        for(j=0; j<NV; j+=2)\r
-        {\r
-          VectorCopy(xyz[i  ][j  ].p,uv[0][0].p);\r
-          VectorCopy(xyz[i+1][j  ].p,uv[1][0].p);\r
-          VectorCopy(xyz[i+2][j  ].p,uv[2][0].p);\r
-          VectorCopy(xyz[i  ][j+1].p,uv[0][1].p);\r
-          VectorCopy(xyz[i+1][j+1].p,uv[1][1].p);\r
-          VectorCopy(xyz[i+2][j+1].p,uv[2][1].p);\r
-          VectorCopy(xyz[i  ][j+2].p,uv[0][2].p);\r
-          VectorCopy(xyz[i+1][j+2].p,uv[1][2].p);\r
-          VectorCopy(xyz[i+2][j+2].p,uv[2][2].p);\r
-          uv[1][0].p[k] = (4*xyz[i+1][j  ].p[k] - xyz[i  ][j  ].p[k] - xyz[i+2][j  ].p[k])/2;\r
-          uv[0][1].p[k] = (4*xyz[i  ][j+1].p[k] - xyz[i  ][j  ].p[k] - xyz[i  ][j+2].p[k])/2;\r
-          uv[2][1].p[k] = (4*xyz[i+2][j+1].p[k] - xyz[i+2][j  ].p[k] - xyz[i+2][j+2].p[k])/2;\r
-          uv[1][2].p[k] = (4*xyz[i+1][j+2].p[k] - xyz[i  ][j+2].p[k] - xyz[i+2][j+2].p[k])/2;\r
-          uv[1][1].p[k] = (16*xyz[i+1][j+1].p[k] -\r
-                           xyz[i  ][j  ].p[k] - 2*xyz[i+1][j  ].p[k] -  xyz[i+2][j  ].p[k] -\r
-                           2*xyz[i  ][j+1].p[k]                        -2*xyz[i+2][j+1].p[k] -\r
-                           xyz[i  ][j+2].p[k] - 2*xyz[i+1][j+2].p[k] -  xyz[i+2][j+2].p[k]   )/4;\r
-\r
-          for(ii=0; ii<=SUBDIVS; ii++)\r
-          {\r
-            if(ii==0 || ii==SUBDIVS/2 || ii==SUBDIVS)\r
-                                               {\r
-                                                       g_GLTable.m_pfn_qglLineWidth (1);\r
-                                                       g_GLTable.m_pfn_qglColor3f (0, 1, 0);\r
-                                                       g_GLTable.m_pfn_qglDisable (GL_LINE_STIPPLE);\r
-                                                       // PEN_GRID\r
-                                               }\r
-            else\r
-                                               {\r
-                                                       g_GLTable.m_pfn_qglLineWidth (1);\r
-                                                       g_GLTable.m_pfn_qglColor3f (0, 1, 0);\r
-                                                       g_GLTable.m_pfn_qglLineStipple (1, 0xF0F0);\r
-                                                       g_GLTable.m_pfn_qglEnable (GL_LINE_STIPPLE);\r
-              // PEN_DASH\r
-                                               }\r
-\r
-            u = (float)(ii)/(float)(SUBDIVS);\r
-            for(jj=0; jj<3; jj++)\r
-            {\r
-              for(axis=0; axis<3; axis++)\r
-              {\r
-                float  a, b, c;\r
-                float  qA, qB, qC;\r
-                a = (float)uv[0][jj].p[axis];\r
-                b = (float)uv[1][jj].p[axis];\r
-                c = (float)uv[2][jj].p[axis];\r
-                qA = a - 2 * b + c;\r
-                qB = 2 * b - 2 * a;\r
-                qC = a;\r
-                Ctrl[jj].p[axis] = qA * u * u + qB * u + qC;\r
-              }\r
-            }\r
-            VectorCopy(Ctrl[0].p,out.p);\r
-            project(&out);\r
-            Scale(rc,out,&pt[0]);\r
-            g_GLTable.m_pfn_qglBegin (GL_LINE_STRIP);\r
-            g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);\r
-            for(jj=1; jj<=SUBDIVS; jj++)\r
-            {\r
-              v = (float)(jj)/(float)(SUBDIVS);\r
-              for (axis = 0 ; axis < 3 ; axis++) \r
-              {\r
-                float  a, b, c;\r
-                float  qA, qB, qC;\r
-                a = (float)Ctrl[0].p[axis];\r
-                b = (float)Ctrl[1].p[axis];\r
-                c = (float)Ctrl[2].p[axis];\r
-                qA = a - 2 * b + c;\r
-                qB = 2 * b - 2 * a;\r
-                qC = a;\r
-                out.p[axis] = qA * v * v + qB * v + qC;\r
-              }\r
-              project(&out);\r
-              Scale(rc,out,&pt[0]);\r
-              g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);\r
-            }\r
-            g_GLTable.m_pfn_qglEnd ();\r
-          }\r
-          for(jj=0; jj<=SUBDIVS; jj++)\r
-          {\r
-            if(jj==0 || jj==SUBDIVS/2 || jj==SUBDIVS)\r
-                                               {\r
-                                                       g_GLTable.m_pfn_qglLineWidth (1);\r
-                                                       g_GLTable.m_pfn_qglColor3f (0, 1, 0);\r
-                                                       g_GLTable.m_pfn_qglDisable (GL_LINE_STIPPLE);\r
-              // PEN_GRID\r
-                                               }\r
-            else\r
-                                               {\r
-                                                       g_GLTable.m_pfn_qglLineWidth (1);\r
-                                                       g_GLTable.m_pfn_qglColor3f (0, 1, 0);\r
-                                                       g_GLTable.m_pfn_qglLineStipple (1, 0xF0F0);\r
-                                                       g_GLTable.m_pfn_qglEnable (GL_LINE_STIPPLE);\r
-                                                       // PEN_DASH\r
-                                               }\r
-\r
-            v = (float)(jj)/(float)(SUBDIVS);\r
-            for(ii=0; ii<3; ii++)\r
-            {\r
-              for(axis=0; axis<3; axis++)\r
-              {\r
-                float  a, b, c;\r
-                float  qA, qB, qC;\r
-                a = (float)uv[ii][0].p[axis];\r
-                b = (float)uv[ii][1].p[axis];\r
-                c = (float)uv[ii][2].p[axis];\r
-                qA = a - 2 * b + c;\r
-                qB = 2 * b - 2 * a;\r
-                qC = a;\r
-                Ctrl[ii].p[axis] = qA * v * v + qB * v + qC;\r
-              }\r
-            }\r
-            VectorCopy(Ctrl[0].p,out.p);\r
-            project(&out);\r
-            Scale(rc,out,&pt[0]);\r
-            g_GLTable.m_pfn_qglBegin (GL_LINE_STRIP);\r
-            g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);\r
-            for(ii=1; ii<=SUBDIVS; ii++)\r
-            {\r
-              u = (float)(ii)/(float)(SUBDIVS);\r
-              for (axis = 0 ; axis < 3 ; axis++) \r
-              {\r
-                float  a, b, c;\r
-                float  qA, qB, qC;\r
-                a = (float)Ctrl[0].p[axis];\r
-                b = (float)Ctrl[1].p[axis];\r
-                c = (float)Ctrl[2].p[axis];\r
-                qA = a - 2 * b + c;\r
-                qB = 2 * b - 2 * a;\r
-                qC = a;\r
-                out.p[axis] = qA * u * u + qB * u + qC;\r
-              }\r
-              project(&out);\r
-              Scale(rc,out,&pt[0]);\r
-              g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);\r
-            }\r
-            g_GLTable.m_pfn_qglEnd ();\r
-          }\r
-        }\r
-      }\r
-    }\r
-    else\r
-    {\r
-      for(i=0; i<=NH; i++)\r
-      {\r
-        Scale(rc,xyz[i][0],&pt[0]);\r
-        g_GLTable.m_pfn_qglBegin (GL_LINE_STRIP);\r
-        g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);\r
-        for(j=1; j<=NV; j++)\r
-        {\r
-          Scale(rc,xyz[i][j],&pt[0]);\r
-          g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);\r
-        }\r
-        g_GLTable.m_pfn_qglEnd ();\r
-      }\r
-      for(j=0; j<=NV; j++)\r
-      {\r
-        Scale(rc,xyz[0][j],&pt[0]);\r
-        g_GLTable.m_pfn_qglBegin (GL_LINE_STRIP);\r
-        g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);\r
-        for(i=1; i<=NH; i++)\r
-        {\r
-          Scale(rc,xyz[i][j],&pt[0]);\r
-          g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);\r
-        }\r
-        g_GLTable.m_pfn_qglEnd ();\r
-      }\r
-    }\r
-\r
-  if(Game!=QUAKE3 || UsePatches==0)\r
-  {\r
-    // Draw lines from corners to base, and lines around base\r
-    for(i=0; i<=NH; i+=NH)\r
-    {\r
-      for(j=0; j<=NV; j+=NV)\r
-      {\r
-        VectorCopy(xyz[i][j].p, v[0].p);\r
-        switch(Plane)\r
-        {\r
-        case PLANE_XZ0:\r
-        case PLANE_XZ1:\r
-          v[0].p[1] = backface;\r
-          break;\r
-        case PLANE_YZ0:\r
-        case PLANE_YZ1:\r
-          v[0].p[0] = backface;\r
-          break;\r
-        default:\r
-          v[0].p[2] = backface;\r
-        }\r
-        Scale(rc,xyz[i][j],&pt[0]);\r
-#ifndef ISOMETRIC\r
-        project(&v[0]);\r
-#endif\r
-        Scale(rc,v[0],&pt[1]);\r
-        g_GLTable.m_pfn_qglBegin (GL_LINE_STRIP);\r
-        g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);\r
-        g_GLTable.m_pfn_qglVertex2f (pt[1].x, pt[1].y);\r
-        g_GLTable.m_pfn_qglEnd ();\r
-      }\r
-    }\r
-    VectorCopy(xyz[ 0][ 0].p, v[0].p);\r
-    VectorCopy(xyz[NH][ 0].p, v[1].p);\r
-    VectorCopy(xyz[NH][NV].p, v[2].p);\r
-    VectorCopy(xyz[ 0][NV].p, v[3].p);\r
-    switch(Plane)\r
-    {\r
-    case PLANE_XZ0:\r
-    case PLANE_XZ1:\r
-      v[0].p[1] = backface;;\r
-      v[1].p[1] = v[0].p[1];\r
-      v[2].p[1] = v[0].p[1];\r
-      v[3].p[1] = v[0].p[1];\r
-      break;\r
-    case PLANE_YZ0:\r
-    case PLANE_YZ1:\r
-      v[0].p[0] = backface;\r
-      v[1].p[0] = v[0].p[0];\r
-      v[2].p[0] = v[0].p[0];\r
-      v[3].p[0] = v[0].p[0];\r
-      break;\r
-    default:\r
-      v[0].p[2] = backface;\r
-      v[1].p[2] = v[0].p[2];\r
-      v[2].p[2] = v[0].p[2];\r
-      v[3].p[2] = v[0].p[2];\r
-    }\r
-#ifndef ISOMETRIC\r
-    project(&v[3]);\r
-#endif\r
-    Scale(rc,v[3],&pt[0]);\r
-    g_GLTable.m_pfn_qglBegin (GL_LINE_STRIP);\r
-    g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);\r
-    for(i=0; i<3; i++)\r
-    {\r
-#ifndef ISOMETRIC\r
-      project(&v[i]);\r
-#endif\r
-      Scale(rc,v[i],&pt[1]);\r
-      g_GLTable.m_pfn_qglVertex2f (pt[1].x, pt[1].y);\r
-    }\r
-    g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);\r
-    g_GLTable.m_pfn_qglEnd ();\r
-  }\r
-\r
-  g_GLTable.m_pfn_qglLineWidth (1);\r
-  g_GLTable.m_pfn_qglColor3f (0, 1, 0);\r
-  g_GLTable.m_pfn_qglDisable (GL_LINE_STIPPLE);\r
-\r
-#ifdef ISOMETRIC\r
-  // Draw small depiction of coordinate axes\r
-  pt[0].x = rc.right  - cxChar   - cxChar/2 -  cyChar;\r
-  pt[0].y = rc.bottom - cyChar/2 - cxChar/2;\r
-  pt[1].x = pt[0].x + (int)(cyChar*COSXA);\r
-  pt[1].y = pt[0].y - (int)(cyChar*SINXA);\r
-  MoveToEx(hdc,pt[0].x,pt[0].y,NULL);\r
-  LineTo(hdc,pt[1].x,pt[1].y);\r
-  SetTextAlign(hdc,TA_LEFT | TA_TOP);\r
-  TextOut(hdc,pt[1].x,pt[1].y-cyChar/2,"X",1);\r
-  pt[1].x = pt[0].x - (int)(cyChar*COSYA);\r
-  pt[1].y = pt[0].y - (int)(cyChar*SINYA);\r
-  MoveToEx(hdc,pt[0].x,pt[0].y,NULL);\r
-  LineTo(hdc,pt[1].x,pt[1].y);\r
-  SetTextAlign(hdc,TA_RIGHT | TA_TOP);\r
-  TextOut(hdc,pt[1].x,pt[1].y-cyChar/2,"Y",1);\r
-  pt[1].x = pt[0].x;\r
-  pt[1].y = pt[0].y - cyChar;\r
-  MoveToEx(hdc,pt[0].x,pt[0].y,NULL);\r
-  LineTo(hdc,pt[1].x,pt[1].y);\r
-  SetTextAlign(hdc,TA_CENTER | TA_BOTTOM);\r
-  TextOut(hdc,pt[1].x,pt[1].y,"Z",1);\r
-#else\r
-  L = 2*(double)cyChar/SF;\r
-  v[0].p[0] = 0.;\r
-  v[0].p[1] = 0.;\r
-  v[0].p[2] = 0.;\r
-  v[1].p[0] = L;\r
-  v[1].p[1] = 0.;\r
-  v[1].p[2] = 0.;\r
-  v[2].p[0] = 0.;\r
-  v[2].p[1] = L;\r
-  v[2].p[2] = 0.;\r
-  v[3].p[0] = 0.;\r
-  v[3].p[1] = 0.;\r
-  v[3].p[2] = L;\r
-  for(i=0; i<=3; i++)\r
-  {\r
-    project(&v[i]);\r
-    Scale(rc,v[i],&pt[i]);\r
-  }\r
-  for(i=1; i<=3; i++)\r
-  {\r
-    pt[i].x += -pt[0].x + rc.right  - 2*cyChar;\r
-    pt[i].y += -pt[0].y + rc.bottom + 2*cyChar;\r
-  }\r
-  pt[0].x = rc.right  - 2*cyChar;\r
-  pt[0].y = rc.bottom + 2*cyChar;\r
-\r
-  for(i=1; i<=3; i++)\r
-  {\r
-    g_GLTable.m_pfn_qglBegin (GL_LINES);\r
-    g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);\r
-    g_GLTable.m_pfn_qglVertex2f (pt[i].x, pt[i].y);\r
-    g_GLTable.m_pfn_qglEnd ();\r
-    texfont_write (axis[i-1], pt[i].x-cxChar/2,pt[i].y+cyChar/2);\r
-  }\r
-#endif\r
-\r
-  // Draw player model's bounding box in red to give a sense of scale\r
-  // PEN_RED\r
-       g_GLTable.m_pfn_qglLineWidth (2);\r
-       g_GLTable.m_pfn_qglColor3f (1, 0, 0);\r
-       g_GLTable.m_pfn_qglDisable (GL_LINE_STIPPLE);\r
-\r
-  switch(Plane)\r
-  {\r
-  case PLANE_XY1:\r
-    v[0].p[0] = xyz[NH/2][NV/2].p[0] + PlayerBox[Game].x[0];\r
-    v[0].p[1] = xyz[NH/2][NV/2].p[1] + PlayerBox[Game].y[0];\r
-    v[0].p[2] = zmin - PlayerBox[Game].z[0] - 32;\r
-    break;\r
-  case PLANE_XZ0:\r
-    v[0].p[0] = (xmax+xmin)/2 + PlayerBox[Game].x[0];\r
-    v[0].p[1] = ymax+64;\r
-    v[0].p[2] = zmin;\r
-    break;\r
-  case PLANE_XZ1:\r
-    v[0].p[0] = (xmax+xmin)/2 + PlayerBox[Game].x[0];\r
-    v[0].p[1] = ymin-64;\r
-    v[0].p[2] = zmin;\r
-    break;\r
-  case PLANE_YZ0:\r
-    v[0].p[0] = xmax+64;\r
-    v[0].p[1] = (ymax+ymin)/2 + PlayerBox[Game].y[0];\r
-    v[0].p[2] = zmin;\r
-    break;\r
-  case PLANE_YZ1:\r
-    v[0].p[0] = xmin-64;\r
-    v[0].p[1] = (ymax+ymin)/2 + PlayerBox[Game].y[0];\r
-    v[0].p[2] = zmin;\r
-    break;\r
-  default:\r
-    // Put player on a node. For patches, put on an even numbered node.\r
-    if(Game==QUAKE3 && UsePatches!=0)\r
-    {\r
-      if(NH > 2)\r
-        x = Hll + dh * (int)(NH/2 + 1);\r
-      else\r
-        x = Hll + dh * (int)(NH/2);\r
-      if(NV > 2)\r
-        y = Vll + dv * (int)(NV/2 + 1);\r
-      else\r
-        y = Vll + dv * (int)(NV/2);\r
-    }\r
-    else\r
-    {\r
-      if(NH > 1)\r
-        x = Hll + dh * (int)(NH/2);\r
-      else\r
-        x = Hll + dh/2;\r
-      if(NV > 1)\r
-        y = Vll + dv * (int)(NV/2);\r
-      else\r
-        y = Vll + dv/2;\r
-    }\r
-//             x = (Hll+Hur)/2.;\r
-//             y = (Vll+Vur)/2.;\r
-    v[0].p[0] = x + PlayerBox[Game].x[0];\r
-    v[0].p[1] = y + PlayerBox[Game].y[0];\r
-    v[0].p[2] = PlayerStartZ(x,y) + PlayerBox[Game].z[0] + 8; // add 8 cuz I'm a pessimist\r
-  }\r
-  v[1].p[0] = v[0].p[0] + PlayerBox[Game].x[1] - PlayerBox[Game].x[0];\r
-  v[1].p[1] = v[0].p[1];\r
-  v[1].p[2] = v[0].p[2];\r
-  v[2].p[0] = v[1].p[0];\r
-  v[2].p[1] = v[1].p[1] + PlayerBox[Game].y[1] - PlayerBox[Game].y[0];\r
-  v[2].p[2] = v[0].p[2];\r
-  v[3].p[0] = v[0].p[0];\r
-  v[3].p[1] = v[2].p[1];\r
-  v[3].p[2] = v[0].p[2];\r
-  VectorCopy(v[0].p,v[4].p);\r
-  VectorCopy(v[1].p,v[5].p);\r
-  VectorCopy(v[2].p,v[6].p);\r
-  VectorCopy(v[3].p,v[7].p);\r
-  v[4].p[2] += PlayerBox[Game].z[1] - PlayerBox[Game].z[0];\r
-  v[5].p[2] += PlayerBox[Game].z[1] - PlayerBox[Game].z[0];\r
-  v[6].p[2] += PlayerBox[Game].z[1] - PlayerBox[Game].z[0];\r
-  v[7].p[2] += PlayerBox[Game].z[1] - PlayerBox[Game].z[0];\r
-  for(i=0; i<=7; i++)\r
-  {\r
-#ifndef ISOMETRIC\r
-    project(&v[i]);\r
-#endif\r
-    Scale(rc,v[i],&pt[i]);\r
-  }\r
-  g_GLTable.m_pfn_qglBegin (GL_LINE_STRIP);\r
-  g_GLTable.m_pfn_qglVertex2f (pt[3].x, pt[3].y);\r
-  for(i=0; i<=3; i++)\r
-    g_GLTable.m_pfn_qglVertex2f (pt[i].x, pt[i].y);\r
-  g_GLTable.m_pfn_qglEnd ();\r
-  g_GLTable.m_pfn_qglBegin (GL_LINE_STRIP);\r
-  g_GLTable.m_pfn_qglVertex2f (pt[7].x, pt[7].y);\r
-  for(i=4; i<=7; i++)\r
-    g_GLTable.m_pfn_qglVertex2f (pt[i].x, pt[i].y);\r
-  g_GLTable.m_pfn_qglEnd ();\r
-  g_GLTable.m_pfn_qglBegin (GL_LINES);\r
-  for(i=0; i<=3; i++)\r
-  {\r
-    g_GLTable.m_pfn_qglVertex2f (pt[i].x,pt[i].y);\r
-    g_GLTable.m_pfn_qglVertex2f (pt[i+4].x,pt[i+4].y);\r
-  }\r
-  g_GLTable.m_pfn_qglEnd ();\r
-\r
-  g_GLTable.m_pfn_qglLineWidth (1);\r
-  g_GLTable.m_pfn_qglColor3f (0, 1, 0);\r
-  g_GLTable.m_pfn_qglDisable (GL_LINE_STIPPLE);\r
-}\r
-//=============================================================\r
-void DrawGrid(RECT rc)\r
-{\r
-  int        i, j, k;\r
-  double     h,w,x,y;\r
-  POINT      pt[2];\r
-  RECT       rcBox;\r
-\r
-  w = (double)(rc.right-rc.left+1) - cxChar;\r
-  h = (double)(rc.top-rc.bottom+1) - cxChar - cyChar;\r
-\r
-  SFG = w/(Hur-Hll);\r
-  SFG = min(SFG, h/(Vur-Vll));\r
-\r
-  // Center drawing\r
-  X0G = (int)(rc.left + rc.right - (int)(SFG*(Hur-Hll)))/2;\r
-  Y0G = (int)(rc.top + rc.bottom + cyChar - (int)(SFG*(Vur-Vll)))/2;\r
-\r
-  g_GLTable.m_pfn_qglLineWidth (2);\r
-  g_GLTable.m_pfn_qglColor3f (0, 1, 0);\r
-  g_GLTable.m_pfn_qglDisable (GL_LINE_STIPPLE);\r
-\r
-  pt[0].y = Y0G;\r
-  pt[1].y = Y0G + (int)(SFG*(Vur-Vll));\r
-  g_GLTable.m_pfn_qglBegin (GL_LINES);\r
-  for(i=0; i<=NH; i++)\r
-  {\r
-    x = Hll + i * dh;\r
-    pt[0].x = X0G + (int)(SFG*(x-Hll));\r
-    g_GLTable.m_pfn_qglVertex2f(pt[0].x, pt[0].y);\r
-    g_GLTable.m_pfn_qglVertex2f(pt[0].x, pt[1].y);\r
-  }\r
-  g_GLTable.m_pfn_qglEnd ();\r
-  pt[0].x = X0G;\r
-  pt[1].x = X0G + (int)(SFG*(Hur-Hll));\r
-  g_GLTable.m_pfn_qglBegin (GL_LINES);\r
-  for(i=0; i<=NV; i++)\r
-  {\r
-    y = Vll + i * dv;\r
-    pt[0].y = Y0G + (int)(SFG*(Vur-y));\r
-    g_GLTable.m_pfn_qglVertex2f (pt[0].x,pt[0].y);\r
-    g_GLTable.m_pfn_qglVertex2f (pt[1].x,pt[0].y);\r
-  }\r
-  g_GLTable.m_pfn_qglEnd ();\r
-\r
-  g_GLTable.m_pfn_qglLineWidth (1);\r
-\r
-  // Draw axes\r
-  pt[0].x = rc.right  - cyChar - cxChar - cyChar/2;\r
-  pt[0].y = rc.bottom + cyChar/2;\r
-  pt[1].x = pt[0].x + cyChar;\r
-  pt[1].y = pt[0].y;\r
-  g_GLTable.m_pfn_qglBegin (GL_LINES);\r
-  g_GLTable.m_pfn_qglVertex2f (pt[0].x,pt[0].y);\r
-  g_GLTable.m_pfn_qglVertex2f (pt[1].x,pt[1].y);\r
-  g_GLTable.m_pfn_qglEnd ();\r
-  switch(Plane)\r
-  {\r
-  case PLANE_YZ0:\r
-  case PLANE_YZ1:\r
-    texfont_write ("Y", pt[1].x, pt[1].y+cyChar/2);\r
-    break;\r
-  default:\r
-    texfont_write ("X", pt[1].x, pt[1].y+cyChar/2);\r
-  }\r
-  pt[1].x = pt[0].x;\r
-  pt[1].y = pt[0].y + cyChar;\r
-  g_GLTable.m_pfn_qglBegin (GL_LINES);\r
-  g_GLTable.m_pfn_qglVertex2f (pt[0].x,pt[0].y);\r
-  g_GLTable.m_pfn_qglVertex2f (pt[1].x,pt[1].y);\r
-  g_GLTable.m_pfn_qglEnd ();\r
-  switch(Plane)\r
-  {\r
-  case PLANE_XY0:\r
-  case PLANE_XY1:\r
-    texfont_write ("Y", pt[1].x-cyChar/2, pt[1].y+cyChar);\r
-    break;\r
-  default:\r
-    texfont_write ("Z", pt[1].x-cyChar/2, pt[1].y+cyChar);\r
-  }\r
-\r
-  // Denote fixed points with a 5x5 red rectangle\r
-  for(i=0; i<=NH; i++)\r
-  {\r
-    for(j=0; j<=NV; j++)\r
-    {\r
-      if(xyz[i][j].fixed)\r
-      {\r
-        x = Hll + i*dh;\r
-        y = Vll + j*dv;\r
-        rcBox.left   = X0G + (int)(SFG*(x-Hll)) - 2;\r
-        rcBox.top    = Y0G + (int)(SFG*(Vur-y)) + 2;\r
-        rcBox.right  = rcBox.left + 5;\r
-        rcBox.bottom = rcBox.top  - 5;\r
-\r
-        DRAW_QUAD (rcBox, 1,0,0);\r
-      }\r
-    }\r
-  }\r
-\r
-  // Denote currently selected point with a 5x5 green rectangle\r
-  if (NumVerticesSelected)\r
-  {\r
-    for(k=0; k<NumVerticesSelected; k++)\r
-    {\r
-      x = Hll + Vertex[k].i*dh;\r
-      y = Vll + Vertex[k].j*dv;\r
-      rcBox.left   = X0G + (int)(SFG*(x-Hll)) - 2;\r
-      rcBox.top    = Y0G + (int)(SFG*(Vur-y)) + 2;\r
-      rcBox.right  = rcBox.left + 5;\r
-      rcBox.bottom = rcBox.top  - 5;\r
-\r
-      DRAW_QUAD (rcBox, 0,1,0);\r
-    }\r
-  }\r
-\r
-  // Unmovable vertices\r
-  for(i=0; i<=NH; i++)\r
-  {\r
-    for(j=0; j<=NV; j++)\r
-    {\r
-      if(!CanEdit(i,j))\r
-      {\r
-        x = Hll + i*dh;\r
-        y = Vll + j*dv;\r
-        rcBox.left   = X0G + (int)(SFG*(x-Hll)) - 2;\r
-        rcBox.top    = Y0G + (int)(SFG*(Vur-y)) + 2;\r
-        rcBox.right  = rcBox.left + 5;\r
-        rcBox.bottom = rcBox.top  - 5;\r
-\r
-        DRAW_QUAD (rcBox, 1,1,0);\r
-      }\r
-    }\r
-  }\r
-\r
-  // Legend\r
-  rcBox.left   = rc.left + cxChar/2 - 2;\r
-  rcBox.top    = rc.top  - cyChar/2 - 2;\r
-  rcBox.right  = rcBox.left + 5;\r
-  rcBox.bottom = rcBox.top  - 5;\r
-  DRAW_QUAD (rcBox, 1,0,0);\r
-  texfont_write ("Fixed points", rcBox.right+cxChar,rcBox.top-4+cyChar/2);\r
-\r
-  rcBox.top    -= cyChar;\r
-  rcBox.bottom -= cyChar;\r
-  DRAW_QUAD (rcBox, 1,1,0);\r
-  texfont_write ("Not movable", rcBox.right+cxChar, rcBox.top-4+cyChar/2);\r
-\r
-  rcBox.top    -= cyChar;\r
-  rcBox.bottom -= cyChar;\r
-  DRAW_QUAD (rcBox, 0,1,0);\r
-  texfont_write ("Selected", rcBox.right+cxChar, rcBox.top-4+cyChar/2);\r
-}\r
-\r
-//=============================================================\r
-void GetScaleFactor(RECT rc)\r
-{\r
-#ifdef ISOMETRIC\r
-       double      h, w;\r
-\r
-       w = (double)(rc.right-rc.left+1) - cxChar;\r
-       h = (double)(rc.top-rc.bottom+1) - cxChar;\r
-\r
-       SF = w/( (XHi-XLo)*COSXA + (YHi-YLo)*COSYA );\r
-       SF = min(SF, h/( (XHi-XLo)*SINXA + (YHi-YLo)*SINYA + ZHi-ZLo ) );\r
-       // Center drawing\r
-       X0 = (int)(rc.left + rc.right - (int)(SF*( (XHi-XLo)*COSXA + (YHi-YLo)*COSYA )) )/2;\r
-       Y0 = (int)(rc.top + rc.bottom - (int)(SF*( (XHi-XLo)*SINXA + (YHi-YLo)*SINYA + ZHi-ZLo) ))/2;\r
-\r
-#else\r
-       double      h, w;\r
-\r
-       w = (double)(rc.right-rc.left+1) - cxChar;\r
-       h = (double)(rc.top-rc.bottom+1) - cxChar;\r
-\r
-       SF = w/(Hhi-Hlo);\r
-       SF = min(SF, h/(Vhi-Vlo) );\r
-       X0 = (int)(rc.left + rc.right - (int)(SF*(Hhi-Hlo)))/2;\r
-       Y0 = (int)(rc.top + rc.bottom + (int)(SF*(Vhi-Vlo)))/2;\r
-#endif\r
-}\r
-\r
-//=============================================================\r
-void Scale(RECT rc,XYZ xyz,POINT *pt)\r
-{\r
-\r
-#ifdef ISOMETRIC\r
-\r
-       pt[0].x = X0 + (int)(SF*( (xyz.p[0]-XLo)*COSXA +\r
-                              (YHi-xyz.p[1])*COSYA   ));\r
-       pt[0].y = Y0 + (int)(SF*(  ZHi-xyz.p[2] +\r
-                                 (YHi-xyz.p[1])*SINYA +\r
-                                                 (XHi-xyz.p[0])*SINXA   ));\r
-#else\r
-       pt[0].x = X0 + (int)(SF*( xyz.pp[0] - Hlo ) );\r
-       pt[0].y = Y0 - (int)(SF*( Vhi - xyz.pp[1] ) );\r
-#endif\r
-\r
-}\r
-\r
-#ifndef ISOMETRIC\r
-/* ======================================================================= */\r
-void project(XYZ *v)\r
-{\r
-       // project a 3D point (x,y,z) onto view plane\r
-       double x, y, z, xa, ya, za;\r
-\r
-       x = v->p[0];\r
-       y = v->p[1];\r
-       z = v->p[2];\r
-\r
-       // yaw\r
-       xa = ct[0]*x - st[0]*z;\r
-       za = st[0]*x + ct[0]*z;\r
-\r
-       // roll\r
-       x  = ct[1]*xa + st[1]*y;\r
-       ya = ct[1]*y  - st[1]*xa;\r
-\r
-       // azimuth\r
-       z  = ct[2]*za - st[2]*ya;\r
-       y  = ct[2]*ya + st[2]*za;\r
-\r
-       // horizontal and vertical projections:\r
-//     v->pp[0] = D*x/z;\r
-//     v->pp[1] = D*y/z;\r
-       v->pp[0] = -y;\r
-       v->pp[1] =  x;\r
-       v->pp[2] =  z;\r
-\r
-       // NOTE: if perspective transformation is desired,\r
-       // set "persp" to the range from the surface,\r
-       // then:\r
-       // v->projected_h = -v->projected_h * persp/(v->projected_z-persp);\r
-       // v->projected_v = -v->projected_v * persp/(v->projected_z-persp);\r
-}\r
-/*=======================================================================*/\r
-void evaluate()\r
-{\r
-       int i, j;\r
-       XYZ v[4];\r
-       \r
-       if(elevation > PI) elevation -= 2.*PI;\r
-       roll = elevation * sin(azimuth);\r
-       yaw  = 1.5*PI + elevation*cos(azimuth);\r
-\r
-       //      Find angles from midpoint to viewpoint:\r
-       st[0] = sin(yaw);\r
-       st[1] = sin(roll);\r
-       st[2] = sin(azimuth);\r
-       ct[0] = cos(yaw);\r
-       ct[1] = cos(roll);\r
-       ct[2] = cos(azimuth);\r
-\r
-       for(i=0; i<=NH; i++)\r
-       {\r
-               for(j=0; j<=NV; j++)\r
-               {\r
-                       project(&xyz[i][j]);\r
-               }\r
-       }\r
-\r
-       Hhi = xyz[0][0].pp[0];\r
-       Hlo = Hhi;\r
-       Vhi = xyz[0][0].pp[1];\r
-       Vlo = Vhi;\r
-       for(i=0; i<=NH; i++)\r
-       {\r
-               for(j=0; j<=NV; j++)\r
-               {\r
-                       Hlo = min(Hlo,xyz[i][j].pp[0]);\r
-                       Hhi = max(Hhi,xyz[i][j].pp[0]);\r
-                       Vlo = min(Vlo,xyz[i][j].pp[1]);\r
-                       Vhi = max(Vhi,xyz[i][j].pp[1]);\r
-               }\r
-       }\r
-\r
-       // Include backface in min-max\r
-       VectorCopy(xyz[ 0][ 0].p,v[0].p);\r
-       VectorCopy(xyz[NH][ 0].p,v[1].p);\r
-       VectorCopy(xyz[NH][NV].p,v[2].p);\r
-       VectorCopy(xyz[ 0][NV].p,v[3].p);\r
-       switch(Plane)\r
-       {\r
-       case PLANE_XZ0:\r
-       case PLANE_XZ1:\r
-               v[0].p[1] = backface;\r
-               v[1].p[1] = v[0].p[1];\r
-               v[2].p[1] = v[0].p[1];\r
-               v[3].p[1] = v[0].p[1];\r
-               break;\r
-       case PLANE_YZ0:\r
-       case PLANE_YZ1:\r
-               v[0].p[0] = backface;\r
-               v[1].p[0] = v[0].p[0];\r
-               v[2].p[0] = v[0].p[0];\r
-               v[3].p[0] = v[0].p[0];\r
-               break;\r
-       default:\r
-               v[0].p[2] = backface;\r
-               v[1].p[2] = v[0].p[2];\r
-               v[2].p[2] = v[0].p[2];\r
-               v[3].p[2] = v[0].p[2];\r
-       }\r
-       for(i=0; i<=3; i++)\r
-       {\r
-               project(&v[i]);\r
-               Hlo = min(Hlo,v[i].pp[0]);\r
-               Hhi = max(Hhi,v[i].pp[0]);\r
-               Vlo = min(Vlo,v[i].pp[1]);\r
-               Vhi = max(Vhi,v[i].pp[1]);\r
-       }\r
-\r
-}\r
-#endif\r
+/*
+GenSurf plugin for GtkRadiant
+Copyright (C) 2001 David Hyde, Loki software and qeradiant.com
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "gensurf.h"
+
+#undef ISOMETRIC
+
+extern double backface;
+extern double dh, dv;
+extern double xmin,xmax,ymin,ymax,zmin,zmax;
+
+double    SF, SFG;         // Graphics scale factors
+double    XLo, XHi, YLo, YHi, ZLo, ZHi;
+double    yaw,roll;
+double    elevation,azimuth;
+int       cxChar = 10, cyChar = 16;
+int       X0, Y0;
+int       X0G, Y0G;
+
+static RECT rcCoord;   // where X= Y= is drawn
+static RECT rcGrid;    // rectangle within rcLower that forms the border of the grid, plus
+                       //   a 3 pixel slop.
+static RECT rcLower;   // lower half of window, where plan view is drawn
+static RECT rcUpper;   // upper half or entire window, where isometric projection is drawn
+
+void vertex_selected ();
+void texfont_init ();
+void texfont_write (const char *text, float l, float t);
+
+#define PEN_GRID { \
+  g_GLTable.m_pfn_qglLineWidth (1); \
+  g_GLTable.m_pfn_qglColor3f (0, 1, 0); \
+  g_GLTable.m_pfn_qglDisable (GL_LINE_STIPPLE); }
+
+#define PEN_RED { \
+  g_GLTable.m_pfn_qglLineWidth (2); \
+  g_GLTable.m_pfn_qglColor3f (1, 0, 0); \
+  g_GLTable.m_pfn_qglDisable (GL_LINE_STIPPLE); }
+
+#define PEN_DASH { \
+  g_GLTable.m_pfn_qglLineWidth (1); \
+  g_GLTable.m_pfn_qglColor3f (0, 1, 0); \
+  g_GLTable.m_pfn_qglLineStipple (1, 0xF0F0); \
+  g_GLTable.m_pfn_qglEnable (GL_LINE_STIPPLE); }
+
+#define DRAW_QUAD(rc,r,g,b) { \
+  g_GLTable.m_pfn_qglBegin (GL_QUADS); \
+  g_GLTable.m_pfn_qglColor3f (0,1,0); \
+  g_GLTable.m_pfn_qglVertex2f (rc.left-1, rc.bottom); \
+  g_GLTable.m_pfn_qglVertex2f (rc.right, rc.bottom); \
+  g_GLTable.m_pfn_qglVertex2f (rc.right, rc.top+1); \
+  g_GLTable.m_pfn_qglVertex2f (rc.left-1, rc.top+1); \
+  g_GLTable.m_pfn_qglColor3f (r,g,b); \
+  g_GLTable.m_pfn_qglVertex2f (rc.left, rc.bottom+1); \
+  g_GLTable.m_pfn_qglVertex2f (rc.right-1, rc.bottom+1); \
+  g_GLTable.m_pfn_qglVertex2f (rc.right-1, rc.top); \
+  g_GLTable.m_pfn_qglVertex2f (rc.left, rc.top); \
+  g_GLTable.m_pfn_qglEnd (); }
+
+
+#ifndef ISOMETRIC
+double    D=65536.;
+double    ct[3],st[3];
+double    Hhi, Hlo, Vhi, Vlo;
+#endif
+
+#define SUBDIVS 6
+
+
+void ShowPreview ()
+{
+  if (Preview)
+  {
+    if (g_pWndPreview == NULL)
+      CreateViewWindow ();
+    gtk_widget_show (g_pWndPreview);
+
+    UpdatePreview (true);
+  }
+  else
+    gtk_widget_hide (g_pWndPreview);
+}
+
+static void draw_preview ()
+{
+  int width = g_pPreviewWidget->allocation.width, height = g_pPreviewWidget->allocation.height;
+
+  g_GLTable.m_pfn_qglClearColor (0, 0, 0, 1);
+  g_GLTable.m_pfn_qglViewport (0, 0, width, height);
+  g_GLTable.m_pfn_qglMatrixMode (GL_PROJECTION);
+  g_GLTable.m_pfn_qglLoadIdentity ();
+  g_GLTable.m_pfn_qglOrtho (0, width, 0, height, -1, 1);
+  g_GLTable.m_pfn_qglClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+       
+       // ^Fishman - Antializing for the preview window.
+       if (Antialiasing)
+       {
+               g_GLTable.m_pfn_qglEnable(GL_BLEND);
+               g_GLTable.m_pfn_qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+               g_GLTable.m_pfn_qglEnable(GL_LINE_SMOOTH);
+       }
+       else
+       {
+               g_GLTable.m_pfn_qglDisable(GL_BLEND);
+               g_GLTable.m_pfn_qglDisable(GL_LINE_SMOOTH);
+       }
+
+  texfont_init ();
+
+  if (!ValidSurface ())
+    return;
+
+  rcUpper.left = 0;
+  rcUpper.right = width;
+  rcUpper.bottom = 0;
+  rcUpper.top = height;
+  rcLower.left = 0;
+  rcLower.right = width;
+  rcLower.bottom = 0;
+  rcLower.top = height;
+
+  if (VertexMode)
+  {
+    rcUpper.bottom = rcUpper.top/2;
+    DrawPreview (rcUpper);
+    g_GLTable.m_pfn_qglBegin (GL_LINES);
+    g_GLTable.m_pfn_qglVertex2f (rcUpper.left, rcUpper.bottom);
+    g_GLTable.m_pfn_qglVertex2f (rcUpper.right, rcUpper.bottom);
+    g_GLTable.m_pfn_qglEnd ();
+    rcLower.top = rcUpper.bottom-1;
+    DrawGrid (rcLower);
+    rcCoord.left = rcLower.left;
+    rcCoord.right = rcLower.right;
+    rcCoord.bottom = rcLower.bottom;
+    rcCoord.top = rcLower.top;
+    rcCoord.top = rcCoord.bottom+cyChar;
+    rcCoord.right = rcCoord.left + 15*cxChar;
+    rcGrid.left   = X0G - 3;
+    rcGrid.bottom = Y0G - 3;
+    rcGrid.right  = X0G + (int)(SFG*(Hur-Hll)) + 3;
+    rcGrid.top    = Y0G + (int)(SFG*(Vur-Vll)) + 3;
+  }
+  else
+    DrawPreview (rcUpper);
+}
+
+static gint expose (GtkWidget *widget, GdkEventExpose *event, gpointer data)
+{
+  if (event->count > 0)
+    return TRUE;
+
+  if (!g_UIGtkTable.m_pfn_glwidget_make_current (g_pPreviewWidget))
+  {
+    g_FuncTable.m_pfnSysPrintf ("GtkGenSurf: glMakeCurrent failed\n");
+    return TRUE;
+  }
+
+  draw_preview ();
+
+  g_UIGtkTable.m_pfn_glwidget_swap_buffers (g_pPreviewWidget);
+  g_GLTable.m_pfn_QE_CheckOpenGLForErrors ();
+
+  return TRUE;
+}
+
+static void button_press (GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+  POINT pt = { (long)event->x, widget->allocation.height - (long)event->y };
+  bool        Selected;
+  double      x,y;
+  int         i, j, k, ks;
+  int         i0, i1, j0, j1;
+
+  if ((!VertexMode) || (event->button != 1))
+    return;
+
+  if (!PtInRect (&rcGrid,pt))
+  {
+    gdk_beep ();
+    return;
+  }
+
+  x = Hll + (pt.x-X0G)/SFG;
+  y = Vur - (pt.y-Y0G)/SFG;
+  i = (int)(floor( (x-Hll)/dh - 0.5) + 1);
+  j = (int)(floor( (y-Vll)/dv - 0.5) + 1);
+  if (i < 0 || i > NH || j < 0 || j > NV)
+  {
+    gdk_beep ();
+    return;
+  }
+
+  if(!CanEdit(i,j))
+  {
+    gdk_beep ();
+    return;
+  }
+
+  // Control key pressed - add this point, or remove it if already selected
+  if ((event->state & GDK_CONTROL_MASK) != 0)
+  {
+    Selected = FALSE;
+    if (NumVerticesSelected)
+    {
+      for (k=0; k<NumVerticesSelected && !Selected; k++)
+      {
+        if(Vertex[k].i == i && Vertex[k].j == j)
+        {
+          Selected = TRUE;
+          ks = k;
+        }
+      }
+    }
+
+    // Already selected - unselect it.
+    if (Selected)
+    {
+      if (ks < NumVerticesSelected)
+      {
+        for (k=ks;k<NumVerticesSelected-1;k++)
+        {
+          Vertex[k].i = Vertex[k+1].i;
+          Vertex[k].j = Vertex[k+1].j;
+        }
+        NumVerticesSelected--;
+      }
+    }
+    else
+    {
+      Vertex[NumVerticesSelected].i = i;
+      Vertex[NumVerticesSelected].j = j;
+      NumVerticesSelected++;
+    }
+  }
+  else if ((event->state & GDK_SHIFT_MASK) != 0)
+  {
+    if (NumVerticesSelected)
+    {
+      NumVerticesSelected = 1;
+      i0 = min(Vertex[0].i, i);
+      i1 = max(Vertex[0].i, i);
+      j0 = min(Vertex[0].j, j);
+      j1 = max(Vertex[0].j, j);
+      for(i=i0; i<=i1; i++)
+      {
+        for(j=j0; j<=j1; j++)
+        {
+          if(i==0  && j==0 ) continue;
+          if(i==NH && j==0 ) continue;
+          if(i==0  && j==NV) continue;
+          if(i==NH && j==NV) continue;
+          if(i != Vertex[0].i || j != Vertex[0].j)
+          {
+            Vertex[NumVerticesSelected].i = i;
+            Vertex[NumVerticesSelected].j = j;
+            NumVerticesSelected++;
+          }
+        }
+      }
+    }
+    else
+    {
+      Vertex[0].i = i;
+      Vertex[0].j = j;
+      NumVerticesSelected = 1;
+    }
+  }
+  else
+  {
+    Vertex[0].i = i;
+    Vertex[0].j = j;
+    NumVerticesSelected = 1;
+  }
+
+  vertex_selected ();
+}
+
+static void motion (GtkWidget *widget, GdkEventMotion *event, gpointer data)
+{
+  POINT pt = { (long)event->x, widget->allocation.height - (long)event->y };
+
+  if (!VertexMode)
+    return;
+
+  if (!g_UIGtkTable.m_pfn_glwidget_make_current (g_pPreviewWidget))
+  {
+    g_FuncTable.m_pfnSysPrintf ("GtkGenSurf: glMakeCurrent failed\n");
+    return;
+  }
+
+  g_GLTable.m_pfn_qglEnable (GL_SCISSOR_TEST);
+  g_GLTable.m_pfn_qglScissor (rcCoord.left, rcCoord.bottom, rcCoord.right-rcCoord.left,
+                              rcCoord.top-rcCoord.bottom);
+  g_GLTable.m_pfn_qglClear (GL_COLOR_BUFFER_BIT);
+
+  if (PtInRect(&rcGrid,pt))
+  {
+    GdkCursor *cursor = gdk_cursor_new (GDK_CROSS);
+    gdk_window_set_cursor (g_pWndPreview->window, cursor);
+    gdk_cursor_unref (cursor);
+
+    char Text[32];
+    int x, y;
+
+    x = (int)(Hll + (pt.x-X0G)/SFG);
+    y = (int)(Vur - (pt.y-Y0G)/SFG);
+    switch(Plane)
+    {
+    case PLANE_XZ0:
+    case PLANE_XZ1:
+      sprintf(Text," x=%d, z=%d   ",(int)(floor(x-0.5)+1.) ,(int)(floor(y-0.5)+1.) );
+      break;
+    case PLANE_YZ0:
+    case PLANE_YZ1:
+      sprintf(Text," y=%d, z=%d   ",(int)(floor(x-0.5)+1.) ,(int)(floor(y-0.5)+1.) );
+      break;
+    default:
+      sprintf(Text," x=%d, y=%d   ",(int)(floor(x-0.5)+1.) ,(int)(floor(y-0.5)+1.) );
+    }
+
+    texfont_write (Text, rcCoord.left, rcCoord.top);
+  }
+  else
+  {
+    gdk_window_set_cursor (g_pWndPreview->window, NULL);
+  }
+
+  g_UIGtkTable.m_pfn_glwidget_swap_buffers (g_pPreviewWidget);
+  g_GLTable.m_pfn_QE_CheckOpenGLForErrors ();
+  g_GLTable.m_pfn_qglDisable (GL_SCISSOR_TEST);
+}
+
+static gint preview_close (GtkWidget *widget, gpointer data)
+{
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (g_object_get_data (G_OBJECT (g_pWnd), "main_preview")), FALSE);
+  return TRUE;
+}
+
+static void preview_focusout (GtkSpinButton *spin, GdkEventFocus *event, double *data)
+{
+  *data = DegreesToRadians ((double)(gtk_spin_button_get_value_as_int (spin) % 360));
+  UpdatePreview (false);
+}
+
+static gint doublevariable_spinfocusout(GtkWidget* widget, GdkEventFocus* event, gpointer data)
+{
+  preview_focusout(GTK_SPIN_BUTTON(widget), event, reinterpret_cast<double*>(data));
+  return FALSE;
+}
+
+static void preview_spin (GtkAdjustment *adj, double *data)
+{
+  *data = DegreesToRadians (adj->value);
+  UpdatePreview (false);
+}
+
+void CreateViewWindow ()
+{
+  GtkWidget *dlg, *vbox, *hbox, *label, *spin, *frame;
+  GtkObject *adj;
+
+#ifndef ISOMETRIC
+  elevation = PI/6.;
+  azimuth   = PI/6.;
+#endif
+
+  g_pWndPreview = dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title (GTK_WINDOW (dlg), "GtkGenSurf Preview");
+  gtk_signal_connect (GTK_OBJECT (dlg), "delete_event", GTK_SIGNAL_FUNC (preview_close), NULL);
+  gtk_signal_connect (GTK_OBJECT (dlg), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
+  gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (g_pWnd));
+  gtk_window_set_default_size (GTK_WINDOW (dlg), 300, 400);
+
+  vbox = gtk_vbox_new (FALSE, 5);
+  gtk_widget_show (vbox);
+  gtk_container_add (GTK_CONTAINER (dlg), vbox);
+
+#ifndef ISOMETRIC
+  hbox = gtk_hbox_new (TRUE, 5);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (hbox), 3);
+
+  label = gtk_label_new ("Elevation");
+  gtk_widget_show (label);
+  gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
+
+  adj = gtk_adjustment_new (30, -90, 90, 1, 10, 10);
+  gtk_signal_connect (adj, "value_changed", GTK_SIGNAL_FUNC (preview_spin), &elevation);
+  spin = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1, 0);
+  gtk_widget_show (spin);
+  gtk_box_pack_start (GTK_BOX (hbox), spin, FALSE, TRUE, 0);
+  g_signal_connect (G_OBJECT (spin), "focus_out_event", G_CALLBACK (doublevariable_spinfocusout), &elevation);
+
+  adj = gtk_adjustment_new (30, 0, 359, 1, 10, 10);
+  gtk_signal_connect (adj, "value_changed", GTK_SIGNAL_FUNC (preview_spin), &azimuth);
+  spin = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1, 0);
+  gtk_widget_show (spin);
+  gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spin), TRUE);
+  gtk_box_pack_end (GTK_BOX (hbox), spin, FALSE, TRUE, 0);
+
+  label = gtk_label_new ("Azimuth");
+  gtk_widget_show (label);
+  gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
+  gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, TRUE, 0);
+  g_signal_connect (G_OBJECT (spin), "focus_out_event", G_CALLBACK (doublevariable_spinfocusout), &azimuth);
+#endif
+
+  frame = gtk_frame_new (NULL);
+  gtk_widget_show (frame);
+  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+  gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
+
+  g_pPreviewWidget = g_UIGtkTable.m_pfn_glwidget_new (FALSE, NULL);
+
+  gtk_widget_set_events (g_pPreviewWidget, GDK_EXPOSURE_MASK|GDK_BUTTON_PRESS_MASK|GDK_POINTER_MOTION_MASK);
+  gtk_signal_connect (GTK_OBJECT (g_pPreviewWidget), "expose_event", GTK_SIGNAL_FUNC (expose), NULL);
+  gtk_signal_connect (GTK_OBJECT (g_pPreviewWidget), "motion_notify_event", GTK_SIGNAL_FUNC (motion), NULL);
+  gtk_signal_connect (GTK_OBJECT (g_pPreviewWidget), "button_press_event",
+                      GTK_SIGNAL_FUNC (button_press), NULL);
+
+  gtk_widget_show (g_pPreviewWidget);
+  gtk_container_add (GTK_CONTAINER (frame), g_pPreviewWidget);
+
+  if (Preview)
+    gtk_widget_show (g_pWndPreview);
+
+  UpdatePreview (true);
+}
+
+//=============================================================
+/* DrawPreview */
+void DrawPreview (RECT rc)
+{
+#define COSXA 0.8660254037844
+#define SINXA 0.5
+#define COSYA 0.8660254037844
+#define SINYA 0.5
+
+  double     L;
+  double     x,y;
+  int        i, j;
+  POINT      pt[8];
+  XYZ        v[8];
+  char axis[3][2] = {"X","Y","Z"};
+
+#ifndef ISOMETRIC
+  evaluate();
+#endif
+
+  XLo = xmin;
+  XHi = xmax;
+  YLo = ymin;
+  YHi = ymax;
+  ZLo = zmin;
+  ZHi = zmax;
+  switch (Plane)
+  {
+  case PLANE_XY1:
+    ZHi = backface;
+    break;
+  case PLANE_XZ0:
+    YLo = backface;
+    break;
+  case PLANE_XZ1:
+    YHi = backface;
+    break;
+  case PLANE_YZ0:
+    XLo = backface;
+    break;
+  case PLANE_YZ1:
+    XHi = backface;
+    break;
+  default:
+    ZLo = backface;
+  }
+
+
+
+  GetScaleFactor(rc);
+       //PEN_GRID
+       g_GLTable.m_pfn_qglLineWidth (1);
+       g_GLTable.m_pfn_qglColor3f (0, 1, 0);
+       g_GLTable.m_pfn_qglDisable (GL_LINE_STIPPLE);
+
+    if (Decimate > 0 && (Game != QUAKE3 || UsePatches==0) )
+    {
+      XYZ  *vv;
+
+      vv   = (XYZ *) malloc(gNumNodes * sizeof(XYZ));
+      for(i=0; i<gNumNodes; i++)
+      {
+        for(j=0; j<3; j++)
+          vv[i].p[j] = (double)(gNode[i].p[j]);
+        project(&vv[i]);
+      }
+
+      for(i=0; i<gNumTris; i++)
+      {
+        for(j=0; j<3; j++)
+          Scale(rc,vv[gTri[i].v[j]],&pt[j]);
+
+        g_GLTable.m_pfn_qglBegin (GL_LINE_STRIP);
+        g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);
+        g_GLTable.m_pfn_qglVertex2f (pt[1].x, pt[1].y);
+        g_GLTable.m_pfn_qglVertex2f (pt[2].x, pt[2].y);
+        g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);
+        g_GLTable.m_pfn_qglEnd ();
+      }
+      free(vv);
+    }
+    else if (Game==QUAKE3 && UsePatches!=0)
+    {
+      int              axis, ii, jj, k;
+      float    u, v;
+      XYZ              uv[3][3];
+      XYZ              Ctrl[3],out;
+
+      switch (Plane)
+      {
+      case PLANE_XY0:
+      case PLANE_XY1:
+        k = 2;
+        break;
+      case PLANE_XZ0:
+      case PLANE_XZ1:
+        k = 1;
+        break;
+      default:
+        k = 0;
+      }
+      for(i=0; i<NH; i+=2)
+      {
+        for(j=0; j<NV; j+=2)
+        {
+          VectorCopy(xyz[i  ][j  ].p,uv[0][0].p);
+          VectorCopy(xyz[i+1][j  ].p,uv[1][0].p);
+          VectorCopy(xyz[i+2][j  ].p,uv[2][0].p);
+          VectorCopy(xyz[i  ][j+1].p,uv[0][1].p);
+          VectorCopy(xyz[i+1][j+1].p,uv[1][1].p);
+          VectorCopy(xyz[i+2][j+1].p,uv[2][1].p);
+          VectorCopy(xyz[i  ][j+2].p,uv[0][2].p);
+          VectorCopy(xyz[i+1][j+2].p,uv[1][2].p);
+          VectorCopy(xyz[i+2][j+2].p,uv[2][2].p);
+          uv[1][0].p[k] = (4*xyz[i+1][j  ].p[k] - xyz[i  ][j  ].p[k] - xyz[i+2][j  ].p[k])/2;
+          uv[0][1].p[k] = (4*xyz[i  ][j+1].p[k] - xyz[i  ][j  ].p[k] - xyz[i  ][j+2].p[k])/2;
+          uv[2][1].p[k] = (4*xyz[i+2][j+1].p[k] - xyz[i+2][j  ].p[k] - xyz[i+2][j+2].p[k])/2;
+          uv[1][2].p[k] = (4*xyz[i+1][j+2].p[k] - xyz[i  ][j+2].p[k] - xyz[i+2][j+2].p[k])/2;
+          uv[1][1].p[k] = (16*xyz[i+1][j+1].p[k] -
+                           xyz[i  ][j  ].p[k] - 2*xyz[i+1][j  ].p[k] -  xyz[i+2][j  ].p[k] -
+                           2*xyz[i  ][j+1].p[k]                        -2*xyz[i+2][j+1].p[k] -
+                           xyz[i  ][j+2].p[k] - 2*xyz[i+1][j+2].p[k] -  xyz[i+2][j+2].p[k]   )/4;
+
+          for(ii=0; ii<=SUBDIVS; ii++)
+          {
+            if(ii==0 || ii==SUBDIVS/2 || ii==SUBDIVS)
+                                               {
+                                                       g_GLTable.m_pfn_qglLineWidth (1);
+                                                       g_GLTable.m_pfn_qglColor3f (0, 1, 0);
+                                                       g_GLTable.m_pfn_qglDisable (GL_LINE_STIPPLE);
+                                                       // PEN_GRID
+                                               }
+            else
+                                               {
+                                                       g_GLTable.m_pfn_qglLineWidth (1);
+                                                       g_GLTable.m_pfn_qglColor3f (0, 1, 0);
+                                                       g_GLTable.m_pfn_qglLineStipple (1, 0xF0F0);
+                                                       g_GLTable.m_pfn_qglEnable (GL_LINE_STIPPLE);
+              // PEN_DASH
+                                               }
+
+            u = (float)(ii)/(float)(SUBDIVS);
+            for(jj=0; jj<3; jj++)
+            {
+              for(axis=0; axis<3; axis++)
+              {
+                float  a, b, c;
+                float  qA, qB, qC;
+                a = (float)uv[0][jj].p[axis];
+                b = (float)uv[1][jj].p[axis];
+                c = (float)uv[2][jj].p[axis];
+                qA = a - 2 * b + c;
+                qB = 2 * b - 2 * a;
+                qC = a;
+                Ctrl[jj].p[axis] = qA * u * u + qB * u + qC;
+              }
+            }
+            VectorCopy(Ctrl[0].p,out.p);
+            project(&out);
+            Scale(rc,out,&pt[0]);
+            g_GLTable.m_pfn_qglBegin (GL_LINE_STRIP);
+            g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);
+            for(jj=1; jj<=SUBDIVS; jj++)
+            {
+              v = (float)(jj)/(float)(SUBDIVS);
+              for (axis = 0 ; axis < 3 ; axis++) 
+              {
+                float  a, b, c;
+                float  qA, qB, qC;
+                a = (float)Ctrl[0].p[axis];
+                b = (float)Ctrl[1].p[axis];
+                c = (float)Ctrl[2].p[axis];
+                qA = a - 2 * b + c;
+                qB = 2 * b - 2 * a;
+                qC = a;
+                out.p[axis] = qA * v * v + qB * v + qC;
+              }
+              project(&out);
+              Scale(rc,out,&pt[0]);
+              g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);
+            }
+            g_GLTable.m_pfn_qglEnd ();
+          }
+          for(jj=0; jj<=SUBDIVS; jj++)
+          {
+            if(jj==0 || jj==SUBDIVS/2 || jj==SUBDIVS)
+                                               {
+                                                       g_GLTable.m_pfn_qglLineWidth (1);
+                                                       g_GLTable.m_pfn_qglColor3f (0, 1, 0);
+                                                       g_GLTable.m_pfn_qglDisable (GL_LINE_STIPPLE);
+              // PEN_GRID
+                                               }
+            else
+                                               {
+                                                       g_GLTable.m_pfn_qglLineWidth (1);
+                                                       g_GLTable.m_pfn_qglColor3f (0, 1, 0);
+                                                       g_GLTable.m_pfn_qglLineStipple (1, 0xF0F0);
+                                                       g_GLTable.m_pfn_qglEnable (GL_LINE_STIPPLE);
+                                                       // PEN_DASH
+                                               }
+
+            v = (float)(jj)/(float)(SUBDIVS);
+            for(ii=0; ii<3; ii++)
+            {
+              for(axis=0; axis<3; axis++)
+              {
+                float  a, b, c;
+                float  qA, qB, qC;
+                a = (float)uv[ii][0].p[axis];
+                b = (float)uv[ii][1].p[axis];
+                c = (float)uv[ii][2].p[axis];
+                qA = a - 2 * b + c;
+                qB = 2 * b - 2 * a;
+                qC = a;
+                Ctrl[ii].p[axis] = qA * v * v + qB * v + qC;
+              }
+            }
+            VectorCopy(Ctrl[0].p,out.p);
+            project(&out);
+            Scale(rc,out,&pt[0]);
+            g_GLTable.m_pfn_qglBegin (GL_LINE_STRIP);
+            g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);
+            for(ii=1; ii<=SUBDIVS; ii++)
+            {
+              u = (float)(ii)/(float)(SUBDIVS);
+              for (axis = 0 ; axis < 3 ; axis++) 
+              {
+                float  a, b, c;
+                float  qA, qB, qC;
+                a = (float)Ctrl[0].p[axis];
+                b = (float)Ctrl[1].p[axis];
+                c = (float)Ctrl[2].p[axis];
+                qA = a - 2 * b + c;
+                qB = 2 * b - 2 * a;
+                qC = a;
+                out.p[axis] = qA * u * u + qB * u + qC;
+              }
+              project(&out);
+              Scale(rc,out,&pt[0]);
+              g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);
+            }
+            g_GLTable.m_pfn_qglEnd ();
+          }
+        }
+      }
+    }
+    else
+    {
+      for(i=0; i<=NH; i++)
+      {
+        Scale(rc,xyz[i][0],&pt[0]);
+        g_GLTable.m_pfn_qglBegin (GL_LINE_STRIP);
+        g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);
+        for(j=1; j<=NV; j++)
+        {
+          Scale(rc,xyz[i][j],&pt[0]);
+          g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);
+        }
+        g_GLTable.m_pfn_qglEnd ();
+      }
+      for(j=0; j<=NV; j++)
+      {
+        Scale(rc,xyz[0][j],&pt[0]);
+        g_GLTable.m_pfn_qglBegin (GL_LINE_STRIP);
+        g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);
+        for(i=1; i<=NH; i++)
+        {
+          Scale(rc,xyz[i][j],&pt[0]);
+          g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);
+        }
+        g_GLTable.m_pfn_qglEnd ();
+      }
+    }
+
+  if(Game!=QUAKE3 || UsePatches==0)
+  {
+    // Draw lines from corners to base, and lines around base
+    for(i=0; i<=NH; i+=NH)
+    {
+      for(j=0; j<=NV; j+=NV)
+      {
+        VectorCopy(xyz[i][j].p, v[0].p);
+        switch(Plane)
+        {
+        case PLANE_XZ0:
+        case PLANE_XZ1:
+          v[0].p[1] = backface;
+          break;
+        case PLANE_YZ0:
+        case PLANE_YZ1:
+          v[0].p[0] = backface;
+          break;
+        default:
+          v[0].p[2] = backface;
+        }
+        Scale(rc,xyz[i][j],&pt[0]);
+#ifndef ISOMETRIC
+        project(&v[0]);
+#endif
+        Scale(rc,v[0],&pt[1]);
+        g_GLTable.m_pfn_qglBegin (GL_LINE_STRIP);
+        g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);
+        g_GLTable.m_pfn_qglVertex2f (pt[1].x, pt[1].y);
+        g_GLTable.m_pfn_qglEnd ();
+      }
+    }
+    VectorCopy(xyz[ 0][ 0].p, v[0].p);
+    VectorCopy(xyz[NH][ 0].p, v[1].p);
+    VectorCopy(xyz[NH][NV].p, v[2].p);
+    VectorCopy(xyz[ 0][NV].p, v[3].p);
+    switch(Plane)
+    {
+    case PLANE_XZ0:
+    case PLANE_XZ1:
+      v[0].p[1] = backface;;
+      v[1].p[1] = v[0].p[1];
+      v[2].p[1] = v[0].p[1];
+      v[3].p[1] = v[0].p[1];
+      break;
+    case PLANE_YZ0:
+    case PLANE_YZ1:
+      v[0].p[0] = backface;
+      v[1].p[0] = v[0].p[0];
+      v[2].p[0] = v[0].p[0];
+      v[3].p[0] = v[0].p[0];
+      break;
+    default:
+      v[0].p[2] = backface;
+      v[1].p[2] = v[0].p[2];
+      v[2].p[2] = v[0].p[2];
+      v[3].p[2] = v[0].p[2];
+    }
+#ifndef ISOMETRIC
+    project(&v[3]);
+#endif
+    Scale(rc,v[3],&pt[0]);
+    g_GLTable.m_pfn_qglBegin (GL_LINE_STRIP);
+    g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);
+    for(i=0; i<3; i++)
+    {
+#ifndef ISOMETRIC
+      project(&v[i]);
+#endif
+      Scale(rc,v[i],&pt[1]);
+      g_GLTable.m_pfn_qglVertex2f (pt[1].x, pt[1].y);
+    }
+    g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);
+    g_GLTable.m_pfn_qglEnd ();
+  }
+
+  g_GLTable.m_pfn_qglLineWidth (1);
+  g_GLTable.m_pfn_qglColor3f (0, 1, 0);
+  g_GLTable.m_pfn_qglDisable (GL_LINE_STIPPLE);
+
+#ifdef ISOMETRIC
+  // Draw small depiction of coordinate axes
+  pt[0].x = rc.right  - cxChar   - cxChar/2 -  cyChar;
+  pt[0].y = rc.bottom - cyChar/2 - cxChar/2;
+  pt[1].x = pt[0].x + (int)(cyChar*COSXA);
+  pt[1].y = pt[0].y - (int)(cyChar*SINXA);
+  MoveToEx(hdc,pt[0].x,pt[0].y,NULL);
+  LineTo(hdc,pt[1].x,pt[1].y);
+  SetTextAlign(hdc,TA_LEFT | TA_TOP);
+  TextOut(hdc,pt[1].x,pt[1].y-cyChar/2,"X",1);
+  pt[1].x = pt[0].x - (int)(cyChar*COSYA);
+  pt[1].y = pt[0].y - (int)(cyChar*SINYA);
+  MoveToEx(hdc,pt[0].x,pt[0].y,NULL);
+  LineTo(hdc,pt[1].x,pt[1].y);
+  SetTextAlign(hdc,TA_RIGHT | TA_TOP);
+  TextOut(hdc,pt[1].x,pt[1].y-cyChar/2,"Y",1);
+  pt[1].x = pt[0].x;
+  pt[1].y = pt[0].y - cyChar;
+  MoveToEx(hdc,pt[0].x,pt[0].y,NULL);
+  LineTo(hdc,pt[1].x,pt[1].y);
+  SetTextAlign(hdc,TA_CENTER | TA_BOTTOM);
+  TextOut(hdc,pt[1].x,pt[1].y,"Z",1);
+#else
+  L = 2*(double)cyChar/SF;
+  v[0].p[0] = 0.;
+  v[0].p[1] = 0.;
+  v[0].p[2] = 0.;
+  v[1].p[0] = L;
+  v[1].p[1] = 0.;
+  v[1].p[2] = 0.;
+  v[2].p[0] = 0.;
+  v[2].p[1] = L;
+  v[2].p[2] = 0.;
+  v[3].p[0] = 0.;
+  v[3].p[1] = 0.;
+  v[3].p[2] = L;
+  for(i=0; i<=3; i++)
+  {
+    project(&v[i]);
+    Scale(rc,v[i],&pt[i]);
+  }
+  for(i=1; i<=3; i++)
+  {
+    pt[i].x += -pt[0].x + rc.right  - 2*cyChar;
+    pt[i].y += -pt[0].y + rc.bottom + 2*cyChar;
+  }
+  pt[0].x = rc.right  - 2*cyChar;
+  pt[0].y = rc.bottom + 2*cyChar;
+
+  for(i=1; i<=3; i++)
+  {
+    g_GLTable.m_pfn_qglBegin (GL_LINES);
+    g_GLTable.m_pfn_qglVertex2f (pt[0].x, pt[0].y);
+    g_GLTable.m_pfn_qglVertex2f (pt[i].x, pt[i].y);
+    g_GLTable.m_pfn_qglEnd ();
+    texfont_write (axis[i-1], pt[i].x-cxChar/2,pt[i].y+cyChar/2);
+  }
+#endif
+
+  // Draw player model's bounding box in red to give a sense of scale
+  // PEN_RED
+       g_GLTable.m_pfn_qglLineWidth (2);
+       g_GLTable.m_pfn_qglColor3f (1, 0, 0);
+       g_GLTable.m_pfn_qglDisable (GL_LINE_STIPPLE);
+
+  switch(Plane)
+  {
+  case PLANE_XY1:
+    v[0].p[0] = xyz[NH/2][NV/2].p[0] + PlayerBox[Game].x[0];
+    v[0].p[1] = xyz[NH/2][NV/2].p[1] + PlayerBox[Game].y[0];
+    v[0].p[2] = zmin - PlayerBox[Game].z[0] - 32;
+    break;
+  case PLANE_XZ0:
+    v[0].p[0] = (xmax+xmin)/2 + PlayerBox[Game].x[0];
+    v[0].p[1] = ymax+64;
+    v[0].p[2] = zmin;
+    break;
+  case PLANE_XZ1:
+    v[0].p[0] = (xmax+xmin)/2 + PlayerBox[Game].x[0];
+    v[0].p[1] = ymin-64;
+    v[0].p[2] = zmin;
+    break;
+  case PLANE_YZ0:
+    v[0].p[0] = xmax+64;
+    v[0].p[1] = (ymax+ymin)/2 + PlayerBox[Game].y[0];
+    v[0].p[2] = zmin;
+    break;
+  case PLANE_YZ1:
+    v[0].p[0] = xmin-64;
+    v[0].p[1] = (ymax+ymin)/2 + PlayerBox[Game].y[0];
+    v[0].p[2] = zmin;
+    break;
+  default:
+    // Put player on a node. For patches, put on an even numbered node.
+    if(Game==QUAKE3 && UsePatches!=0)
+    {
+      if(NH > 2)
+        x = Hll + dh * (int)(NH/2 + 1);
+      else
+        x = Hll + dh * (int)(NH/2);
+      if(NV > 2)
+        y = Vll + dv * (int)(NV/2 + 1);
+      else
+        y = Vll + dv * (int)(NV/2);
+    }
+    else
+    {
+      if(NH > 1)
+        x = Hll + dh * (int)(NH/2);
+      else
+        x = Hll + dh/2;
+      if(NV > 1)
+        y = Vll + dv * (int)(NV/2);
+      else
+        y = Vll + dv/2;
+    }
+//             x = (Hll+Hur)/2.;
+//             y = (Vll+Vur)/2.;
+    v[0].p[0] = x + PlayerBox[Game].x[0];
+    v[0].p[1] = y + PlayerBox[Game].y[0];
+    v[0].p[2] = PlayerStartZ(x,y) + PlayerBox[Game].z[0] + 8; // add 8 cuz I'm a pessimist
+  }
+  v[1].p[0] = v[0].p[0] + PlayerBox[Game].x[1] - PlayerBox[Game].x[0];
+  v[1].p[1] = v[0].p[1];
+  v[1].p[2] = v[0].p[2];
+  v[2].p[0] = v[1].p[0];
+  v[2].p[1] = v[1].p[1] + PlayerBox[Game].y[1] - PlayerBox[Game].y[0];
+  v[2].p[2] = v[0].p[2];
+  v[3].p[0] = v[0].p[0];
+  v[3].p[1] = v[2].p[1];
+  v[3].p[2] = v[0].p[2];
+  VectorCopy(v[0].p,v[4].p);
+  VectorCopy(v[1].p,v[5].p);
+  VectorCopy(v[2].p,v[6].p);
+  VectorCopy(v[3].p,v[7].p);
+  v[4].p[2] += PlayerBox[Game].z[1] - PlayerBox[Game].z[0];
+  v[5].p[2] += PlayerBox[Game].z[1] - PlayerBox[Game].z[0];
+  v[6].p[2] += PlayerBox[Game].z[1] - PlayerBox[Game].z[0];
+  v[7].p[2] += PlayerBox[Game].z[1] - PlayerBox[Game].z[0];
+  for(i=0; i<=7; i++)
+  {
+#ifndef ISOMETRIC
+    project(&v[i]);
+#endif
+    Scale(rc,v[i],&pt[i]);
+  }
+  g_GLTable.m_pfn_qglBegin (GL_LINE_STRIP);
+  g_GLTable.m_pfn_qglVertex2f (pt[3].x, pt[3].y);
+  for(i=0; i<=3; i++)
+    g_GLTable.m_pfn_qglVertex2f (pt[i].x, pt[i].y);
+  g_GLTable.m_pfn_qglEnd ();
+  g_GLTable.m_pfn_qglBegin (GL_LINE_STRIP);
+  g_GLTable.m_pfn_qglVertex2f (pt[7].x, pt[7].y);
+  for(i=4; i<=7; i++)
+    g_GLTable.m_pfn_qglVertex2f (pt[i].x, pt[i].y);
+  g_GLTable.m_pfn_qglEnd ();
+  g_GLTable.m_pfn_qglBegin (GL_LINES);
+  for(i=0; i<=3; i++)
+  {
+    g_GLTable.m_pfn_qglVertex2f (pt[i].x,pt[i].y);
+    g_GLTable.m_pfn_qglVertex2f (pt[i+4].x,pt[i+4].y);
+  }
+  g_GLTable.m_pfn_qglEnd ();
+
+  g_GLTable.m_pfn_qglLineWidth (1);
+  g_GLTable.m_pfn_qglColor3f (0, 1, 0);
+  g_GLTable.m_pfn_qglDisable (GL_LINE_STIPPLE);
+}
+//=============================================================
+void DrawGrid(RECT rc)
+{
+  int        i, j, k;
+  double     h,w,x,y;
+  POINT      pt[2];
+  RECT       rcBox;
+
+  w = (double)(rc.right-rc.left+1) - cxChar;
+  h = (double)(rc.top-rc.bottom+1) - cxChar - cyChar;
+
+  SFG = w/(Hur-Hll);
+  SFG = min(SFG, h/(Vur-Vll));
+
+  // Center drawing
+  X0G = (int)(rc.left + rc.right - (int)(SFG*(Hur-Hll)))/2;
+  Y0G = (int)(rc.top + rc.bottom + cyChar - (int)(SFG*(Vur-Vll)))/2;
+
+  g_GLTable.m_pfn_qglLineWidth (2);
+  g_GLTable.m_pfn_qglColor3f (0, 1, 0);
+  g_GLTable.m_pfn_qglDisable (GL_LINE_STIPPLE);
+
+  pt[0].y = Y0G;
+  pt[1].y = Y0G + (int)(SFG*(Vur-Vll));
+  g_GLTable.m_pfn_qglBegin (GL_LINES);
+  for(i=0; i<=NH; i++)
+  {
+    x = Hll + i * dh;
+    pt[0].x = X0G + (int)(SFG*(x-Hll));
+    g_GLTable.m_pfn_qglVertex2f(pt[0].x, pt[0].y);
+    g_GLTable.m_pfn_qglVertex2f(pt[0].x, pt[1].y);
+  }
+  g_GLTable.m_pfn_qglEnd ();
+  pt[0].x = X0G;
+  pt[1].x = X0G + (int)(SFG*(Hur-Hll));
+  g_GLTable.m_pfn_qglBegin (GL_LINES);
+  for(i=0; i<=NV; i++)
+  {
+    y = Vll + i * dv;
+    pt[0].y = Y0G + (int)(SFG*(Vur-y));
+    g_GLTable.m_pfn_qglVertex2f (pt[0].x,pt[0].y);
+    g_GLTable.m_pfn_qglVertex2f (pt[1].x,pt[0].y);
+  }
+  g_GLTable.m_pfn_qglEnd ();
+
+  g_GLTable.m_pfn_qglLineWidth (1);
+
+  // Draw axes
+  pt[0].x = rc.right  - cyChar - cxChar - cyChar/2;
+  pt[0].y = rc.bottom + cyChar/2;
+  pt[1].x = pt[0].x + cyChar;
+  pt[1].y = pt[0].y;
+  g_GLTable.m_pfn_qglBegin (GL_LINES);
+  g_GLTable.m_pfn_qglVertex2f (pt[0].x,pt[0].y);
+  g_GLTable.m_pfn_qglVertex2f (pt[1].x,pt[1].y);
+  g_GLTable.m_pfn_qglEnd ();
+  switch(Plane)
+  {
+  case PLANE_YZ0:
+  case PLANE_YZ1:
+    texfont_write ("Y", pt[1].x, pt[1].y+cyChar/2);
+    break;
+  default:
+    texfont_write ("X", pt[1].x, pt[1].y+cyChar/2);
+  }
+  pt[1].x = pt[0].x;
+  pt[1].y = pt[0].y + cyChar;
+  g_GLTable.m_pfn_qglBegin (GL_LINES);
+  g_GLTable.m_pfn_qglVertex2f (pt[0].x,pt[0].y);
+  g_GLTable.m_pfn_qglVertex2f (pt[1].x,pt[1].y);
+  g_GLTable.m_pfn_qglEnd ();
+  switch(Plane)
+  {
+  case PLANE_XY0:
+  case PLANE_XY1:
+    texfont_write ("Y", pt[1].x-cyChar/2, pt[1].y+cyChar);
+    break;
+  default:
+    texfont_write ("Z", pt[1].x-cyChar/2, pt[1].y+cyChar);
+  }
+
+  // Denote fixed points with a 5x5 red rectangle
+  for(i=0; i<=NH; i++)
+  {
+    for(j=0; j<=NV; j++)
+    {
+      if(xyz[i][j].fixed)
+      {
+        x = Hll + i*dh;
+        y = Vll + j*dv;
+        rcBox.left   = X0G + (int)(SFG*(x-Hll)) - 2;
+        rcBox.top    = Y0G + (int)(SFG*(Vur-y)) + 2;
+        rcBox.right  = rcBox.left + 5;
+        rcBox.bottom = rcBox.top  - 5;
+
+        DRAW_QUAD (rcBox, 1,0,0);
+      }
+    }
+  }
+
+  // Denote currently selected point with a 5x5 green rectangle
+  if (NumVerticesSelected)
+  {
+    for(k=0; k<NumVerticesSelected; k++)
+    {
+      x = Hll + Vertex[k].i*dh;
+      y = Vll + Vertex[k].j*dv;
+      rcBox.left   = X0G + (int)(SFG*(x-Hll)) - 2;
+      rcBox.top    = Y0G + (int)(SFG*(Vur-y)) + 2;
+      rcBox.right  = rcBox.left + 5;
+      rcBox.bottom = rcBox.top  - 5;
+
+      DRAW_QUAD (rcBox, 0,1,0);
+    }
+  }
+
+  // Unmovable vertices
+  for(i=0; i<=NH; i++)
+  {
+    for(j=0; j<=NV; j++)
+    {
+      if(!CanEdit(i,j))
+      {
+        x = Hll + i*dh;
+        y = Vll + j*dv;
+        rcBox.left   = X0G + (int)(SFG*(x-Hll)) - 2;
+        rcBox.top    = Y0G + (int)(SFG*(Vur-y)) + 2;
+        rcBox.right  = rcBox.left + 5;
+        rcBox.bottom = rcBox.top  - 5;
+
+        DRAW_QUAD (rcBox, 1,1,0);
+      }
+    }
+  }
+
+  // Legend
+  rcBox.left   = rc.left + cxChar/2 - 2;
+  rcBox.top    = rc.top  - cyChar/2 - 2;
+  rcBox.right  = rcBox.left + 5;
+  rcBox.bottom = rcBox.top  - 5;
+  DRAW_QUAD (rcBox, 1,0,0);
+  texfont_write ("Fixed points", rcBox.right+cxChar,rcBox.top-4+cyChar/2);
+
+  rcBox.top    -= cyChar;
+  rcBox.bottom -= cyChar;
+  DRAW_QUAD (rcBox, 1,1,0);
+  texfont_write ("Not movable", rcBox.right+cxChar, rcBox.top-4+cyChar/2);
+
+  rcBox.top    -= cyChar;
+  rcBox.bottom -= cyChar;
+  DRAW_QUAD (rcBox, 0,1,0);
+  texfont_write ("Selected", rcBox.right+cxChar, rcBox.top-4+cyChar/2);
+}
+
+//=============================================================
+void GetScaleFactor(RECT rc)
+{
+#ifdef ISOMETRIC
+       double      h, w;
+
+       w = (double)(rc.right-rc.left+1) - cxChar;
+       h = (double)(rc.top-rc.bottom+1) - cxChar;
+
+       SF = w/( (XHi-XLo)*COSXA + (YHi-YLo)*COSYA );
+       SF = min(SF, h/( (XHi-XLo)*SINXA + (YHi-YLo)*SINYA + ZHi-ZLo ) );
+       // Center drawing
+       X0 = (int)(rc.left + rc.right - (int)(SF*( (XHi-XLo)*COSXA + (YHi-YLo)*COSYA )) )/2;
+       Y0 = (int)(rc.top + rc.bottom - (int)(SF*( (XHi-XLo)*SINXA + (YHi-YLo)*SINYA + ZHi-ZLo) ))/2;
+
+#else
+       double      h, w;
+
+       w = (double)(rc.right-rc.left+1) - cxChar;
+       h = (double)(rc.top-rc.bottom+1) - cxChar;
+
+       SF = w/(Hhi-Hlo);
+       SF = min(SF, h/(Vhi-Vlo) );
+       X0 = (int)(rc.left + rc.right - (int)(SF*(Hhi-Hlo)))/2;
+       Y0 = (int)(rc.top + rc.bottom + (int)(SF*(Vhi-Vlo)))/2;
+#endif
+}
+
+//=============================================================
+void Scale(RECT rc,XYZ xyz,POINT *pt)
+{
+
+#ifdef ISOMETRIC
+
+       pt[0].x = X0 + (int)(SF*( (xyz.p[0]-XLo)*COSXA +
+                              (YHi-xyz.p[1])*COSYA   ));
+       pt[0].y = Y0 + (int)(SF*(  ZHi-xyz.p[2] +
+                                 (YHi-xyz.p[1])*SINYA +
+                                                 (XHi-xyz.p[0])*SINXA   ));
+#else
+       pt[0].x = X0 + (int)(SF*( xyz.pp[0] - Hlo ) );
+       pt[0].y = Y0 - (int)(SF*( Vhi - xyz.pp[1] ) );
+#endif
+
+}
+
+#ifndef ISOMETRIC
+/* ======================================================================= */
+void project(XYZ *v)
+{
+       // project a 3D point (x,y,z) onto view plane
+       double x, y, z, xa, ya, za;
+
+       x = v->p[0];
+       y = v->p[1];
+       z = v->p[2];
+
+       // yaw
+       xa = ct[0]*x - st[0]*z;
+       za = st[0]*x + ct[0]*z;
+
+       // roll
+       x  = ct[1]*xa + st[1]*y;
+       ya = ct[1]*y  - st[1]*xa;
+
+       // azimuth
+       z  = ct[2]*za - st[2]*ya;
+       y  = ct[2]*ya + st[2]*za;
+
+       // horizontal and vertical projections:
+//     v->pp[0] = D*x/z;
+//     v->pp[1] = D*y/z;
+       v->pp[0] = -y;
+       v->pp[1] =  x;
+       v->pp[2] =  z;
+
+       // NOTE: if perspective transformation is desired,
+       // set "persp" to the range from the surface,
+       // then:
+       // v->projected_h = -v->projected_h * persp/(v->projected_z-persp);
+       // v->projected_v = -v->projected_v * persp/(v->projected_z-persp);
+}
+/*=======================================================================*/
+void evaluate()
+{
+       int i, j;
+       XYZ v[4];
+       
+       if(elevation > PI) elevation -= 2.*PI;
+       roll = elevation * sin(azimuth);
+       yaw  = 1.5*PI + elevation*cos(azimuth);
+
+       //      Find angles from midpoint to viewpoint:
+       st[0] = sin(yaw);
+       st[1] = sin(roll);
+       st[2] = sin(azimuth);
+       ct[0] = cos(yaw);
+       ct[1] = cos(roll);
+       ct[2] = cos(azimuth);
+
+       for(i=0; i<=NH; i++)
+       {
+               for(j=0; j<=NV; j++)
+               {
+                       project(&xyz[i][j]);
+               }
+       }
+
+       Hhi = xyz[0][0].pp[0];
+       Hlo = Hhi;
+       Vhi = xyz[0][0].pp[1];
+       Vlo = Vhi;
+       for(i=0; i<=NH; i++)
+       {
+               for(j=0; j<=NV; j++)
+               {
+                       Hlo = min(Hlo,xyz[i][j].pp[0]);
+                       Hhi = max(Hhi,xyz[i][j].pp[0]);
+                       Vlo = min(Vlo,xyz[i][j].pp[1]);
+                       Vhi = max(Vhi,xyz[i][j].pp[1]);
+               }
+       }
+
+       // Include backface in min-max
+       VectorCopy(xyz[ 0][ 0].p,v[0].p);
+       VectorCopy(xyz[NH][ 0].p,v[1].p);
+       VectorCopy(xyz[NH][NV].p,v[2].p);
+       VectorCopy(xyz[ 0][NV].p,v[3].p);
+       switch(Plane)
+       {
+       case PLANE_XZ0:
+       case PLANE_XZ1:
+               v[0].p[1] = backface;
+               v[1].p[1] = v[0].p[1];
+               v[2].p[1] = v[0].p[1];
+               v[3].p[1] = v[0].p[1];
+               break;
+       case PLANE_YZ0:
+       case PLANE_YZ1:
+               v[0].p[0] = backface;
+               v[1].p[0] = v[0].p[0];
+               v[2].p[0] = v[0].p[0];
+               v[3].p[0] = v[0].p[0];
+               break;
+       default:
+               v[0].p[2] = backface;
+               v[1].p[2] = v[0].p[2];
+               v[2].p[2] = v[0].p[2];
+               v[3].p[2] = v[0].p[2];
+       }
+       for(i=0; i<=3; i++)
+       {
+               project(&v[i]);
+               Hlo = min(Hlo,v[i].pp[0]);
+               Hhi = max(Hhi,v[i].pp[0]);
+               Vlo = min(Vlo,v[i].pp[1]);
+               Vhi = max(Vhi,v[i].pp[1]);
+       }
+
+}
+#endif