From c24efe43a1276ce924b6163144b5bbc3e070449a Mon Sep 17 00:00:00 2001 From: Jiri Pittner Date: Sat, 8 Apr 2023 17:31:06 +0200 Subject: [PATCH] perspective projection in vecmat3 and tX test program --- .gitignore | 1 + Makefile.am | 5 +- mat.h | 2 +- tX.cc | 355 ++++++++++++++++++++++++++++++++++++++++++++++++++++ vec.cc | 6 - vec.h | 11 ++ vecmat3.cc | 11 ++ vecmat3.h | 3 + 8 files changed, 386 insertions(+), 8 deletions(-) create mode 100644 tX.cc diff --git a/.gitignore b/.gitignore index 384e8e1..09e61b9 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ config.log libla.la t test +tX *.tar.bz2 .*.swp # CVS default ignores end diff --git a/Makefile.am b/Makefile.am index 705ca63..76e99b7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,9 +1,10 @@ lib_LTLIBRARIES = libla.la include_HEADERS = simple.h vecmat3.h quaternion.h fortran.h cuda_la.h auxstorage.h davidson.h laerror.h mat.h qsort.h vec.h bisection.h diis.h la.h noncblas.h smat.h bitvector.h fourindex.h la_traits.h nonclass.h sparsemat.h sparsesmat.h csrmat.h conjgrad.h gmres.h matexp.h permutation.h polynomial.h contfrac.h libla_la_SOURCES = simple.cc quaternion.cc vecmat3.cc vec.cc mat.cc smat.cc sparsemat.cc sparsesmat.cc csrmat.cc laerror.cc noncblas.cc bitvector.cc strassen.cc nonclass.cc cuda_la.cc fourindex.cc permutation.cc polynomial.cc contfrac.cc -check_PROGRAMS = t test +check_PROGRAMS = t test tX t_SOURCES = t.cc t2.cc test_SOURCES = test.cc +tX_SOURCES = tX.cc LDADD = .libs/libla.a ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = LICENSE doxygen.cfg aminclude.am acinclude.m4 footer.html @@ -31,4 +32,6 @@ AM_LDFLAGS += $(ATLASLIB) AM_LDFLAGS += $(MKLLIB) AM_LDFLAGS += $(CUDALIBS) +tX_LDFLAGS = $(AM_LDFLAGS) -lX11 -lm + include $(top_srcdir)/aminclude.am diff --git a/mat.h b/mat.h index 56dd33b..5a5a968 100644 --- a/mat.h +++ b/mat.h @@ -497,7 +497,7 @@ NRMat::NRMat(const T &a, const int n, const int m, const GPUID loc) : nn(n), /***************************************************************************//** - * inline constructor creating vector from an array + * inline constructor creating matrix from an array ******************************************************************************/ diff --git a/tX.cc b/tX.cc new file mode 100644 index 0000000..258fc03 --- /dev/null +++ b/tX.cc @@ -0,0 +1,355 @@ +/* + LA: linear algebra C++ interface library graphical test program + Copyright (C) 2022 Jiri Pittner or + + 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 3 of the License, or + (at your option) any later version. + + This program 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 program. If not, see . +*/ + + +#include +#include +#include +#include +#include + +#include "la.h" +#include "vecmat3.h" +#include "quaternion.h" +#include "permutation.h" +#include "polynomial.h" +#include "contfrac.h" +#include "simple.h" + + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace LA_Vecmat3; +using namespace LA_Quaternion; +using namespace LA_Simple; +using namespace LA; + + + +/* +* function: create_simple_window. Creates a window with a white background +* +in the given size. +* input: +display, size of the window (in pixels), and location of the window +* +(in pixels). +* output: +the window's ID. +* notes: +window is created with a black border, 2 pixels wide. +* +the window is automatically mapped after its creation. +*/ + + +Window create_simple_window(Display* display, int width, int height, int x, int y) +{ +int screen_num = DefaultScreen(display); +int win_border_width = 2; +Window win; +/* create a simple window, as a direct child of the screen's */ +/* root window. Use the screen's black and white colors as +*/ +/* the foreground and background colors of the window, +*/ +/* respectively. Place the new window's top-left corner at +*/ +/* the given 'x,y' coordinates. +*/ +win = XCreateSimpleWindow(display, RootWindow(display, screen_num), +x, y, width, height, win_border_width, +BlackPixel(display, screen_num), +WhitePixel(display, screen_num)); +/* make the window actually appear on the screen. */ +XMapWindow(display, win); +/* flush all pending requests to the X server. */ +XFlush(display); +return win; +} + + + +GC create_gc(Display* display, Window win) +{ +GC gc; +/* handle of newly created GC. */ +unsigned long valuemask = 0; +/* which values in 'values' to */ +/* check when creating the GC. */ +XGCValues values; +/* initial values for the GC. +*/ +unsigned int line_width = 1; +/* line width for the GC. +*/ +int line_style = LineSolid; +/* style for lines drawing and */ +int cap_style = CapButt; +/* style of the line's edje and */ +int join_style = JoinBevel; +/* joined lines. +*/ +int screen_num = DefaultScreen(display); +gc = XCreateGC(display, win, valuemask, &values); +if (!gc) { +fprintf(stderr, "error XCreateGC: \n"); +} +/* define the style of lines that will be drawn using this GC. */ +XSetLineAttributes(display, gc, +line_width, line_style, cap_style, join_style); +/* define the fill style for the GC. to be 'solid filling'. */ +XSetFillStyle(display, gc, FillSolid); + + + + +return gc; +} + + +typedef struct { +Vec3 point0; +Vec3 point1; +} LINE; + +template<> +class LA::LA_traits { +public: + static bool is_plaindata() {return true;}; + typedef double normtype; +}; + + + +void plotobject(Display* display, Pixmap pixmap, GC gc, int width,int height, const NRVec &lines, const Mat3 &camera_angle, const Vec3 &camera, const Vec3 &plane_to_camera, double xod,double xdo,double yod,double ydo) +{ +for(int i=0; i lines(lines0); + +Mat3 camera_angle; +double eul[3]={40.*M_PI/180.,40.*M_PI/180.,10.*M_PI/180.}; +euler2rotmat(eul,camera_angle,"xyz"); +Vec3 camera={50,30,40}; +Vec3 plane_to_camera={-20,-20,-20}; + + +XSetForeground(display,gc,mycolor.pixel); +plotobject(display, pixmap, gc, width,height, lines,camera_angle,camera,plane_to_camera,xod,xdo,yod,ydo); + +XClearWindow(display,win); //expose the pixmap +XSetForeground(display, gc, BlackPixel(display, DefaultScreen(display)));//vratit cernou +XFlush(display); XSync(display, False); + +//prepare to receive events +XSelectInput(display, win, KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|Button1MotionMask|PointerMotionMask); +XEvent event; +int ispressed1=0; +int ispressed2=0; +int ispressed3=0; +int x,y,x0,y0; +while(1) //LOOP .... process events + { + XNextEvent(display, &event); + switch (event.type) + { + case KeyPress: + { + char text[16]; + KeySym mykey; + int n=XLookupString(&event.xkey, text,16,&mykey,0); + if(n==1&&text[0]=='q') goto done; + } + break; + case ButtonPress: + if(event.xbutton.button==Button1) ispressed1=1; + if(event.xbutton.button==Button2) ispressed2=1; + if(event.xbutton.button==Button3) ispressed3=1; + break; + case MotionNotify: + x = event.xbutton.x; + y = event.xbutton.y; + if(ispressed1) + { + if(x0>x) eul[0]+=0.01; + if(x0y) eul[1]+=0.01; + if(y0 -NRVec::NRVec(const std::list l) : NRVec(l.size()) -{ -int ii=0; -for(typename std::list::const_iterator i=l.begin(); i!=l.end(); ++i) (*this)[ii++] = *i; -} /***************************************************************************//** diff --git a/vec.h b/vec.h index e525dfb..b3070ed 100644 --- a/vec.h +++ b/vec.h @@ -1945,6 +1945,17 @@ void NRVec::get(int fd, bool dim, bool transp) { } +//constructor from a list +template +NRVec::NRVec(const std::list l) : NRVec(l.size()) +{ +int ii=0; +for(typename std::list::const_iterator i=l.begin(); i!=l.end(); ++i) (*this)[ii++] = *i; +} + + + + }//namespace #endif /* _LA_VEC_H_ */ diff --git a/vecmat3.cc b/vecmat3.cc index 9e4703c..b36f330 100644 --- a/vecmat3.cc +++ b/vecmat3.cc @@ -842,12 +842,23 @@ T Mat3::norm(const T scalar) const return sqrt(sum); } +//cf. https://en.wikipedia.org/wiki/3D_projection +template +void perspective(T *proj_xy, const Vec3 &point, const Mat3 &camera_angle, const Vec3 &camera, const Vec3 &plane_to_camera) +{ +Vec3 d=camera_angle*(point-camera); +T scale = plane_to_camera[2]/d[2]; +for(int i=0; i<2; ++i) proj_xy[i]= scale*d[i] + plane_to_camera[i]; +} + + //force instantization #define INSTANTIZE(T) \ template class Vec3; \ template class Mat3; \ template void euler2rotmat(const T *eul, Mat3 &a, const char *type, bool transpose=0, bool direction=0, bool reverse=0); \ template void rotmat2euler(T *eul, const Mat3 &a, const char *type, bool transpose=0, bool direction=0, bool reverse=0); \ +template void perspective(T *proj_xy, const Vec3 &point, const Mat3 &camera_angle, const Vec3 &camera, const Vec3 &plane_to_camera); \ #ifndef AVOID_STDSTREAM diff --git a/vecmat3.h b/vecmat3.h index a34ca0e..f486022 100644 --- a/vecmat3.h +++ b/vecmat3.h @@ -190,6 +190,9 @@ void euler2rotmat(const T *eul, Mat3 &a, const char *type, bool transpose=0, template void rotmat2euler(T *eul, const Mat3 &a, const char *type, bool transpose=0, bool direction=0, bool reverse=0); +template +void perspective(T *proj_xy, const Vec3 &point, const Mat3 &camera_angle, const Vec3 &camera, const Vec3 &plane_to_camera); + }//namespace #endif /* _VECMAT3_H_ */