Start to add OpenGL support to SolveSpace, for the graphical view.
I've got the user interface to pan and rotate an object, more or less works. [git-p4: depot-paths = "//depot/solvespace/": change = 1654]
This commit is contained in:
parent
fcdf43d487
commit
e426fe8a53
3
Makefile
3
Makefile
@ -12,9 +12,10 @@ W32OBJS = $(OBJDIR)\w32main.obj \
|
||||
SSOBJS = $(OBJDIR)\solvespace.obj \
|
||||
$(OBJDIR)\cmdline.obj \
|
||||
$(OBJDIR)\graphicswin.obj \
|
||||
$(OBJDIR)\util.obj \
|
||||
|
||||
|
||||
LIBS = user32.lib gdi32.lib comctl32.lib advapi32.lib
|
||||
LIBS = user32.lib gdi32.lib comctl32.lib advapi32.lib opengl32.lib glu32.lib
|
||||
|
||||
all: $(OBJDIR)/solvespace.exe
|
||||
@cp $(OBJDIR)/solvespace.exe .
|
||||
|
15
dsc.h
15
dsc.h
@ -5,10 +5,23 @@
|
||||
typedef unsigned long DWORD;
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
typedef struct {
|
||||
typedef struct VectorTag Vector;
|
||||
|
||||
typedef struct VectorTag {
|
||||
double x, y, z;
|
||||
|
||||
Vector Cross(Vector b);
|
||||
double Vector::Dot(Vector b);
|
||||
Vector RotatedAbout(Vector axis, double theta);
|
||||
double Magnitude(void);
|
||||
Vector ScaledBy(double v);
|
||||
|
||||
} Vector;
|
||||
|
||||
typedef struct {
|
||||
double x, y;
|
||||
} Point2d;
|
||||
|
||||
template <class T, class H> struct IdList {
|
||||
typedef struct {
|
||||
T v;
|
||||
|
102
graphicswin.cpp
102
graphicswin.cpp
@ -1,5 +1,9 @@
|
||||
#include "solvespace.h"
|
||||
#include <stdarg.h>
|
||||
#include <windows.h>
|
||||
#include <gl/gl.h>
|
||||
#include <gl/glu.h>
|
||||
|
||||
#include "solvespace.h"
|
||||
|
||||
const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
||||
{ 0, "&File", 0, NULL },
|
||||
@ -33,3 +37,99 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
||||
{ -1 },
|
||||
};
|
||||
|
||||
void GraphicsWindow::Init(void) {
|
||||
offset.x = offset.y = offset.z = 0.9;
|
||||
scale = 1;
|
||||
projRight.x = 1; projRight.y = projRight.z = 0;
|
||||
projDown.y = 1; projDown.z = projDown.x = 0;
|
||||
|
||||
}
|
||||
|
||||
void GraphicsWindow::NormalizeProjectionVectors(void) {
|
||||
Vector norm = projRight.Cross(projDown);
|
||||
projDown = norm.Cross(projRight);
|
||||
|
||||
projDown = projDown.ScaledBy(1/projDown.Magnitude());
|
||||
projRight = projRight.ScaledBy(1/projRight.Magnitude());
|
||||
}
|
||||
|
||||
void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
||||
bool middleDown, bool rightDown, bool shiftDown, bool ctrlDown)
|
||||
{
|
||||
if(middleDown) {
|
||||
double dx = (x - orig.mouse.x) / scale;
|
||||
double dy = (y - orig.mouse.y) / scale;
|
||||
|
||||
if(shiftDown) {
|
||||
offset.x = orig.offset.x + dx*projRight.x + dy*projDown.x;
|
||||
offset.y = orig.offset.y + dx*projRight.y + dy*projDown.y;
|
||||
offset.z = orig.offset.z + dx*projRight.z + dy*projDown.z;
|
||||
} else if(ctrlDown) {
|
||||
double theta = atan2(orig.mouse.y, orig.mouse.x);
|
||||
theta -= atan2(y, x);
|
||||
|
||||
Vector normal = orig.projRight.Cross(orig.projDown);
|
||||
projRight = orig.projRight.RotatedAbout(normal, theta);
|
||||
projDown = orig.projDown.RotatedAbout(normal, theta);
|
||||
|
||||
NormalizeProjectionVectors();
|
||||
} else {
|
||||
double s = 0.3*(PI/180); // degrees per pixel
|
||||
projRight = orig.projRight.RotatedAbout(orig.projDown, -s*dx);
|
||||
projDown = orig.projDown.RotatedAbout(orig.projRight, s*dy);
|
||||
|
||||
NormalizeProjectionVectors();
|
||||
|
||||
orig.projRight = projRight;
|
||||
orig.projDown = projDown;
|
||||
orig.mouse.x = x;
|
||||
orig.mouse.y = y;
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsWindow::MouseMiddleDown(double x, double y) {
|
||||
orig.offset = offset;
|
||||
orig.projDown = projDown;
|
||||
orig.projRight = projRight;
|
||||
orig.mouse.x = x;
|
||||
orig.mouse.y = y;
|
||||
}
|
||||
|
||||
void GraphicsWindow::MouseLeftDown(double x, double y) {
|
||||
}
|
||||
|
||||
void GraphicsWindow::Paint(int w, int h) {
|
||||
glViewport(0, 0, w, h);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glScaled(scale*2.0/w, scale*2.0/h, 0);
|
||||
|
||||
double tx = projRight.Dot(offset);
|
||||
double ty = projDown.Dot(offset);
|
||||
double mat[16];
|
||||
MakeMatrix(mat, projRight.x, projRight.y, projRight.z, tx,
|
||||
projDown.x, projDown.y, projDown.z, ty,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 1);
|
||||
glMultMatrixd(mat);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glClearIndex((GLfloat)0);
|
||||
glClearDepth(1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
GLUquadricObj *quadObj;
|
||||
quadObj = gluNewQuadric();
|
||||
gluQuadricDrawStyle(quadObj, GLU_LINE);
|
||||
gluSphere(quadObj, 300, 4, 4);
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ SolveSpace SS;
|
||||
|
||||
void SolveSpace::Init(void) {
|
||||
TW.Init();
|
||||
GW.Init();
|
||||
|
||||
int i;
|
||||
for(i = 0; i < 20; i++) {
|
||||
|
10
solvespace.h
10
solvespace.h
@ -5,6 +5,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "dsc.h"
|
||||
#include "ui.h"
|
||||
#include "sketch.h"
|
||||
@ -13,8 +14,17 @@
|
||||
#define oops() do { dbp("oops at line %d, file %s", __LINE__, __FILE__); \
|
||||
exit(-1); } while(0)
|
||||
void dbp(char *str, ...);
|
||||
void Invalidate(void);
|
||||
|
||||
|
||||
|
||||
#define arraylen(x) (sizeof((x))/sizeof((x)[0]))
|
||||
#define PI (3.1415926535897931)
|
||||
void MakeMatrix(double *mat, double a11, double a12, double a13, double a14,
|
||||
double a21, double a22, double a23, double a24,
|
||||
double a31, double a32, double a33, double a34,
|
||||
double a41, double a42, double a43, double a44);
|
||||
|
||||
|
||||
typedef struct {
|
||||
TextWindow TW;
|
||||
|
18
ui.h
18
ui.h
@ -64,16 +64,26 @@ typedef struct {
|
||||
// coordinates of the 3d sketch points. We will use an axonometric
|
||||
// projection.
|
||||
Vector offset;
|
||||
double scale;
|
||||
Vector projRight;
|
||||
Vector projDown;
|
||||
double scale;
|
||||
struct {
|
||||
Vector offset;
|
||||
Vector projRight;
|
||||
Vector projDown;
|
||||
Point2d mouse;
|
||||
} orig;
|
||||
|
||||
void Init(void);
|
||||
void NormalizeProjectionVectors(void);
|
||||
|
||||
// These are called by the platform-specific code.
|
||||
void Paint(void);
|
||||
void Paint(int w, int h);
|
||||
void MouseMoved(double x, double y, bool leftDown, bool middleDown,
|
||||
bool rightDown);
|
||||
void MouseLeftClick(double x, double y);
|
||||
bool rightDown, bool shiftDown, bool ctrlDown);
|
||||
void MouseLeftDown(double x, double y);
|
||||
void MouseLeftDoubleClick(double x, double y);
|
||||
void MouseMiddleDown(double x, double y);
|
||||
void MouseScroll(int delta);
|
||||
} GraphicsWindow;
|
||||
|
||||
|
80
util.cpp
Normal file
80
util.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
#include "solvespace.h"
|
||||
|
||||
void MakeMatrix(double *mat, double a11, double a12, double a13, double a14,
|
||||
double a21, double a22, double a23, double a24,
|
||||
double a31, double a32, double a33, double a34,
|
||||
double a41, double a42, double a43, double a44)
|
||||
{
|
||||
mat[ 0] = a11;
|
||||
mat[ 1] = a21;
|
||||
mat[ 2] = a31;
|
||||
mat[ 3] = a41;
|
||||
mat[ 4] = a12;
|
||||
mat[ 5] = a22;
|
||||
mat[ 6] = a32;
|
||||
mat[ 7] = a42;
|
||||
mat[ 8] = a13;
|
||||
mat[ 9] = a23;
|
||||
mat[10] = a33;
|
||||
mat[11] = a43;
|
||||
mat[12] = a14;
|
||||
mat[13] = a24;
|
||||
mat[14] = a34;
|
||||
mat[15] = a44;
|
||||
}
|
||||
|
||||
|
||||
Vector Vector::Cross(Vector b)
|
||||
{
|
||||
Vector r;
|
||||
|
||||
r.x = -(z*b.y) + (y*b.z);
|
||||
r.y = (z*b.x) - (x*b.z);
|
||||
r.z = -(y*b.x) + (x*b.y);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
double Vector::Dot(Vector b)
|
||||
{
|
||||
return (x*b.x + y*b.y + z*b.z);
|
||||
}
|
||||
|
||||
Vector Vector::RotatedAbout(Vector axis, double theta)
|
||||
{
|
||||
double c = cos(theta);
|
||||
double s = sin(theta);
|
||||
|
||||
Vector r;
|
||||
|
||||
r.x = (x)*(c + (1 - c)*(axis.x)*(axis.x)) +
|
||||
(y)*((1 - c)*(axis.x)*(axis.y) - s*(axis.z)) +
|
||||
(z)*((1 - c)*(axis.x)*(axis.z) + s*(axis.y));
|
||||
|
||||
r.y = (x)*((1 - c)*(axis.y)*(axis.x) + s*(axis.z)) +
|
||||
(y)*(c + (1 - c)*(axis.y)*(axis.y)) +
|
||||
(z)*((1 - c)*(axis.y)*(axis.z) - s*(axis.x));
|
||||
|
||||
r.z = (x)*((1 - c)*(axis.z)*(axis.x) - s*(axis.y)) +
|
||||
(y)*((1 - c)*(axis.z)*(axis.y) + s*(axis.x)) +
|
||||
(z)*(c + (1 - c)*(axis.z)*(axis.z));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
double Vector::Magnitude(void)
|
||||
{
|
||||
return sqrt(x*x + y*y + z*z);
|
||||
}
|
||||
|
||||
Vector Vector::ScaledBy(double v)
|
||||
{
|
||||
Vector r;
|
||||
|
||||
r.x = x * v;
|
||||
r.y = y * v;
|
||||
r.z = z * v;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <gl/gl.h>
|
||||
#include <gl/glu.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
@ -197,6 +199,40 @@ LRESULT CALLBACK TextWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static HGLRC CreateGlContext(HDC hdc)
|
||||
{
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
int pixelFormat;
|
||||
|
||||
memset(&pfd, 0, sizeof(pfd));
|
||||
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
|
||||
PFD_DOUBLEBUFFER;
|
||||
pfd.dwLayerMask = PFD_MAIN_PLANE;
|
||||
pfd.iPixelType = PFD_TYPE_COLORINDEX;
|
||||
pfd.cColorBits = 8;
|
||||
pfd.cDepthBits = 16;
|
||||
pfd.cAccumBits = 0;
|
||||
pfd.cStencilBits = 0;
|
||||
|
||||
pixelFormat = ChoosePixelFormat(hdc, &pfd);
|
||||
if(!pixelFormat) oops();
|
||||
|
||||
if(!SetPixelFormat(hdc, pixelFormat, &pfd)) oops();
|
||||
|
||||
HGLRC hgrc = wglCreateContext(hdc);
|
||||
wglMakeCurrent(hdc, hgrc);
|
||||
|
||||
return hgrc;
|
||||
}
|
||||
|
||||
void Invalidate(void)
|
||||
{
|
||||
InvalidateRect(GraphicsWnd, NULL, FALSE);
|
||||
InvalidateRect(TextWnd, NULL, FALSE);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK GraphicsWndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
@ -208,6 +244,64 @@ LRESULT CALLBACK GraphicsWndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
InvalidateRect(TextWnd, NULL, FALSE);
|
||||
break;
|
||||
|
||||
case WM_ERASEBKGND:
|
||||
break;
|
||||
|
||||
case WM_SIZE:
|
||||
InvalidateRect(GraphicsWnd, NULL, FALSE);
|
||||
break;
|
||||
|
||||
case WM_PAINT: {
|
||||
InvalidateRect(GraphicsWnd, NULL, FALSE);
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc = BeginPaint(hwnd, &ps);
|
||||
|
||||
HGLRC hgrc = CreateGlContext(hdc);
|
||||
|
||||
RECT r;
|
||||
GetClientRect(GraphicsWnd, &r);
|
||||
int w = r.right - r.left;
|
||||
int h = r.bottom - r.top;
|
||||
|
||||
SS.GW.Paint(w, h);
|
||||
|
||||
SwapBuffers(hdc);
|
||||
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
wglDeleteContext(hgrc);
|
||||
|
||||
EndPaint(hwnd, &ps);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN: {
|
||||
int x = LOWORD(lParam);
|
||||
int y = HIWORD(lParam);
|
||||
|
||||
RECT r;
|
||||
GetClientRect(GraphicsWnd, &r);
|
||||
x = x - (r.right - r.left)/2;
|
||||
y = (r.bottom - r.top)/2 - y;
|
||||
|
||||
if(msg == WM_LBUTTONDOWN) {
|
||||
SS.GW.MouseLeftDown(x, y);
|
||||
} else if(msg == WM_MBUTTONDOWN) {
|
||||
SS.GW.MouseMiddleDown(x, y);
|
||||
} else if(msg == WM_MOUSEMOVE) {
|
||||
SS.GW.MouseMoved(x, y,
|
||||
!!(wParam & MK_LBUTTON),
|
||||
!!(wParam & MK_MBUTTON),
|
||||
!!(wParam & MK_RBUTTON),
|
||||
!!(wParam & MK_SHIFT),
|
||||
!!(wParam & MK_CONTROL));
|
||||
} else {
|
||||
oops();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_CLOSE:
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
@ -260,7 +354,7 @@ static void CreateMainWindows(void)
|
||||
wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_OWNDC |
|
||||
CS_DBLCLKS;
|
||||
wc.lpfnWndProc = (WNDPROC)GraphicsWndProc;
|
||||
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
|
||||
wc.lpszClassName = "GraphicsWnd";
|
||||
wc.lpszMenuName = NULL;
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
@ -271,8 +365,8 @@ static void CreateMainWindows(void)
|
||||
HMENU top = CreateGraphicsWindowMenus();
|
||||
GraphicsWnd = CreateWindowEx(0, "GraphicsWnd", "SolveSpace (View Sketch)",
|
||||
WS_OVERLAPPED | WS_THICKFRAME | WS_CLIPCHILDREN | WS_MAXIMIZEBOX |
|
||||
WS_MINIMIZEBOX | WS_SYSMENU | WS_SIZEBOX,
|
||||
600, 300, 400, 400, NULL, top, Instance, NULL);
|
||||
WS_MINIMIZEBOX | WS_SYSMENU | WS_SIZEBOX | WS_CLIPSIBLINGS,
|
||||
600, 300, 200, 200, NULL, top, Instance, NULL);
|
||||
if(!GraphicsWnd) oops();
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user