diff --git a/Makefile b/Makefile index 132acb1..5d5c1fa 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,8 @@ SSOBJS = $(OBJDIR)\solvespace.obj \ $(OBJDIR)\cmdline.obj \ $(OBJDIR)\graphicswin.obj \ $(OBJDIR)\util.obj \ + $(OBJDIR)\entity.obj \ + $(OBJDIR)\sketch.obj \ LIBS = user32.lib gdi32.lib comctl32.lib advapi32.lib opengl32.lib glu32.lib diff --git a/dsc.h b/dsc.h index 2313dd6..b2eacec 100644 --- a/dsc.h +++ b/dsc.h @@ -9,13 +9,19 @@ class Vector { public: double x, y, z; + Vector Plus(Vector b); + Vector Minus(Vector b); + Vector Negated(void); Vector Cross(Vector b); - double Vector::Dot(Vector b); + double Dot(Vector b); + Vector Normal(int which); Vector RotatedAbout(Vector axis, double theta); double Magnitude(void); Vector ScaledBy(double v); }; +void glVertex3v(Vector u); + class Point2d { public: diff --git a/entity.cpp b/entity.cpp new file mode 100644 index 0000000..8e4e6fe --- /dev/null +++ b/entity.cpp @@ -0,0 +1,32 @@ +#include "solvespace.h" + +void Entity::Draw(void) { + int i; + for(i = 0; i < 3; i++) { + Vector p, u, v; + + if(i == 0) { + p.x = 0; p.y = 0; p.z = 1; + } else if(i == 1) { + p.x = 0; p.y = 1; p.z = 0; + } else { + p.x = 1; p.y = 0; p.z = 0; + } + + u = p.Normal(0); + v = p.Normal(1); + + double s = (min(SS.GW.width, SS.GW.height))*0.4; + + u = u.ScaledBy(s); + v = v.ScaledBy(s); + + Vector r; + glBegin(GL_LINE_LOOP); + r = p; r = r.Minus(v); r = r.Minus(u); glVertex3v(r); + r = p; r = r.Plus(v); r = r.Minus(u); glVertex3v(r); + r = p; r = r.Plus(v); r = r.Plus(u); glVertex3v(r); + r = p; r = r.Minus(v); r = r.Plus(u); glVertex3v(r); + glEnd(); + } +} diff --git a/graphicswin.cpp b/graphicswin.cpp index a22ea65..8154b2d 100644 --- a/graphicswin.cpp +++ b/graphicswin.cpp @@ -1,7 +1,4 @@ #include -#include -#include -#include #include "solvespace.h" @@ -101,7 +98,31 @@ void GraphicsWindow::MouseMiddleDown(double x, double y) { void GraphicsWindow::MouseLeftDown(double x, double y) { } +void GraphicsWindow::MouseScroll(double x, double y, int delta) { + double offsetRight = offset.Dot(projRight); + double offsetDown = offset.Dot(projDown); + + double righti = x/scale - offsetRight; + double downi = y/scale - offsetDown; + + if(delta > 0) { + scale *= 1.3; + } else { + scale /= 1.3; + } + + double rightf = x/scale - offsetRight; + double downf = y/scale - offsetDown; + + offset = offset.Plus(projRight.ScaledBy(rightf - righti)); + offset = offset.Plus(projDown.ScaledBy(downf - downi)); + + Invalidate(); +} + void GraphicsWindow::Paint(int w, int h) { + width = w; height = h; + glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); @@ -127,17 +148,7 @@ void GraphicsWindow::Paint(int w, int h) { glClearDepth(1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glBegin(GL_QUADS); - glVertex3f(-200, -200, 0); - glVertex3f(-200, 200, 0); - glVertex3f( 200, 200, 0); - glVertex3f( 200, -200, 0); - glEnd(); - glBegin(GL_QUADS); - glVertex3f(-200, -200, 200); - glVertex3f(-200, 200, 200); - glVertex3f( 200, 200, 200); - glVertex3f( 200, -200, 200); - glEnd(); + Entity e; + e.Draw(); } diff --git a/sketch.cpp b/sketch.cpp new file mode 100644 index 0000000..43ae6c5 --- /dev/null +++ b/sketch.cpp @@ -0,0 +1,6 @@ +#include "solvespace.h" + +const hRequest Request::HREQUEST_DATUM_PLANE_XY = { 0x00000001 }; +const hRequest Request::HREQUEST_DATUM_PLANE_YZ = { 0x00000002 }; +const hRequest Request::HREQUEST_DATUM_PLANE_ZX = { 0x00000003 }; + diff --git a/sketch.h b/sketch.h index 0d62db0..7f19d47 100644 --- a/sketch.h +++ b/sketch.h @@ -6,6 +6,7 @@ class hEntity; class hPoint; class hRequest; class hParam; +class hGroup; class hRequest { public: @@ -16,9 +17,11 @@ public: class Request { public: - static const int REQUEST_LINE_SEGMENT = 0; - static const int REQUEST_STEP_REPEAT_TRANSLATE = 1; - static const int REQUEST_STEP_REPEAT_TRANSLATE_SYM = 2; + static const hRequest HREQUEST_DATUM_PLANE_XY, + HREQUEST_DATUM_PLANE_YZ, + HREQUEST_DATUM_PLANE_ZX; + + static const int FOR_PLANE = 0; int type; hRequest h; @@ -34,11 +37,12 @@ public: class Entity { public: - static const int ENTITY_LINE_SEGMENT = 0; - static const int ENTITY_PWL_SEGMENT = 1; + static const int ENTITY_PLANE = 0; int type; hEntity h; + + void Draw(void); }; class hPoint { diff --git a/solvespace.cpp b/solvespace.cpp index eb0cd9a..a324573 100644 --- a/solvespace.cpp +++ b/solvespace.cpp @@ -15,8 +15,15 @@ void SolveSpace::Init(void) { point.Clear(); param.Clear(); + // The sketch starts with three requests, for three datum planes. + Request n; + n.type = Request::FOR_PLANE; + req.AddById(&n, Request::HREQUEST_DATUM_PLANE_XY); + req.AddById(&n, Request::HREQUEST_DATUM_PLANE_YZ); + req.AddById(&n, Request::HREQUEST_DATUM_PLANE_ZX); + int i; - for(i = 0; i < 20; i++) { + for(i = 0; i < 10; i++) { TW.Printf("this is line number %d", i); } } diff --git a/solvespace.h b/solvespace.h index 318315c..d4fb093 100644 --- a/solvespace.h +++ b/solvespace.h @@ -17,6 +17,10 @@ void dbp(char *str, ...); #include #include #include +#include // required for GL stuff +#include +#include + #include "dsc.h" #include "ui.h" #include "sketch.h" diff --git a/ui.h b/ui.h index a477a2e..a2ddf5a 100644 --- a/ui.h +++ b/ui.h @@ -62,14 +62,15 @@ public: // This table describes the top-level menus in the graphics winodw. typedef void MenuHandler(int id); typedef struct { - int level; // 0 == on menu bar, 1 == one level down, ... + int level; // 0 == on menu bar, 1 == one level down char *label; // or NULL for a separator int id; // unique ID MenuHandler *fn; } MenuEntry; static const MenuEntry menu[]; - + // The width and height (in pixels) of the window. + double width, height; // These parameters define the map from 2d screen coordinates to the // coordinates of the 3d sketch points. We will use an axonometric // projection. @@ -94,7 +95,7 @@ public: void MouseLeftDown(double x, double y); void MouseLeftDoubleClick(double x, double y); void MouseMiddleDown(double x, double y); - void MouseScroll(int delta); + void MouseScroll(double x, double y, int delta); }; diff --git a/util.cpp b/util.cpp index 547a375..4542d16 100644 --- a/util.cpp +++ b/util.cpp @@ -23,6 +23,35 @@ void MakeMatrix(double *mat, double a11, double a12, double a13, double a14, mat[15] = a44; } +Vector Vector::Plus(Vector b) { + Vector r; + + r.x = x + b.x; + r.y = y + b.y; + r.z = z + b.z; + + return r; +} + +Vector Vector::Minus(Vector b) { + Vector r; + + r.x = x - b.x; + r.y = y - b.y; + r.z = z - b.z; + + return r; +} + +Vector Vector::Negated(void) { + Vector r; + + r.x = -x; + r.y = -y; + r.z = -z; + + return r; +} Vector Vector::Cross(Vector b) { Vector r; @@ -38,6 +67,42 @@ double Vector::Dot(Vector b) { return (x*b.x + y*b.y + z*b.z); } +Vector Vector::Normal(int which) { + Vector n; + + // Arbitrarily choose one vector that's normal to us, pivoting + // appropriately. + double xa = fabs(x), ya = fabs(y), za = fabs(z); + double minc = min(min(xa, ya), za); + if(minc == xa) { + n.x = 0; + n.y = z; + n.z = -y; + } else if(minc == ya) { + n.y = 0; + n.z = x; + n.x = -z; + } else if(minc == za) { + n.z = 0; + n.x = y; + n.y = -x; + } else { + oops(); + } + + if(which == 0) { + // That's the vector we return. + } else if(which == 1) { + n = this->Cross(n); + } else { + oops(); + } + + n = n.ScaledBy(1/n.Magnitude()); + + return n; +} + Vector Vector::RotatedAbout(Vector axis, double theta) { double c = cos(theta); double s = sin(theta); @@ -72,3 +137,8 @@ Vector Vector::ScaledBy(double v) { return r; } + +void glVertex3v(Vector u) +{ + glVertex3f((GLfloat)u.x, (GLfloat)u.y, (GLfloat)u.z); +} diff --git a/win32/w32main.cpp b/win32/w32main.cpp index 9388a1e..9cdcb18 100644 --- a/win32/w32main.cpp +++ b/win32/w32main.cpp @@ -16,12 +16,16 @@ HINSTANCE Instance; -HWND TextWnd, GraphicsWnd; +HWND TextWnd; HWND TextWndScrollBar; int TextWndScrollPos; int TextWndRows; +HWND GraphicsWnd; HMENU SubMenus[100]; +struct { + int x, y; +} LastMousePos; int ClientIsSmallerBy; @@ -203,7 +207,7 @@ LRESULT CALLBACK TextWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) } break; } - + case WM_CHAR: SS.TW.KeyPressed(wParam); HandleTextWindowScrollBar(SB_BOTTOM, 0); @@ -317,6 +321,9 @@ LRESULT CALLBACK GraphicsWndProc(HWND hwnd, UINT msg, WPARAM wParam, x = x - (r.right - r.left)/2; y = (r.bottom - r.top)/2 - y; + LastMousePos.x = x; + LastMousePos.y = y; + if(msg == WM_LBUTTONDOWN) { SS.GW.MouseLeftDown(x, y); } else if(msg == WM_MBUTTONDOWN) { @@ -333,6 +340,11 @@ LRESULT CALLBACK GraphicsWndProc(HWND hwnd, UINT msg, WPARAM wParam, } break; } + case WM_MOUSEWHEEL: { + int delta = GET_WHEEL_DELTA_WPARAM(wParam); + SS.GW.MouseScroll(LastMousePos.x, LastMousePos.y, delta); + break; + } case WM_CLOSE: case WM_DESTROY: