Add ability to set a background image. I import a png with libpng,

load it as a texture, and show it instead of a flat-color
background. Includes user interface to specify scale and
translation of image, but the rotation is always aligned to the
view.

[git-p4: depot-paths = "//depot/solvespace/": change = 2071]
solver
Jonathan Westhues 2009-11-07 17:11:38 -08:00
parent 28d1bc67bc
commit d74b1e7ece
6 changed files with 196 additions and 2 deletions

View File

@ -479,9 +479,58 @@ void GraphicsWindow::Paint(int w, int h) {
ForceTextWindowShown();
}
glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(SS.bgImage.fromFile) {
// If a background image is loaded, then we draw it now as a texture.
// This handles the resizing for us nicely.
glBindTexture(GL_TEXTURE_2D, 10);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
SS.bgImage.rw, SS.bgImage.rh,
0,
GL_RGB, GL_UNSIGNED_BYTE,
SS.bgImage.fromFile);
double tw = ((double)SS.bgImage.w) / SS.bgImage.rw,
th = ((double)SS.bgImage.h) / SS.bgImage.rh;
double mmw = SS.bgImage.w / SS.bgImage.scale,
mmh = SS.bgImage.h / SS.bgImage.scale;
Vector origin = SS.bgImage.origin;
origin = origin.DotInToCsys(projRight, projUp, n);
// Place the depth of our origin at the point that corresponds to
// w = 1, so that it's unaffected by perspective.
origin.z = (offset.ScaledBy(-1)).Dot(n);
origin = origin.ScaleOutOfCsys(projRight, projUp, n);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2d(0, 0);
glxVertex3v(origin);
glTexCoord2d(0, th);
glxVertex3v(origin.Plus(projUp.ScaledBy(mmh)));
glTexCoord2d(tw, th);
glxVertex3v(origin.Plus(projRight.ScaledBy(mmw).Plus(
projUp. ScaledBy(mmh))));
glTexCoord2d(tw, 0);
glxVertex3v(origin.Plus(projRight.ScaledBy(mmw)));
glEnd();
glDisable(GL_TEXTURE_2D);
}
// Now clear the depth; so the background color and image are both at
// the very back of everything.
glClearDepth(1.0);
// Nasty case when we're reloading the imported files; could be that
// we get an error, so a dialog pops up, and a message loop starts, and
// we have to get called to paint ourselves. If the sketch is screwed

View File

