home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dream 52
/
Amiga_Dream_52.iso
/
Linux
/
Divers
/
freedraft.tar.gz
/
freedraft.tar
/
FREEdraft-050298
/
VIEWPORT
/
vdglcanvas.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1998-05-01
|
15KB
|
600 lines
// vdglcanvas.cpp
// Copyright (C) 1997 Cliff Johnson //
// //
// This program is free software; you can redistribute it and/or //
// modify it under the terms of the GNU General Public //
// License as published by the Free Software Foundation; either //
// version 2 of the License, or (at your option) any later version. //
// //
// This software 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 //
// General Public License for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this software (see COPYING.LIB); if not, write to the //
// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. //
#include <iostream.h>
#include <data_enum.h>
#include <vdglcanvas.h>
#include <vdcmdwin.h>
#include <drawablegeom.h>
#include <point.h>
#include <line.h>
#include <selectstack.h>
#include <vdapp_enum.h>
#include <attrib_enum.h>
#include <coreexception.h>
//************************************************************************************
void VDGLCanvas::LoadRegister(CanvasRegister* cr)
{
canvasRegister = cr;
}
//************************************************************************************
//======================>>> testGLCanvasPane::VDGLCanvas<<<======================
VDGLCanvas::VDGLCanvas(CanvasRegister* cr, unsigned int glmode):
vBaseGLCanvasPane(glmode),
glState(Point(),1.,3.4) // centered at zero, scale 1, 3.8 pixels/mm
{
// load register
canvasRegister = cr;
// set initial conditions
interfaceMode = NOMODE;
pickCount = 0;
initDone = 0;
}
//======================>>> testGLCanvasPane::~VDGLCanvas<<<======================
VDGLCanvas::~VDGLCanvas()
{
}
//======================>>> testGLCanvasPane::graphicsInit<<<======================
void VDGLCanvas::graphicsInit(void)
{
vBaseGLCanvasPane::graphicsInit(); // call the superclass first
// glEnable(GL_DEPTH_TEST);
glClearDepth(1.0);
glClearColor(0.0,0.0,0.0,0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
SetOrtho2D();
glMatrixMode(GL_MODELVIEW);
initDone = 1;
}
//======================>>> testGLCanvasPane::MouseDown <<<======================
void VDGLCanvas::MouseDown(int x, int y, int button)
{
//cerr << "VDGLCanvas::MouseDown()" << endl;
switch(interfaceMode)
{
case PANNING:
case ZOOMIN:
case ZOOMOUT:
{
if(button != 1)break;
Point p = PickedCoord(x,y);
pStack.Push(p);
break;
}
case CENTERING:
{
if(button != 1)break;
glState.SetCenter(PickedCoord(x,y));
vglMakeCurrent();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
SetOrtho2D();
glMatrixMode(GL_MODELVIEW);
Redraw(0,0,0,0);
break;
}
// case PICKING:
// case NOMODE:
// {
// SelectRegisteredEntities(x,y,button);
// interfaceMode = NOMODE;
// break;
// }
}
// we are overriding the following:
// vBaseGLCanvasPane::MouseDown(x,y,button);
}
//========================>>> VDGLCanvas::MouseUp <<<======================
void VDGLCanvas::MouseUp(int x, int y, int button)
{
switch(interfaceMode)
{
case PANNING:
{
if(button != 1)break;
Point p1 = pStack.Pop();
Point p2 = PickedCoord(x,y);
glState.SetCenter(glState.GetCenter() - p2 + p1);
vglMakeCurrent();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
SetOrtho2D();
glMatrixMode(GL_MODELVIEW);
Redraw(0,0,0,0);
break;
}
case ZOOMIN:
{
if(button != 1)break;
Point p1 = pStack.Pop();
Point p2 = PickedCoord(x,y);
glState.ZoomIn(p1,p2,GetWidth(),GetHeight());
vglMakeCurrent();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
SetOrtho2D();
glMatrixMode(GL_MODELVIEW);
Redraw(0,0,0,0);
break;
}
case ZOOMOUT:
{
if(button != 1)break;
Point p1 = pStack.Pop();
Point p2 = PickedCoord(x,y);
glState.ZoomOut(p1,p2,GetWidth(),GetHeight());
vglMakeCurrent();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
SetOrtho2D();
glMatrixMode(GL_MODELVIEW);
Redraw(0,0,0,0);
break;
}
case PICKING:
case NOMODE:
{
SelectRegisteredEntities(x,y,button);
interfaceMode = NOMODE;
break;
}
}
// vBaseGLCanvasPane::MouseUp(x,y,button);
}
//======================>>> VDGLCanvas::MouseMove <<<======================
void VDGLCanvas::MouseMove(int x, int y, int button)
{
// animate the displacment line or selection box
switch(interfaceMode)
{
case PANNING:
{
if(button != 1)break;
Point p1 = pStack.Top();
Point p2 = PickedCoord(x,y);
vglMakeCurrent();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DrawRegisteredEntities();
SetAttributes(Attributes(FD_RED,FD_LINESTYLE_SOLID,1,0));
glBegin(GL_LINES);
glVertex2f(p1[0],p1[1]);
glVertex2f(p2[0],p2[1]);
glEnd();
vglFlush();
break;
}
case ZOOMIN:
case ZOOMOUT:
{
if(button != 1)break;
Point p1 = pStack.Top();
Point p2 = PickedCoord(x,y);
vglMakeCurrent();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DrawRegisteredEntities();
SetAttributes(Attributes(FD_RED,FD_LINESTYLE_SOLID,1,0));
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glBegin(GL_POLYGON);
glVertex2f(p1[0],p1[1]);
glVertex2f(p2[0],p1[1]);
glVertex2f(p2[0],p2[1]);
glVertex2f(p1[0],p2[1]);
glEnd();
vglFlush();
break;
}
}
vBaseGLCanvasPane::MouseMove(x,y,button);
}
//=========================>>> VDGLCanvas::Redraw <<<======================
void VDGLCanvas::Redraw(int x, int y, int w, int h)
{
static int inRedraw = 0;
if (inRedraw || !initDone)return; // Don't draw until initialized
inRedraw = 1; // Don't allow recursive redraws.
vglMakeCurrent();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DrawRegisteredEntities();
vglFlush();
inRedraw = 0;
}
//======================>>> virtual void VDGLCanvas::Resize <<<======================
void VDGLCanvas::Resize(int w, int h)
{
vBaseGLCanvasPane::Resize(w,h);
vglMakeCurrent();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
SetOrtho2D();
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DrawRegisteredEntities();
vglFlush();
}
int VDGLCanvas::GetWidth()
{
return vBaseGLCanvasPane::GetWidth();
}
int VDGLCanvas::GetHeight()
{
return vBaseGLCanvasPane::GetHeight();
}
//=========================VDGLCanvas::DrawRegisteredEnttities===============
void VDGLCanvas::DrawRegisteredEntities()
{
// pass through the list of handles, drawing each entity
RegisteredEntity re; // use a temporary copy for processing
float scale = glState.GetScale();
if(!canvasRegister)return; // if there is a list ( not NULL) ...
canvasRegister->Init(); // reset the list iterator
while(canvasRegister->NextItem(re) )
{
if(re.IsVisible())
{
if(re.IsHighlight())SetAttributes(Attributes(FD_MEDGREY,FD_LINESTYLE_SOLID,2,0));
else SetAttributes(re.GetAttributes());
re.Draw(scale);
}
}
}
//=========================VDGLCanvas::SelectRegisteredEnttities===============
void VDGLCanvas::SelectRegisteredEntities(int x, int y, int button)
{
//cerr << "VDGLCanvas::SelectRegisteredEntities()" << endl;
RegisteredEntity re; // use a temporary copy for processing
if(!canvasRegister)return; // if there is a list ( not NULL) ...
// prepare for picking
GLuint selectBuf[BUFSIZE];
GLint hits;
GLint viewport[4];
float scale = glState.GetScale();
glGetIntegerv(GL_VIEWPORT,viewport);
glSelectBuffer(BUFSIZE,selectBuf);
glRenderMode(GL_SELECT);
glInitNames();
glPushName(0);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
// 6x6 pixel picking region near cursor location
gluPickMatrix(static_cast<GLfloat>(x), static_cast<GLfloat>(viewport[3] -y),
10.0,10.0,viewport);
SetOrtho2D();
// draw the entities
canvasRegister->Init(); // reset the list iterator
// for each visible handle
while(canvasRegister->NextItem(re) ) re.Select(scale);
// collect the pick information
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glFlush();
hits = glRenderMode(GL_RENDER);
SendCmdWindowResponse(x,y,button, hits,selectBuf);
}
//===========================================================================================
void VDGLCanvas::SendCmdWindowResponse(int x, int y, int button, GLint hits,GLuint* selectBuf)
{
//cerr << "VDGLCanvas::SendCmdWindowResponse()" << endl;
// process the selection records
GLuint *ptr = selectBuf;
GLuint names;
RegisteredEntity re;
Handle htmp;
unsigned int hidx;
SelectStack ss(button, PickedCoord(x,y)); // initialize selectstack
canvasRegister->Init(); // reset the list iterator
// parse the hit records for the picked names
// for each hit...
for(int i=0; i<hits; i++){
// just skip through this stuff for our purposes
names = *ptr; // get number of names on stack when hit happened
ptr++; // to z1;
ptr++; // to z2;
ptr++; // to name lists
// for(unsigned int j=0;j<names;j++){
// this name is what we want
// if(j == 0)
hidx = *ptr; // get the name (unsigned integer)
ptr++;
// } // get past this record
// find the registered entity with this handle idx - handles should be in the same order
// as in the canvas register
try
{
htmp = canvasRegister->GetHandleFromName(hidx);
ss.Push(htmp);
}
catch(CoreException & ce)
{
cerr << "CoreException Raised in VDGLCanvas::SendCmdWindowResponse()" << endl;
cerr << " " << ce.what() << endl;
}
}
// all done. Send the selected handles back to the command window
(static_cast<vdCmdWindow*>(_parentWin))->CanvasPick(ss);
}
//=========================VDGLCanvas::DrawLine===============
//
//void VDGLCanvas::DrawLine(const Line& l)
//{
// // Point p0 = Point(l.Origin()) + (10000. * Point(l.Direction()));
// // Point p1 = Point(l.Origin()) - (10000. * Point(l.Direction()));
// Point p0 = l.Origin() + (10000. * l.Direction());
// Point p1 = l.Origin() - (10000. * l.Direction());
// glBegin(GL_LINES);
// glVertex2f(p0[0],p0[1]);
// glVertex2f(p1[0],p1[1]);
// glEnd();
//}
//
//
//----------------------VDGLCanvas::SetAttributes-----------------------
void VDGLCanvas::SetAttributes(const Attributes& a) // loading a null register cancels display
{
if(a == currentAttributes)return; // no reason to change anything
// we have only a small set of colors so we can implement useable selections by color
if(!(a.GetColor() == currentAttributes.GetColor()))
{
float r,g,b;
int colidx = a.GetColor();
r = vStdColors[colidx].r()/255.;
g = vStdColors[colidx].g()/255.;
b = vStdColors[colidx].b()/255.;
glColor3f(r,g,b);
}
unsigned short sx;
if(!((sx = a.GetLineStyle()) == currentAttributes.GetLineStyle()))
{
// linestippling
switch(sx)
{
case FD_LINESTYLE_SOLID:
case FD_LINESTYLE_LONGDASH:
case FD_LINESTYLE_DOTTED:
glLineStipple(1,sx);
break;
case FD_LINESTYLE_CHAIN:
glLineStipple(2,sx);
break;
}
glEnable(GL_LINE_STIPPLE);
}
// process thicknesses here
if(!(a.GetThick() == currentAttributes.GetThick())){
glPointSize(a.GetThick());
glLineWidth(a.GetThick());
}
currentAttributes = a;
}
//===========================VDGLCanvas::Register ==================
//
// add an entity with the window - and with the current canvasRegister
//void VDGLCanvas::Register(const Handle& h, const Attributes& a, const Visibility& v)
//{
// if(canvasRegister)canvasRegister->Register(h,a,v);
//}
//
//===========================VDGLCanvas::CancelAction==================
void VDGLCanvas::CancelAction()
{
interfaceMode = NOMODE;
pickCount = 0;
pStack.Clear();
}
//===========================VDGLCanvas::PickPan=========================
void VDGLCanvas::PickPan()
{
interfaceMode = PANNING;
}
//===============================VDGLCanvas::PickCenter====================
void VDGLCanvas::PickCenter()
{
interfaceMode = CENTERING;
}
//===============================VDGLCanvas::ZoomIn====================
void VDGLCanvas::ZoomIn()
{
interfaceMode = ZOOMIN;
}
//===============================VDGLCanvas::ZoomOut====================
void VDGLCanvas::ZoomOut()
{
interfaceMode = ZOOMOUT;
}
//===============================VDGLCanvas::ZoomOut====================
void VDGLCanvas::ResetView()
{
glState.viewCenter = Point();
glState.viewScale = 1.;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
SetOrtho2D();
glMatrixMode(GL_MODELVIEW);
Redraw(0,0,0,0);
}
//void VDGLCanvas::SetGridLines(bool status, int step)
//{
// drawGrid = status;
// if(drawGrid)gridStep = step;
//}
//
//void VDGLCanvas::DrawGridLines()
//{
//}
//void VDGLCanvas::LoadDrawableGeom(const DrawableGeom& dptr )
//{
// for(int i=0; i< drawableRegister.size(); i++)
// {
// // replace if already in the register
// if( dptr.Type() == drawableRegister[i].Type())
// {
// drawableRegister[i] = dptr;
// return;
// }
// }
//
// // not already in the list, add to the register.
// drawableRegister.push_back(dptr);
//}
void VDGLCanvas::ModifyView(const vKey& keysym)
{
// zoom in, zoom out pan left,right,up,down
float scale = glState.GetScale();
Point center = glState.GetCenter();
float ppmm = glState.GetPPMM();
float w = GetWidth();
float h = GetHeight();
switch(keysym)
{
//case KB_CenterView:
case KB_ZoomUp:
glState.SetScale(scale * 1.1);
break;
case KB_ZoomDown:
glState.SetScale(scale / 1.1);
break;
// pan 10% of canvas size in each direction
case KB_LeftArrow: // geometry should move left, so the center goes to the right.
glState.SetCenter(center + Point(.1*w/(scale*ppmm),0));
break;
case KB_UpArrow:
glState.SetCenter(center - Point(0,.1*h/(scale*ppmm)));
break;
case KB_RightArrow:
glState.SetCenter(center - Point(.1*w/(scale*ppmm),0));
break;
case KB_DownArrow:
glState.SetCenter(center + Point(0,.1*h/(scale*ppmm)));
break;
}
vglMakeCurrent();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
SetOrtho2D();
glMatrixMode(GL_MODELVIEW);
Redraw(0,0,0,0);
}