@ -79,6 +79,13 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
if(GraphicsEditControlIsVisible()) return;
if(context.active) return;
if(!orig.mouseDown) {
// If someone drags the mouse into our window with the left button
// already depressed, then we don't have our starting point; so
// don't try.
leftDown = false;
}
if(rightDown) {
middleDown = true;
shiftDown = !shiftDown;
@ -703,6 +710,8 @@ bool GraphicsWindow::ConstrainPointByHovered(hEntity pt) {
}
void GraphicsWindow::MouseLeftDown(double mx, double my) {
orig.mouseDown = true;
if(GraphicsEditControlIsVisible()) return;
HideTextEditControl();
@ -974,6 +983,8 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
}
void GraphicsWindow::MouseLeftUp(double mx, double my) {
orig.mouseDown = false;
switch(pending.operation) {
case DRAGGING_POINTS:
case DRAGGING_CONSTRAINT:

View File

@ -669,11 +669,20 @@ public:
VectorFileWriter *out);
static void MenuAnalyze(int id);
// Additional display stuff
struct {
SContour path;
hEntity point;
} traced;
SEdgeList nakedEdges;
struct {
BYTE *fromFile;
int w, h;
int rw, rh;
double scale; // pixels per mm
Vector origin;
} bgImage;
void MarkGroupDirty(hGroup hg);
void MarkGroupDirtyByEntity(hEntity he);

122
style.cpp
View File

@ -1,4 +1,5 @@
#include "solvespace.h"
#include <png.h>
#define clamp01(x) (max(0, min(1, (x))))
@ -108,6 +109,8 @@ void Style::LoadFactoryDefaults(void) {
s->name.strcpy(CnfPrefixToName(d->cnfPrefix));
}
SS.backgroundColor = RGB(0, 0, 0);
if(SS.bgImage.fromFile) MemFree(SS.bgImage.fromFile);
SS.bgImage.fromFile = NULL;
}
void Style::FreezeDefaultStyles(void) {
@ -327,6 +330,87 @@ void TextWindow::ScreenChangeBackgroundColor(int link, DWORD v) {
SS.TW.edit.meaning = EDIT_BACKGROUND_COLOR;
}
static int RoundUpToPowerOfTwo(int v)
{
int i;
for(i = 0; i < 31; i++) {
int vt = (1 << i);
if(vt >= v) {
return vt;
}
}
return 0;
}
void TextWindow::ScreenBackgroundImage(int link, DWORD v) {
if(SS.bgImage.fromFile) MemFree(SS.bgImage.fromFile);
SS.bgImage.fromFile = NULL;
if(link == 'l') {
FILE *f = NULL;
png_struct *png_ptr = NULL;
png_info *info_ptr = NULL;
char importFile[MAX_PATH] = "";
if(!GetOpenFile(importFile, PNG_EXT, PNG_PATTERN)) goto err;
f = fopen(importFile, "rb");
if(!f) goto err;
BYTE header[8];
fread(header, 1, 8, f);
if(png_sig_cmp(header, 0, 8)) goto err;
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
NULL, NULL, NULL);
if(!png_ptr) goto err;
info_ptr = png_create_info_struct(png_ptr);
if(!info_ptr) goto err;
if(setjmp(png_jmpbuf(png_ptr))) goto err;
png_init_io(png_ptr, f);
png_set_sig_bytes(png_ptr, 8);
png_read_png(png_ptr, info_ptr,
PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_ALPHA, NULL);
int w = info_ptr->width,
h = info_ptr->height;
BYTE **rows = png_get_rows(png_ptr, info_ptr);
// Round to next-highest powers of two, since the textures require
// that. And round up to 4, to guarantee DWORD alignment.
int rw = max(4, RoundUpToPowerOfTwo(w)),
rh = max(4, RoundUpToPowerOfTwo(h));
SS.bgImage.fromFile = (BYTE *)MemAlloc(rw*rh*3);
for(int i = 0; i < h; i++) {
memcpy(SS.bgImage.fromFile + ((h - 1) - i)*(rw*3), rows[i], w*3);
}
SS.bgImage.w = w;
SS.bgImage.h = h;
SS.bgImage.rw = rw;
SS.bgImage.rh = rh;
SS.bgImage.scale = SS.GW.scale;
SS.bgImage.origin = SS.GW.offset.ScaledBy(-1);
err:
if(png_ptr) png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
if(f) fclose(f);
}
SS.later.showTW = true;
}
void TextWindow::ScreenChangeBackgroundImageScale(int link, DWORD v) {
char str[300];
sprintf(str, "%.3f",
(SS.viewUnits == SolveSpace::UNIT_MM) ? SS.bgImage.scale :
SS.bgImage.scale * 25.4);
SS.TW.edit.meaning = EDIT_BACKGROUND_IMG_SCALE;
ShowTextEditControl(v, 10, str);
}
void TextWindow::ShowListOfStyles(void) {
Printf(true, "%Ft color style-name");
@ -354,6 +438,28 @@ void TextWindow::ShowListOfStyles(void) {
REDf(rgb), GREENf(rgb), BLUEf(rgb),
top[rows-1] + 2, &ScreenChangeBackgroundColor);
Printf(false, "");
Printf(false, "%Ft background bitmap image%E");
if(SS.bgImage.fromFile) {
Printf(false, "%Ba %Ftwidth:%E %dpx %Ftheight:%E %dpx",
SS.bgImage.w, SS.bgImage.h);
if(SS.viewUnits == SolveSpace::UNIT_MM) {
Printf(false, " %Ftscale:%E %# px/mm %Fl%Ll%f%D[change]%E",
SS.bgImage.scale,
&ScreenChangeBackgroundImageScale, top[rows-1] + 2);
} else {
Printf(false, " %Ftscale:%E %# px/inch %Fl%Ll%f%D[change]%E",
SS.bgImage.scale*25.4,
&ScreenChangeBackgroundImageScale, top[rows-1] + 2);
}
Printf(false, "%Ba %Fl%Lc%fclear background image%E",
&ScreenBackgroundImage);
} else {
Printf(false, "%Ba none - %Fl%Ll%fload background image%E",
&ScreenBackgroundImage);
Printf(false, " (bottom left will be center of view)");
}
Printf(false, "");
Printf(false, " %Fl%Ll%fload factory defaults%E",
&ScreenLoadFactoryDefaultStyles);
@ -575,6 +681,22 @@ bool TextWindow::EditControlDoneForStyles(char *str) {
}
break;
case EDIT_BACKGROUND_IMG_SCALE: {
Expr *e = Expr::From(str);
if(e) {
double ev = e->Eval();
if(ev < 0.001 || isnan(ev)) {
Error("Scale must not be zero or negative!");
} else {
SS.bgImage.scale =
(SS.viewUnits == SolveSpace::UNIT_MM) ? ev :
ev / 25.4;
}
} else {
Error("Not a valid number or expression: '%s'", str);
}
break;
}
default: return false;
}
return true;

4
ui.h
View File

@ -101,6 +101,7 @@ public:
static const int EDIT_STYLE_FILL_COLOR = 54;
static const int EDIT_STYLE_NAME = 55;
static const int EDIT_BACKGROUND_COLOR = 56;
static const int EDIT_BACKGROUND_IMG_SCALE = 57;
struct {
int meaning;
int i;
@ -160,6 +161,7 @@ public:
static void ScreenCreateCustomStyle(int link, DWORD v);
static void ScreenLoadFactoryDefaultStyles(int link, DWORD v);
static void ScreenAssignSelectionToStyle(int link, DWORD v);
static void ScreenBackgroundImage(int link, DWORD v);
static void ScreenShowConfiguration(int link, DWORD v);
static void ScreenGoToWebsite(int link, DWORD v);
@ -195,6 +197,7 @@ public:
static void ScreenChangeStyleTextAngle(int link, DWORD v);
static void ScreenChangeStyleColor(int link, DWORD v);
static void ScreenChangeBackgroundColor(int link, DWORD v);
static void ScreenChangeBackgroundImageScale(int link, DWORD v);
bool EditControlDoneForStyles(char *s);
bool EditControlDoneForConfiguration(char *s);
@ -322,6 +325,7 @@ public:
Vector projUp;
double scale;
struct {
bool mouseDown;
Vector offset;
Vector projRight;
Vector projUp;

View File

@ -1,6 +1,5 @@
copy and paste
background image
associative entities from solid model, as a special group
n*log(n) intersection finding