Commit 4fc618cc73b43310710cd0282564fbe913e108fe

Authored by Georg Hopp
0 parents

Initial repository layout

  1 +CC=gcc
  2 +CPP=g++
  3 +MAKE=make
  4 +LD=ld
  5 +
  6 +# CFLAGS=-ggdb
  7 +CXXFLAGS=
  8 +
  9 +LDFLAGS_X11=-L/usr/X11R6/lib -lX11 -lXext
  10 +INC_X11=-I/usr/X11R6/include
  11 +
  12 +# LDFLAGS=$(LDFLAGS_X11) -lefence
  13 +LDFLAGS=$(LDFLAGS_X11)
  14 +INC=$(INC_X11)
  15 +
  16 +OBJECTS=gra_app.o dispatcher.o event_source.o rasterize.o
  17 +XWIN_OBJ=xwin/canvas_x11.o xwin/canvas_x11_shm.o xwin/disp_x11.o xwin/xclass.o
  18 +GEOM_OBJ=geometry/vertex.o geometry/polygon.o geometry/polyeder.o
  19 +HELPER_OBJ=
  20 +MATH_OBJ=math/sin_cos.o
  21 +CANVAS_IMP_OBJ=canvas_imps/canvas_imp_rgb.o
  22 +
  23 +OBJ=$(OBJECTS) $(GEOM_OBJ) $(HELPER_OBJ) $(MATH_OBJ) $(XWIN_OBJ)
  24 +OBJ+=$(CANVAS_IMP_OBJ)
  25 +
  26 +%.o: %.cpp
  27 + $(CPP) $(CFLAGS) $(CXXFLAGS) $(INC) -c $*.cpp
  28 +
  29 +.PHONY : all geometry helper math xwin canvas_imps geometry_clean helper_clean math_clean xwin_clean canvas_imps_clean clean
  30 +
  31 +all: engage
  32 +
  33 +engage: geometry helper math xwin canvas_imps $(OBJECTS)
  34 + $(CPP) $(CFLAGS) $(CXXFLAGS) $(INC) $(LDFLAGS) -o $@ $(OBJ)
  35 +
  36 +geometry:
  37 + @cd geometry && $(MAKE)
  38 +
  39 +helper:
  40 + @cd helper && $(MAKE)
  41 +
  42 +math:
  43 + @cd math && $(MAKE)
  44 +
  45 +xwin:
  46 + @cd xwin && $(MAKE)
  47 +
  48 +canvas_imps:
  49 + @cd canvas_imps && $(MAKE)
  50 +
  51 +geometry_clean:
  52 + @cd geometry && $(MAKE) clean
  53 +
  54 +helper_clean:
  55 + @cd helper && $(MAKE) clean
  56 +
  57 +math_clean::
  58 + @cd math && $(MAKE) clean
  59 +
  60 +xwin_clean::
  61 + @cd xwin && $(MAKE) clean
  62 +
  63 +canvas_imps_clean::
  64 + @cd canvas_imps && $(MAKE) clean
  65 +
  66 +clean: geometry_clean helper_clean math_clean xwin_clean canvas_imps_clean
  67 + @rm -f gra_app
  68 + @rm -f *.o
  1 +/**
  2 + * \file callback.h
  3 + *
  4 + * \brief Implementiert callbacks aus Membern und Funktionen.
  5 + *
  6 + * Enthält alle nötigen Klassen, um sowohl aus Klassenmembern
  7 + * als auch aus normalen Funktionen Callbacks zu machen. Das heißt
  8 + * das sowohl die Adresse des Objekts als auch die der Methode/Funktion
  9 + * gespeichert wird und bei bedarf richtig aufgerufen wird. Es lassen sich
  10 + * also Methoden in Arrays oder Listen vorhalten.
  11 + *
  12 + * \author Georg Steffers <georg@steffers.org>
  13 + *
  14 + * \date 04.12.2003
  15 + *
  16 + * \version ..2001 (Georg Steffers): erste implementation
  17 + * \version 2001-2003 (Georg Steffers): diverse Modifikationen
  18 + * \version 04.12.2003 (Georg Steffers): beginn der Dokumentation via doxygen
  19 + */
  20 +
  21 +/*
  22 + * Copyright (C)2003 Georg Steffers
  23 + *
  24 + * This program is free software; you can redistribute it and/or modify
  25 + * it under the terms of the GNU General Public License as published by
  26 + * the Free Software Foundation; either version 2 of the License, or
  27 + * (at your option) any later version.
  28 + *
  29 + * This program is distributed in the hope that it will be useful,
  30 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  31 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  32 + * GNU General Public License for more details.
  33 + *
  34 + * You should have received a copy of the GNU General Public License
  35 + * along with this program; if not, write to the Free Software
  36 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  37 + */
  38 +
  39 +using namespace std;
  40 +
  41 +#include <cstring>
  42 +
  43 +// enthaelt die adressen unserer callbackfunktion bzw. der Klasse und des
  44 +// Members die wir aufrufen moechten....(dies hier ist die Basisklasse
  45 +// diese wird gleich spezifiziert
  46 +class FunctorBase {
  47 + public:
  48 + // dient wohl nur dazu die groesse eines Member-Pointers zu bestimmen.
  49 + typedef void (FunctorBase::*t_MemberFunc)();
  50 +
  51 + // hierdrin wird der Quatsch gespeichert....
  52 + union {
  53 + const void* Callback;
  54 + char CallbackMember[sizeof(t_MemberFunc)];
  55 + };
  56 + void* Class;
  57 +
  58 + // Konstruktoren
  59 +
  60 + // wichtig, wenn ein Object der Klasse FunctorBase oder einer
  61 + // abgeleiteten Klasse kopiert werden soll.
  62 + FunctorBase() : Class(0), Callback(0) {}
  63 +
  64 + // Hiermit wird eine FunctorBase angelegt.
  65 + FunctorBase(const void* _Class, const void* _Callback, size_t Size) {
  66 + if(_Class) { //Mit nem Member initialisiert
  67 + Class=(void*)_Class;
  68 + memcpy(CallbackMember, _Callback, Size);
  69 + }
  70 + else { // Mit ner normalen Funktion initialisiert
  71 + Class=NULL;
  72 + Callback=_Callback;
  73 + }
  74 + }
  75 +};
  76 +
  77 +// dies wird nu ein Functor, der einen Callback aufnehmen kann, der einen
  78 +// beliebiegen Parameter hat und void zurueckgibt.
  79 +template <class P1, class P2>
  80 +class callback : protected FunctorBase {
  81 + // wir machen einen protected Konstruktor fuer die Klasse, damit nur
  82 + // abgeleitete Klassen einen callback erzeugen koennen. Diese mussen dann
  83 + // sicherstellen, das Funktor1 nur mit Methoden oder Funktionen erzeugt
  84 + // wird, die genau einen Parameter akzeptieren und void zurueckliefern.
  85 + // Der Teil RestoreTypeAndCall(_RTAC) initialisiert RestoreTypeAndCall
  86 + // auf _RTAC.
  87 + protected:
  88 + typedef void (*t_RestoreTypeAndCall)(const FunctorBase&, P1, P2);
  89 + callback(t_RestoreTypeAndCall _RTAC, const void *_Class,
  90 + const void *_Callback, size_t _Size) :
  91 + FunctorBase (_Class, _Callback, _Size), RestoreTypeAndCall(_RTAC) {}
  92 +
  93 + private:
  94 + t_RestoreTypeAndCall RestoreTypeAndCall;
  95 +
  96 + public:
  97 + callback() {}
  98 + void operator() (P1 p1, P2 p2) const { // ueber den koennen wir nachher
  99 + // den Callback aufrufen.
  100 + if(Class) // Wir haben nen Member...
  101 + RestoreTypeAndCall(*this, p1, p2);
  102 + else // normale Funktion, koennen wir direkt aufrufen...
  103 + ((void (*)(P1,P2))Callback)(p1, p2);
  104 + }
  105 + const void* getcb(void) { return Callback; }
  106 +
  107 + int is_null(void) {
  108 + if(Class != 0 || Callback != 0)
  109 + return false;
  110 + return true;
  111 + }
  112 +};
  113 +
  114 +// beim speichern der Klasse als void* ist uns der Typ der Klasse und
  115 +// auch das eigentliche Object verloren gegangen.
  116 +// Deshalb kommt hier jetzt ne Klasse, die den Typ kennt und
  117 +// bei bedarf (jedesmal wenn eine Memberfunktion als Callback aufgerufen
  118 +// werden soll) zurueckwandelt.
  119 +// Ein template: Callee ist jede beliebige Klasse und Func jeder Member
  120 +template <class Callee, class Func, class P1, class P2>
  121 +class MemberTranslator : public callback<P1,P2> {
  122 + public:
  123 + MemberTranslator(Callee &Class, const Func &MemberFunction) :
  124 + callback<P1,P2>(RestoreTypeAndCall, &Class, &MemberFunction,
  125 + sizeof(Func)) {}
  126 +
  127 + static void RestoreTypeAndCall(const FunctorBase &ftor, P1 p1, P2 p2) {
  128 + Callee* Who = (Callee*)(ftor.Class);
  129 + Func TheMemberFunction=*(Func*)(void*)(ftor.CallbackMember);
  130 + (Who->*TheMemberFunction)(p1, p2);
  131 + }
  132 +};
  133 +
  134 +// Da der Konstruktor von callback protected ist brauchen wir noch einen
  135 +// Translator um aus normalen Funktionen Callbacks zu machen.
  136 +template <class P1, class P2>
  137 +class FunctionTranslator : public callback<P1,P2> {
  138 + public:
  139 + FunctionTranslator(void *regularFunc) :
  140 + callback<P1,P2>(NULL,NULL,regularFunc,0) {}
  141 +};
  142 +
  143 +// und jetzt noch 2 makeCallback Templates um das erstellen von Callbacks zu
  144 +// erleichtern.
  145 +template <class Callee, class P1, class P2>
  146 +callback<P1, P2> mk_callback(Callee &Class, void (Callee::*Member)(P1, P2)) {
  147 + return MemberTranslator<Callee,void (Callee::*)(P1,P2),P1,P2>(Class,
  148 + Member);
  149 +}
  150 +
  151 +template <class P1, class P2>
  152 +callback<P1, P2> mk_callback(void (*theFunc)(P1, P2)) {
  153 + return FunctionTranslator<P1, P2>((void*)theFunc);
  154 +}
  1 +/**
  2 + * \file canvas.h
  3 + *
  4 + * \brief Ein canvas ist etwas worauf gezeichnet werden kann.
  5 + *
  6 + * <p>Diese beschreibt einen Speicherbereich in dem gezeichnet werden kann
  7 + * und Methoden zum "blitten" also dem darstellen dieses Speicherbereichs
  8 + * auf dem Bildschirm. Außerdem werden Funktionen zur Farbverwaltung zur
  9 + * verf&uuml;gung gestellt.</p>
  10 + * <p>canvas ist von event-source abgeleitet, da es events erzeugen kann
  11 + * wie z.B. ein redraw-request u.&auml;.</p>
  12 + *
  13 + * \author Georg Steffers <georg@steffers.org> [gs]
  14 + *
  15 + * \date 04.12.2003
  16 + *
  17 + * \version ..2002 [gs]: erste funktionierende Implementation
  18 + * \version 04.12.2003 [gs]: beginn der Dokumentation via doxygen
  19 + * \version 19.12.2003 [gs]: draw_text hinzugefügt, das ist hier eigentlich
  20 + * nicht ganz richtig, aber damit ich nicht meinen
  21 + * eigenen Font-Renderer schreiben muss um debug
  22 + * Ausgaben zu machen und daf&uuml;e die
  23 + * X11-Funktionen nutzen kann, ist der hier.
  24 + */
  25 +
  26 +/*
  27 + * Copyright (C)2003 Georg Steffers
  28 + *
  29 + * This program is free software; you can redistribute it and/or modify
  30 + * it under the terms of the GNU General Public License as published by
  31 + * the Free Software Foundation; either version 2 of the License, or
  32 + * (at your option) any later version.
  33 + *
  34 + * This program is distributed in the hope that it will be useful,
  35 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  36 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  37 + * GNU General Public License for more details.
  38 + *
  39 + * You should have received a copy of the GNU General Public License
  40 + * along with this program; if not, write to the Free Software
  41 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  42 + */
  43 +
  44 +#ifndef __canvas_h__
  45 +#define __canvas_h__
  46 +
  47 +#include "canvas_imps/canvas_imp.h"
  48 +#include "event_source.h"
  49 +#include "rasterize.h"
  50 +#include <cstdio>
  51 +
  52 +typedef enum blit_status {NO_BLIT, BLIT, DRAW};
  53 +
  54 +class canvas : public event_source {
  55 + protected:
  56 + unsigned x_size, y_size;
  57 + canvas_imp* sinfo;
  58 +
  59 + blit_status blit;
  60 + unsigned long draw_color;
  61 +
  62 + public:
  63 + virtual void draw_text(int x, int y, char* text, int length) = 0;
  64 + canvas(unsigned xs, unsigned ys) : event_source() {
  65 + x_size=xs;
  66 + y_size=ys;
  67 +
  68 + sinfo=NULL;
  69 + blit=NO_BLIT;
  70 + }
  71 + virtual ~canvas() {
  72 + close_screen();
  73 + }
  74 +
  75 + virtual rasterizer* create_rasterizer(void) = 0;
  76 + virtual void refresh_palette(void) {};
  77 + virtual void open_screen(void)=0;
  78 + virtual void close_screen(void) {};
  79 + virtual void blit_screen(void)=0;
  80 + blit_status& blitting(void) { return blit; }
  81 + unsigned long get_color(unsigned red, unsigned green, unsigned blue) {
  82 + return sinfo->ext_to_native(red, green, blue);
  83 + }
  84 + void set_color(unsigned long col) { draw_color=col; }
  85 + void set_color(unsigned red, unsigned green, unsigned blue) {
  86 + draw_color=sinfo->ext_to_native(red, green, blue);
  87 + }
  88 + void light_native(unsigned long* col, unsigned intens) {
  89 + sinfo->light_native(col, intens);
  90 + }
  91 +
  92 + char bpp(void) { return sinfo->bytes_per_pixel; }
  93 +
  94 + virtual unsigned get_x_size(void) const { return x_size; }
  95 + virtual unsigned get_y_size(void) const { return y_size; }
  96 +};
  97 +
  98 +class canvas_factory {
  99 + public:
  100 + virtual canvas* create(unsigned xs, unsigned ys) const=0;
  101 +};
  102 +
  103 +#endif // __canvas_h__
  1 +CC=gcc
  2 +CPP=g++
  3 +#CFLAGS=-ggdb
  4 +CXXFLAGS=
  5 +MAKE=make
  6 +
  7 +OBJECTS=canvas_imp_rgb.o
  8 +
  9 +%.o: %.cpp
  10 + $(CPP) $(CFLAGS) $(CXXFLAGS) -c $*.cpp
  11 +
  12 +.PHONY : all clean
  13 +
  14 +all: $(OBJECTS)
  15 +
  16 +clean:
  17 + @rm -f *.o
  1 +/**
  2 + * \file canvas_imp.h
  3 + *
  4 + * \brief ein Prototyp einer Canvas Implementation
  5 + *
  6 + * Die Canvas Implementation dient Haupts&auml;chlich dazu color,
  7 + * light und fogtables passend zum canvas zur verf&uuml;gung zu stellen.
  8 + * Es werden auch Methoden bereit gestellt, über die man externe
  9 + * Farbdefinitionen (z.B. f&uuml;r jeweils rot, gr&uuml;n und blau
  10 + * Werte zwischen 0 und 255) in das von dem canvas benutzte Farbschema
  11 + * zu convertieren.
  12 + *
  13 + * \author Georg Steffers <georg@steffers.org> [gs]
  14 + *
  15 + * \date 04.12.2003
  16 + *
  17 + * \version ..2002 [gs]: erste funktionierende Implementation
  18 + * \version 22.12.2003 [gs]: <ul><li>
  19 + * beginn der Dokumentation via doxygen
  20 + * </li><li>
  21 + * Light und Fogtables hinzugef&uuml;gt
  22 + * </li></ul>
  23 + */
  24 +
  25 +/*
  26 + * Copyright (C)2003 Georg Steffers
  27 + *
  28 + * This program is free software; you can redistribute it and/or modify
  29 + * it under the terms of the GNU General Public License as published by
  30 + * the Free Software Foundation; either version 2 of the License, or
  31 + * (at your option) any later version.
  32 + *
  33 + * This program is distributed in the hope that it will be useful,
  34 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  35 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  36 + * GNU General Public License for more details.
  37 + *
  38 + * You should have received a copy of the GNU General Public License
  39 + * along with this program; if not, write to the Free Software
  40 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  41 + */
  42 +
  43 +#ifndef __canvas_imp_h__
  44 +#define __canvas_imp_h__
  45 +
  46 +#define MAX_LIGHT_LEVELS 255
  47 +#define NUM_LIGHT_LEVELS (MAX_LIGHT_LEVELS+1)
  48 +
  49 +#define MAX_FOG_LEVELS 255
  50 +#define NUM_FOG_LEVELS (MAX_FOG_LEVELS + 1)
  51 +
  52 +class canvas;
  53 +class rasterizer;
  54 +
  55 +class canvas_imp {
  56 + friend class canvas;
  57 + friend class rasterizer;
  58 +
  59 + protected:
  60 + unsigned ext_max_red;
  61 + unsigned ext_max_green;
  62 + unsigned ext_max_blue;
  63 +
  64 + virtual void compute_light_table(void)=0;
  65 + virtual void compute_fog_table(void)=0;
  66 +
  67 + public:
  68 + virtual unsigned long ext_to_native(unsigned red,
  69 + unsigned green,
  70 + unsigned blue)=0;
  71 + virtual ~canvas_imp() {};
  72 +
  73 + // virtual void light_to_native(unsigned char* pcolor,
  74 + // int intensity)=0;
  75 + // virtual void fog_to_native(unsigned char* pcolor,
  76 + // int intensity)=0;
  77 +
  78 + virtual void set_color(unsigned long col) {};
  79 +
  80 + virtual void light_native(unsigned long* col, unsigned intense) = 0;
  81 +
  82 + unsigned char* p_screenbuf;
  83 + char bytes_per_pixel;
  84 +};
  85 +
  86 +#endif // __canvas_imp_h__
  1 +#include "canvas_imp_rgb.h"
  2 +#include <cstdio>
  3 +
  4 +void canvas_imp_rgb::compute_color_resolution(void) {
  5 + for(unsigned rgb=red; rgb<=blue; rgb++) {
  6 + unsigned mask_tmp=col_mask[rgb];
  7 +
  8 + for(col_shift[rgb]=0; (mask_tmp & 0x01) == 0; col_shift[rgb]++)
  9 + mask_tmp>>=1;
  10 + for(col_max[rgb]=1; mask_tmp & 0x01 == 1; col_max[rgb]*=2)
  11 + mask_tmp>>=1;
  12 + col_max[rgb]--;
  13 + }
  14 +}
  15 +
  16 +void canvas_imp_rgb::compute_light_table(void) {
  17 + for(unsigned rgb=red; rgb<=blue; rgb++)
  18 + for(unsigned c=0; c<=col_max[rgb]; c++)
  19 + for(unsigned i=0; i<NUM_LIGHT_LEVELS; i++)
  20 + light_table[rgb][c*NUM_LIGHT_LEVELS+i]=c*i/MAX_LIGHT_LEVELS;
  21 +}
  22 +
  23 +void canvas_imp_rgb::compute_fog_table(void) {
  24 + for(unsigned rgb=red; rgb<=blue; rgb++)
  25 + for(unsigned c=0; c<=col_max[rgb]; c++)
  26 + for(unsigned i=0; i<NUM_FOG_LEVELS; i++)
  27 + fog_table[rgb][c*NUM_FOG_LEVELS+i]=
  28 + c+(unsigned)(((float)i/MAX_FOG_LEVELS)*(col_max[rgb]-c));
  29 +}
  30 +
  31 +canvas_imp_rgb::canvas_imp_rgb(unsigned long red_mask,
  32 + unsigned long green_mask,
  33 + unsigned long blue_mask,
  34 + char bytes_per_pixel,
  35 + char bytes_per_rgb) {
  36 + this->col_mask[red]=red_mask;
  37 + this->col_mask[green]=green_mask;
  38 + this->col_mask[blue]=blue_mask;
  39 +
  40 + this->bytes_per_pixel=bytes_per_pixel;
  41 + this->bytes_per_rgb=bytes_per_rgb;
  42 +
  43 + ext_max_red=255;
  44 + ext_max_green=255;
  45 + ext_max_blue=255;
  46 +
  47 + compute_color_resolution();
  48 +
  49 + light_table[red]=new unsigned[(col_max[red]+1)*NUM_LIGHT_LEVELS];
  50 + light_table[green]=new unsigned[(col_max[green]+1)*NUM_LIGHT_LEVELS];
  51 + light_table[blue]=new unsigned[(col_max[blue]+1)*NUM_LIGHT_LEVELS];
  52 + fog_table[red]=new unsigned[(col_max[red]+1)*NUM_FOG_LEVELS];
  53 + fog_table[green]=new unsigned[(col_max[green]+1)*NUM_FOG_LEVELS];
  54 + fog_table[blue]=new unsigned[(col_max[blue]+1)*NUM_FOG_LEVELS];
  55 +
  56 + compute_light_table();
  57 + compute_fog_table();
  58 +}
  59 +
  60 +unsigned long canvas_imp_rgb::ext_to_native(unsigned red,
  61 + unsigned green,
  62 + unsigned blue) {
  63 + unsigned long red_rescaled=red * col_max[this->red] / ext_max_red;
  64 + unsigned long green_rescaled=green * col_max[this->green] / ext_max_green;
  65 + unsigned long blue_rescaled=blue * col_max[this->blue] / ext_max_blue;
  66 +
  67 + return (red_rescaled << col_shift[this->red]) |
  68 + (green_rescaled << col_shift[this->green]) |
  69 + (blue_rescaled << col_shift[this->blue]);
  70 +}
  71 +
  72 +void canvas_imp_rgb::light_native(unsigned long* col, unsigned intense) {
  73 + unsigned char* c2=(unsigned char*)col;
  74 +
  75 + unsigned long color=0;
  76 + unsigned long color_shift=0;
  77 +
  78 + for(register int p=0; p<bytes_per_rgb; p++) {
  79 + color += (*c2++) << color_shift;
  80 + color_shift += 8; // 8=BITS_PER_BYTE
  81 + }
  82 +
  83 + // mögliche restliche bytes zwischen bytes_per_rgb und
  84 + // bytes_per_pixel überspringen (warum muss ich nochmal
  85 + // rausfinden.
  86 + for(register int p=bytes_per_rgb; p<bytes_per_pixel; p++)
  87 + c2++;
  88 +
  89 + unsigned long r=(color&col_mask[red]) >> col_shift[red];
  90 + unsigned long g=(color&col_mask[green]) >> col_shift[green];
  91 + unsigned long b=(color&col_mask[blue]) >> col_shift[blue];
  92 +
  93 + color=(light_table[red][r*NUM_LIGHT_LEVELS+intense] <<
  94 + col_shift[red]) |
  95 + (light_table[green][g*NUM_LIGHT_LEVELS+intense] <<
  96 + col_shift[green]) |
  97 + (light_table[blue][b*NUM_LIGHT_LEVELS+intense] <<
  98 + col_shift[blue]);
  99 +
  100 + {
  101 + register int i;
  102 + unsigned long mask = 255;
  103 + char shift = 0;
  104 +
  105 + for(c2-=bytes_per_pixel, i=0; i<bytes_per_pixel; i++) {
  106 + *c2 = (color & mask) >> shift;
  107 + c2++;
  108 + mask <<= 8;
  109 + shift += 8;
  110 + }
  111 + }
  112 +}
  1 +/**
  2 + * \file canvas_imp_rgb.h
  3 + *
  4 + * \brief eine Canvas Implementation f&uuml;r ein rgb Canvas.
  5 + *
  6 + * \author Georg Steffers <georg@steffers.org> [gs]
  7 + *
  8 + * \date 04.12.2003
  9 + *
  10 + * \version ..2002 [gs]: erste funktionierende Implementation
  11 + * \version 22.12.2003 [gs]: <ul><li>
  12 + * beginn der Dokumentation via doxygen
  13 + * </li><li>
  14 + * Light und Fogtables hinzugef&uuml;gt
  15 + * eine Methode f&uuml;r perPixel Shading
  16 + * eingebaut, (soll heissen ein gesetztes
  17 + * Pixel kann nachtr&aum;glich noch
  18 + * geshaded werden.
  19 + * </li></ul>
  20 + */
  21 +
  22 +/*
  23 + * Copyright (C)2003 Georg Steffers
  24 + *
  25 + * This program is free software; you can redistribute it and/or modify
  26 + * it under the terms of the GNU General Public License as published by
  27 + * the Free Software Foundation; either version 2 of the License, or
  28 + * (at your option) any later version.
  29 + *
  30 + * This program is distributed in the hope that it will be useful,
  31 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  32 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  33 + * GNU General Public License for more details.
  34 + *
  35 + * You should have received a copy of the GNU General Public License
  36 + * along with this program; if not, write to the Free Software
  37 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  38 + */
  39 +
  40 +#ifndef __canvas_imp_rgb_h__
  41 +#define __canvas_imp_rgb_h__
  42 +
  43 +#include "canvas_imp.h"
  44 +
  45 +class canvas_imp_rgb : public canvas_imp {
  46 + private:
  47 + enum rgb_e_t { red=0, green, blue };
  48 +
  49 + unsigned* light_table[3];
  50 + unsigned* fog_table[3];
  51 +
  52 + char bytes_per_rgb;
  53 +
  54 + unsigned long col_mask[3];
  55 + unsigned col_shift[3];
  56 + unsigned col_max[3];
  57 +
  58 + void compute_color_resolution(void);
  59 + void compute_light_table(void);
  60 + void compute_fog_table(void);
  61 +
  62 + public:
  63 + canvas_imp_rgb(unsigned long, unsigned long, unsigned long,
  64 + char, char);
  65 + virtual ~canvas_imp_rgb() {}
  66 +
  67 + unsigned long ext_to_native(unsigned, unsigned, unsigned);
  68 +
  69 + void light_native(unsigned long* col, unsigned intense);
  70 +
  71 + // und wieder fehlt alles für light und fog.
  72 +};
  73 +
  74 +#endif // __canvas_imp_rgb_h__
This diff could not be displayed because it is too large.
  1 +/**
  2 + * \file dispatcher.cpp
  3 + *
  4 + * \brief Stadardimplementation der virtuellen Member des Dispatcher-Managers.
  5 + *
  6 + * F&uuml;r eine detailierte Beschreibung von Dispatcher und
  7 + * Dispatcher-Manager schauen Sie bitte unter \ref dispatcher.h
  8 + *
  9 + * \author Georg Steffers <georg@steffers.org>
  10 + *
  11 + * \date 04.12.2003
  12 + *
  13 + * \version ..2002 (Georg Steffers): erste funktionierende Implementation
  14 + * \version 04.12.2003 (Georg Steffers): beginn der Dokumentation via doxygen
  15 + */
  16 +
  17 +/*
  18 + * Copyright (C)2003 Georg Steffers
  19 + *
  20 + * This program is free software; you can redistribute it and/or modify
  21 + * it under the terms of the GNU General Public License as published by
  22 + * the Free Software Foundation; either version 2 of the License, or
  23 + * (at your option) any later version.
  24 + *
  25 + * This program is distributed in the hope that it will be useful,
  26 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  27 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  28 + * GNU General Public License for more details.
  29 + *
  30 + * You should have received a copy of the GNU General Public License
  31 + * along with this program; if not, write to the Free Software
  32 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  33 + */
  34 +
  35 +using namespace std;
  36 +
  37 +#include <cstring>
  38 +
  39 +#include "dispatcher.h"
  40 +
  41 +disp_manager::disp_manager(dispatcher* d) {
  42 + disp_count=0;
  43 + disp=NULL;
  44 +
  45 + if(d!=NULL) {
  46 + disp=new dispatcher*[1];
  47 + disp[0]=d;
  48 + disp_count++;
  49 + }
  50 +}
  51 +
  52 +dispatcher*& disp_manager::operator[](unsigned index) {
  53 + if(index+1>disp_count) {
  54 + dispatcher** disp_tmp=new dispatcher*[index+1];
  55 + memcpy(disp_tmp, disp, sizeof(dispatcher*)*disp_count);
  56 +
  57 + delete [] disp;
  58 + disp=disp_tmp;
  59 + disp_count=index+1;
  60 + }
  61 +
  62 + return disp[index];
  63 +}
  64 +
  65 +void disp_manager::start(void) {
  66 + run=true;
  67 +
  68 + while(run)
  69 + do_once();
  70 +}
  71 +
  72 +void disp_manager::do_once(void) {
  73 + for(int i=0; i<disp_count; i++)
  74 + if(disp[i]->e_src)
  75 + disp[i]->go();
  76 +}
  1 +/**
  2 + * \file dispatcher.h
  3 + *
  4 + * \brief Deklaration eines abstrakten Event-Dispatchers und des
  5 + * Dispatcher-Managers.
  6 + *
  7 + * <p>In einem Dispatcher werden callbacks eingetragen, die bei bestimmten
  8 + * Events aufgerufen werden sollen, Der Dispatcher k&uuml;mmert sich dann
  9 + * darum das diese zum richtigen Zeitpunk und f&uuml;r das richtige Event
  10 + * aufgerufen werden. Der Dispatcher wird mit der Event-Quelle initialisiert,
  11 + * die die Events erzeugt. Die hier definierte Dispatcher Klasse ist abstrakt
  12 + * und mu&szlig; noch in einer abgeleiteten Klasse konkretisiert werden. So
  13 + * kann ich diverse Dispatcher erzeugen, die intern unterschiedlich arbeiten,
  14 + * im Moment existiert die X11 implementation eines Dispatches.</p>
  15 + * <p>Im Dispatcher Manager werden die einzelnen Dispatcher registriert. Er
  16 + * sorgt dann dann standartm&auml;&szlig;ig daf&uuml;r, das die einzelnen
  17 + * Dispatcher immer wieder nacheinenader in der Reihenfolge in der sie dem
  18 + * Manager hinzugef&uuml;gt wurden ausgeführt werden und so alle Events immer
  19 + * wieder gecheckt werden. Dieses verhalten kann man aber &auml;ndern indem
  20 + * man einen neuen Manager von diesem ableitet und die virtuellen Methoden
  21 + * entsprechend &uuml;berschreibt.</p>
  22 + *
  23 + * \author Georg Steffers <georg@steffers.org>
  24 + *
  25 + * \date 04.12.2003
  26 + *
  27 + * \version ..2002 (Georg Steffers): erste funktionierende Implementation
  28 + * \version 04.12.2003 (Georg Steffers): beginn der Dokumentation via doxygen
  29 + */
  30 +
  31 +/*
  32 + * Copyright (C)2003 Georg Steffers
  33 + *
  34 + * This program is free software; you can redistribute it and/or modify
  35 + * it under the terms of the GNU General Public License as published by
  36 + * the Free Software Foundation; either version 2 of the License, or
  37 + * (at your option) any later version.
  38 + *
  39 + * This program is distributed in the hope that it will be useful,
  40 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  41 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  42 + * GNU General Public License for more details.
  43 + *
  44 + * You should have received a copy of the GNU General Public License
  45 + * along with this program; if not, write to the Free Software
  46 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  47 + */
  48 +
  49 +#ifndef __dispatcher_h__
  50 +#define __dispatcher_h__
  51 +
  52 +#include "callback.h"
  53 +#include "event_source.h"
  54 +
  55 +class disp_manager;
  56 +class dispatcher {
  57 + friend class disp_manager;
  58 +
  59 + protected:
  60 + callback<event_source*,void*> cb[MaxEvent];
  61 + event_source* e_src;
  62 + int halt_f;
  63 +
  64 + public:
  65 + dispatcher(event_source* es=NULL) {
  66 + e_src=es;
  67 + halt_f=false;
  68 + }
  69 + virtual ~dispatcher() {}
  70 +
  71 + void register_callback(event e, callback<event_source*, void*> _cb) {
  72 + if(e_src)
  73 + cb[e]=_cb;
  74 + }
  75 +
  76 + virtual void go(void)=0;
  77 + virtual void trigger_event(event)=0;
  78 + void halt(void) { halt_f=true; }
  79 + void cont(void) { halt_f=false; }
  80 +};
  81 +
  82 +// Da ich u.U. mehrere Eventquellen in einem Programm habe brauche
  83 +// ich eine Klasse die die verschiedenen Dispatcher-Klassen kontrolliert
  84 +// nacheinander aufruft.
  85 +class disp_manager {
  86 + private:
  87 + dispatcher** disp;
  88 + unsigned disp_count;
  89 + unsigned run;
  90 +
  91 + public:
  92 + disp_manager(dispatcher* = NULL);
  93 + ~disp_manager() {
  94 + delete [] disp;
  95 + }
  96 +
  97 + dispatcher*& operator[](unsigned index);
  98 +
  99 + unsigned count(void) { return disp_count; }
  100 + virtual void start(void);
  101 + virtual void stop(event_source*, void*) {
  102 + run=false;
  103 + }
  104 + virtual void do_once(void);
  105 +};
  106 +
  107 +class dispatcher_factory {
  108 + public:
  109 + virtual dispatcher* create(event_source* es) const=0;
  110 +};
  111 +
  112 +#endif // __dispatcher_h__
  1 +/**
  2 + * \file event_source.cpp
  3 + *
  4 + * \brief definition und initialisierung von max_id
  5 + *
  6 + * F&uuml;r eine detailierte Beschreibung von event_source
  7 + * schauen Sie bitte unter \ref event_source.h
  8 + *
  9 + * \author Georg Steffers <georg@steffers.org>
  10 + *
  11 + * \date 04.12.2003
  12 + *
  13 + * \version ..2002 (Georg Steffers): erste funktionierende Implementation
  14 + * \version 04.12.2003 (Georg Steffers): beginn der Dokumentation via doxygen
  15 + */
  16 +
  17 +/*
  18 + * Copyright (C)2003 Georg Steffers
  19 + *
  20 + * This program is free software; you can redistribute it and/or modify
  21 + * it under the terms of the GNU General Public License as published by
  22 + * the Free Software Foundation; either version 2 of the License, or
  23 + * (at your option) any later version.
  24 + *
  25 + * This program is distributed in the hope that it will be useful,
  26 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  27 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  28 + * GNU General Public License for more details.
  29 + *
  30 + * You should have received a copy of the GNU General Public License
  31 + * along with this program; if not, write to the Free Software
  32 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  33 + */
  34 +
  35 +#include "event_source.h"
  36 +
  37 +unsigned event_source::max_id=0;
  1 +/**
  2 + * \file event_source.h
  3 + *
  4 + * \brief Interface f&uuml;r Events generierende Klassen
  5 + *
  6 + * Alle Klassen die Events erzeugen wollen m&uuml;ssen von diesem
  7 + * Interface abgeleitet werden, damit man einen Dispatcher f&uuml:r Sie
  8 + * erzeugen kann.
  9 + *
  10 + * \author Georg Steffers <georg@steffers.org>
  11 + *
  12 + * \date 04.12.2003
  13 + *
  14 + * \version ..2002 (Georg Steffers): erste funktionierende Implementation
  15 + * \version 04.12.2003 (Georg Steffers): beginn der Dokumentation via doxygen
  16 + */
  17 +
  18 +/*
  19 + * Copyright (C)2003 Georg Steffers
  20 + *
  21 + * This program is free software; you can redistribute it and/or modify
  22 + * it under the terms of the GNU General Public License as published by
  23 + * the Free Software Foundation; either version 2 of the License, or
  24 + * (at your option) any later version.
  25 + *
  26 + * This program is distributed in the hope that it will be useful,
  27 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  28 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  29 + * GNU General Public License for more details.
  30 + *
  31 + * You should have received a copy of the GNU General Public License
  32 + * along with this program; if not, write to the Free Software
  33 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  34 + */
  35 +
  36 +#ifndef __event_source_h__
  37 +#define __event_source_h__
  38 +
  39 +class event_source {
  40 + private:
  41 + static unsigned max_id;
  42 + unsigned id;
  43 +
  44 + public:
  45 + event_source() {
  46 + id=max_id++;
  47 + }
  48 +};
  49 +
  50 +typedef enum event {Key, Update, Draw, Idle, Stop, MaxEvent};
  51 +
  52 +#endif // __event_source_h__
  1 +/**
  2 + * \file factory.h
  3 + *
  4 + * \brief erzeugt auf Anfrage passende Objekte.
  5 + *
  6 + * \author Georg Steffers <georg@steffers.org>
  7 + *
  8 + * \date 04.12.2003
  9 + *
  10 + * \version ..2002 (Georg Steffers): erste funktionierende Implementation
  11 + * \version 04.12.2003 (Georg Steffers): beginn der Dokumentation via doxygen
  12 + */
  13 +
  14 +/*
  15 + * Copyright (C)2003 Georg Steffers
  16 + *
  17 + * This program is free software; you can redistribute it and/or modify
  18 + * it under the terms of the GNU General Public License as published by
  19 + * the Free Software Foundation; either version 2 of the License, or
  20 + * (at your option) any later version.
  21 + *
  22 + * This program is distributed in the hope that it will be useful,
  23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25 + * GNU General Public License for more details.
  26 + *
  27 + * You should have received a copy of the GNU General Public License
  28 + * along with this program; if not, write to the Free Software
  29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  30 + */
  31 +
  32 +#ifndef __factory_h__
  33 +#define __factory_h__
  34 +
  35 +#include "xwin/disp_x11.h"
  36 +#include "xwin/canvas_x11_shm.h"
  37 +#include "xwin/canvas_x11.h"
  38 +#include "canvas_imps/canvas_imp_rgb.h"
  39 +#include "rasterize.h"
  40 +
  41 +class factory_manager {
  42 + public:
  43 + canvas_factory* canvas_f;
  44 + dispatcher_factory* dispatcher_f;
  45 + //rasterizer_factory* rasterizer_f;
  46 +
  47 + factory_manager() : canvas_f(new canvas_x11_shm_factory),
  48 + dispatcher_f(new disp_x11_factory) {}
  49 + virtual ~factory_manager() {
  50 + delete canvas_f;
  51 + delete dispatcher_f;
  52 + };
  53 +};
  54 +
  55 +#endif // __factory_h__
No preview for this file type
No preview for this file type
  1 +CC=gcc
  2 +CPP=g++
  3 +#CFLAGS=-ggdb
  4 +CXXFLAGS=
  5 +MAKE=make
  6 +
  7 +OBJECTS=vertex.o polygon.o polyeder.o
  8 +TEMPLATES=../helper/container.h ../helper/container_tpl.h
  9 +TEMPLATES+=../math/Mmn.h ../math/Mmn_tpl.h ../math/V_K4.h ../math/V_K4_tpl.h
  10 +
  11 +%.o: %.c++ $(TEMPLATES)
  12 + $(CPP) $(CFLAGS) $(CXXFLAGS) -c $*.c++
  13 +
  14 +.PHONY : all clean
  15 +
  16 +all: $(OBJECTS)
  17 +
  18 +clean:
  19 + @rm -f *.o
  1 +/**
  2 + * \file movable.h
  3 + *
  4 + * \brief Definition eines Templates f&uuml;r bewegte Objekte
  5 + *
  6 + * Organisiert, verwaltet und steuert die Bewegung bewegter Objekte.
  7 + *
  8 + * \author Georg Steffers <georg@steffers.org> [gs]
  9 + *
  10 + * \date 19.12.2003
  11 + *
  12 + * \version 19.12.2003 [gs]: erste Implementation aus gra_app gezogen.
  13 + * \version 21.12.2003 [gs]: Bug in rotate_im_axis(double, vertex, vertex)
  14 + * gefixt. Dort wurden immer die Objektkoordinaten
  15 + * auf den Weltursprung verschoben und nicht die
  16 + * Vektorbasis wie es eigentlich sein sollte.
  17 + */
  18 +
  19 +/*
  20 + * Copyright (C)2003 Georg Steffers
  21 + *
  22 + * This program is free software; you can redistribute it and/or modify
  23 + * it under the terms of the GNU General Public License as published by
  24 + * the Free Software Foundation; either version 2 of the License, or
  25 + * (at your option) any later version.
  26 + *
  27 + * This program is distributed in the hope that it will be useful,
  28 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  29 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  30 + * GNU General Public License for more details.
  31 + *
  32 + * You should have received a copy of the GNU General Public License
  33 + * along with this program; if not, write to the Free Software
  34 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  35 + */
  36 +
  37 +#ifndef __movable_h__
  38 +#define __movable_h__
  39 +
  40 +#include "vertex.h"
  41 +#include "../math/Mmn.h"
  42 +
  43 +/**
  44 + * \brief Ein Interface f&uuml;r bewegte Objekte
  45 + *
  46 + * alle Objektklassen, die auch Kind dieses komplett &ouml;ffentlichen
  47 + * Interfaces sind lassen sich dadurch rotieren und bewegen, das man die
  48 + * Rotations- und Bewegungsgeschwindigkeit bez&uuml;glich der lokalen,
  49 + * bzw. der Weltkoordinaten angibt.
  50 + * jeder Aufruf der Methode update aktualisiert dann die Positionen der
  51 + * Vektoren dieses Objekts.
  52 + */
  53 +class movable {
  54 + protected:
  55 + vertex vrp; //!< \brief \<Punkt\> (view reference point)
  56 + //! das Zentrum des Objekts
  57 + vertex vfw_t; //!< \<Punkt\> Spitze von \ref vfw
  58 + vertex vup_t; //!< \<Punkt\> Spitze von \ref vup
  59 + vertex vri_t; //!< \<Punkt\> Spitze von \ref vri
  60 + vertex vfw; //!< \brief \<Vektor\> (vektor forward)
  61 + //! Objektkoordinatensystem z
  62 + vertex vup; //!< \brief \<Vektor\> (vektor up)
  63 + //! Objektkoordinatensystem y
  64 + vertex vri; //!< \brief \<Vektor\> (vektor right)
  65 + //! Objektkoordinatensystem x
  66 +
  67 + Mmn<double> t_mat; //!< Die aktuelle Transformationsmatrize
  68 +
  69 + //! \brief Geschwinidigkeiten
  70 + //! relativ zu Weltkoordinaten
  71 + double speed_x, speed_y, speed_z, rot_speed_x, rot_speed_y, rot_speed_z;
  72 + //! \brief Geschwinidigkeiten
  73 + //! relativ zu Objekt
  74 + double speed_vfw, speed_vri, speed_vup,
  75 + rot_speed_vfw, rot_speed_vri, rot_speed_vup;
  76 +
  77 +
  78 + time_t last_transform; //!<\brief Zeitpunkt der letzten Transformation
  79 + //!
  80 + //! Damit l&auml;&szlig;t sich der genaue
  81 + //! Zeitraum seit der letzten Transformation
  82 + //! berechnen und in alle Transformations
  83 + //! Berechnungen mit einf&uuml;gen, so das
  84 + //! wir wirkliche Echtzeit bekommen.
  85 +
  86 + //! Speed-Falloffs pro Sekunde
  87 + double speed_x_falloff,
  88 + speed_y_falloff,
  89 + speed_z_falloff,
  90 + rot_speed_x_falloff,
  91 + rot_speed_y_falloff,
  92 + rot_speed_z_falloff;
  93 + double speed_vfw_falloff,
  94 + speed_vri_falloff,
  95 + speed_vup_falloff,
  96 + rot_speed_vfw_falloff,
  97 + rot_speed_vri_falloff,
  98 + rot_speed_vup_falloff;
  99 +
  100 + //! \brief Konstruktor
  101 + //!
  102 + //! privater Kontruktor, da man von dem Interface
  103 + //! keinen Eigenen Instanzen bilden k&ouml;nnen soll.
  104 + movable() {
  105 + vrp=vertex(0,0,0,1);
  106 + vfw_t=vertex(0,0,1,1);
  107 + vup_t=vertex(0,1,0,1);
  108 + vri_t=vertex(1,0,0,1);
  109 + vfw=vfw_t-vrp;
  110 + vup=vup_t-vrp;
  111 + vri=vri_t-vrp;
  112 + t_mat=Mmn<double>(4);
  113 + }
  114 +
  115 + public:
  116 + virtual const Mmn<double>& get_t_mat(void) { return t_mat; }
  117 +
  118 + virtual void reset(void) {
  119 + vrp.reset();
  120 + vfw_t.reset();
  121 + vup_t.reset();
  122 + vri_t.reset();
  123 + vfw=vfw_t-vrp;
  124 + vup=vup_t-vrp;
  125 + vri=vri_t-vrp;
  126 +
  127 + t_mat=Mmn<double>(4);
  128 + }
  129 +
  130 + /**
  131 + * \param t_st Transformationsstufe
  132 + */
  133 + virtual void transform(unsigned t_st) {
  134 + vrp.transform(t_mat, t_st);
  135 + vfw_t.transform(t_mat, t_st);
  136 + vup_t.transform(t_mat, t_st);
  137 + vri_t.transform(t_mat, t_st);
  138 + vfw=vfw_t-vrp;
  139 + vup=vup_t-vrp;
  140 + vri=vri_t-vrp;
  141 + }
  142 +
  143 + void print(void) {
  144 + t_mat.print();
  145 + }
  146 +
  147 + const vertex& get_vrp(void) {
  148 + return vrp;
  149 + }
  150 +
  151 + const vertex& get_vfw_t(void) {
  152 + return vfw_t;
  153 + }
  154 +
  155 + const vertex& get_vup_t(void) {
  156 + return vup_t;
  157 + }
  158 +
  159 + const vertex& get_vri_t(void) {
  160 + return vri_t;
  161 + }
  162 +
  163 + const vertex& get_vfw(void) {
  164 + return vfw;
  165 + }
  166 +
  167 + const vertex& get_vup(void) {
  168 + return vup;
  169 + }
  170 +
  171 + const vertex& get_vri(void) {
  172 + return vri;
  173 + }
  174 +
  175 + /**
  176 + * \brief direkte Ver&auml;nderung der Position &uuml;ber eine
  177 + * vorberechnete Matrize.
  178 + * \param trans_mat Eine komplette vorberechnete Transformationsmatrix
  179 + */
  180 + void move_im(const Mmn<double>& trans_mat) {
  181 + t_mat=trans_mat%t_mat;
  182 + }
  183 + /**
  184 + * \brief Verschiebung &uuml;ber (lokale) Objekkoordinaten
  185 + * \param axe Achse entlang der verschoben wird
  186 + * \param step wie weit verschoben wird
  187 + */
  188 + void translate_im_axe(vertex axe, double step) {
  189 + axe=axe.norm()*step;
  190 + t_mat=mat_translate(axe[X], axe[Y], axe[Z])%t_mat;
  191 + }
  192 + /**
  193 + * \brief Verschiebung &uuml;ber (globale) Weltkoordinaten
  194 + * \param x Verschiebung in VRI
  195 + * \param y Verschiebung in VUP
  196 + * \param z Verschiebung in VFW
  197 + */
  198 + void translate_im_global(double x, double y, double z) {
  199 + t_mat=mat_translate(x, y, z)%t_mat;
  200 + }
  201 + /**
  202 + * \brief Drehung &uuml;ber (lokale) Objekkoordinaten vfw
  203 + * \param angle Wieviel Grad soll gedreht werden
  204 + */
  205 + void rotate_im_vfw(double angle) {
  206 + vfw_t.transform(t_mat, 1);
  207 + vrp.transform(t_mat, 1);
  208 +
  209 + rotate_im_axis(angle, vfw_t, vrp);
  210 +
  211 + vfw_t.reset();
  212 + vrp.reset();
  213 + }
  214 + /**
  215 + * \brief Drehung &uuml;ber (lokale) Objekkoordinaten vup
  216 + * \param angle Wieviel Grad soll gedreht werden
  217 + */
  218 + void rotate_im_vup(double angle) {
  219 + vup_t.transform(t_mat, 1);
  220 + vrp.transform(t_mat, 1);
  221 +
  222 + rotate_im_axis(angle, vup_t, vrp);
  223 +
  224 + vup_t.reset();
  225 + vrp.reset();
  226 + }
  227 + /**
  228 + * \brief Drehung &uuml;ber (lokale) Objekkoordinaten vri
  229 + * \param angle Wieviel Grad soll gedreht werden
  230 + */
  231 + void rotate_im_vri(double angle) {
  232 + vri_t.transform(t_mat, 1);
  233 + vrp.transform(t_mat, 1);
  234 +
  235 + rotate_im_axis(angle, vri_t, vrp);
  236 +
  237 + vri_t.reset();
  238 + vrp.reset();
  239 + }
  240 + /**
  241 + * \brief Drehung um X-Achse im Weltkoordinaten-Zentrum
  242 + * \param angle Wieviel Grad soll gedreht werden
  243 + */
  244 + void rotate_im_g_x(double angle) {
  245 + t_mat=mat_rot_x(angle)%t_mat;
  246 + }
  247 + /**
  248 + * \brief Drehung um Y-Achse im Weltkoordinaten-Zentrum
  249 + * \param angle Wieviel Grad soll gedreht werden
  250 + */
  251 + void rotate_im_g_y(double angle) {
  252 + t_mat=mat_rot_y(angle)%t_mat;
  253 + }
  254 + /**
  255 + * \brief Drehung um Z-Achse im Weltkoordinaten-Zentrum
  256 + * \param angle Wieviel Grad soll gedreht werden
  257 + */
  258 + void rotate_im_g_z(double angle) {
  259 + t_mat=mat_rot_z(angle)%t_mat;
  260 + }
  261 + /**
  262 + * \brief Drehung um X-Achse im Objektkoordinaten-Zentrum
  263 + * \param angle Wieviel Grad soll gedreht werden
  264 + */
  265 + void rotate_im_l_x(double angle) {
  266 + Mmn<double> mat_center(4);
  267 + Mmn<double> mat_reset(4);
  268 +
  269 + mat_center.a(0,3)=-t_mat.a(0,3);
  270 + mat_center.a(1,3)=-t_mat.a(1,3);
  271 + mat_center.a(2,3)=-t_mat.a(2,3);
  272 +
  273 + mat_reset.a(0,3)=t_mat.a(0,3);
  274 + mat_reset.a(1,3)=t_mat.a(1,3);
  275 + mat_reset.a(2,3)=t_mat.a(2,3);
  276 +
  277 + t_mat=mat_reset%mat_rot_x(angle)%mat_center%t_mat;
  278 + }
  279 + /**
  280 + * \brief Drehung um Y-Achse im Objektkoordinaten-Zentrum
  281 + * \param angle Wieviel Grad soll gedreht werden
  282 + */
  283 + void rotate_im_l_y(double angle) {
  284 + Mmn<double> mat_center(4);
  285 + Mmn<double> mat_reset(4);
  286 +
  287 + mat_center.a(0,3)=-t_mat.a(0,3);
  288 + mat_center.a(1,3)=-t_mat.a(1,3);
  289 + mat_center.a(2,3)=-t_mat.a(2,3);
  290 +
  291 + mat_reset.a(0,3)=t_mat.a(0,3);
  292 + mat_reset.a(1,3)=t_mat.a(1,3);
  293 + mat_reset.a(2,3)=t_mat.a(2,3);
  294 +
  295 + t_mat=mat_reset%mat_rot_y(angle)%mat_center%t_mat;
  296 + }
  297 + /**
  298 + * \brief Drehung um Z-Achse im Objektkoordinaten-Zentrum
  299 + * \param angle Wieviel Grad soll gedreht werden
  300 + */
  301 + void rotate_im_l_z(double angle) {
  302 + Mmn<double> mat_center(4);
  303 + Mmn<double> mat_reset(4);
  304 +
  305 + mat_center.a(0,3)=-t_mat.a(0,3);
  306 + mat_center.a(1,3)=-t_mat.a(1,3);
  307 + mat_center.a(2,3)=-t_mat.a(2,3);
  308 +
  309 + mat_reset.a(0,3)=t_mat.a(0,3);
  310 + mat_reset.a(1,3)=t_mat.a(1,3);
  311 + mat_reset.a(2,3)=t_mat.a(2,3);
  312 +
  313 + t_mat=mat_reset%mat_rot_z(angle)%mat_center%t_mat;
  314 + }
  315 + /**
  316 + * \brief Drehung um eine beliebige Achse
  317 + * \param angle Wieviel Grad soll gedreht werden
  318 + * \param axe Die Achse um die gedreht werden soll als
  319 + * Ursprungsvektor (also einer der in WC(0,0,0) beginnt)
  320 + */
  321 + void rotate_im_axis(double angle, const vertex& axe) {
  322 + t_mat=mat_rot_axe(angle, axe.get_t())%t_mat;
  323 + }
  324 +
  325 + /**
  326 + * \brief Drehung um Z-Achse im Objektkoordinaten-Zentrum
  327 + * \param angle Wieviel Grad soll gedreht werden
  328 + * \param tip Vertexspitze der Rotationsachse
  329 + * \param base Vertexbasis der Rotationsachse
  330 + */
  331 + void rotate_im_axis(double angle, vertex tip, vertex base) {
  332 + Mmn<double> mat_center(4);
  333 + Mmn<double> mat_reset(4);
  334 +
  335 + mat_center.a(0,3)=-base[X];
  336 + mat_center.a(1,3)=-base[Y];
  337 + mat_center.a(2,3)=-base[Z];
  338 +
  339 + mat_reset.a(0,3)=base[X];
  340 + mat_reset.a(1,3)=base[Y];
  341 + mat_reset.a(2,3)=base[Z];
  342 +
  343 +// if(angle==0 || angle==180) {
  344 +// cout << "------------------------------\n";
  345 +// cout << "Winkel: " << angle << "Grad\n";
  346 +// t_mat.print();
  347 +// }
  348 + t_mat=mat_reset%mat_rot_axe(angle, (tip-base).get_t())%mat_center%t_mat;
  349 +// if(angle==0 || angle==180) {
  350 +// t_mat.print();
  351 +// cout << "------------------------------\n";
  352 +// }
  353 + }
  354 + // sowohl für translatio, als auch für Rotation sollte ich denke
  355 + // ich eigene Methoden für jede Richtung schreiben.!!!
  356 +};
  357 +
  358 +#endif // __movable_h__
  1 +#include "polyeder.h"
  2 +
  3 +polyeder::polyeder(const polygon& p, const vertex_list& vl) :
  4 + container<polygon>(p), vl(vl) {
  5 + for(unsigned i=0; i<count; i++) {
  6 + content[i].set_vertex_list(&this->vl);
  7 + content[i]._init_normal_();
  8 + content[i].set_polyeder(this);
  9 + }
  10 +}
  11 +
  12 +polyeder::polyeder(const polygon* p, unsigned c, const vertex_list& vl) :
  13 + container<polygon>(p, c), vl(vl) {
  14 + for(unsigned i=0; i<count; i++) {
  15 + content[i].set_vertex_list(&this->vl);
  16 + content[i]._init_normal_();
  17 + content[i].set_polyeder(this);
  18 + }
  19 +}
  20 +
  21 +polyeder::polyeder(const polyeder& p) :
  22 + container<polygon>(p), vl(p.vl) {
  23 + for(unsigned i=0; i<count; i++) {
  24 + content[i].set_vertex_list(&this->vl);
  25 + content[i].set_polyeder(this);
  26 + }
  27 +}
  28 +
  29 +const polyeder& polyeder::operator=(const polyeder& p) {
  30 + if(this==&p)
  31 + return *this;
  32 +
  33 + container<polygon>::operator=(p);
  34 + vl=p.vl;
  35 +
  36 + for(unsigned i=0; i<count; i++) {
  37 + content[i].set_vertex_list(&vl);
  38 + content[i].set_polyeder(this);
  39 + }
  40 +
  41 + return *this;
  42 +}
  43 +
  44 +void polyeder::transform(const Mmn<double>& tm, int p) {
  45 + for(unsigned i=0; i<count; i++) {
  46 + content[i].transform(tm, p);
  47 + }
  48 +}
  49 +
  50 +void polyeder::transform_normals(const Mmn<double>& tm, int p) {
  51 + for(unsigned i=0; i<count; i++) {
  52 + content[i].transform_normal(tm, p);
  53 + }
  54 +}
  55 +
  56 +void polyeder::reset(void) {
  57 + vl.reset();
  58 +
  59 + for(unsigned i=0; i<count; i++) {
  60 + content[i].reset();
  61 + }
  62 +}
  63 +
  64 +void polyeder::trans_poly(unsigned i, const Mmn<double>& tm, int p) {
  65 + content[i].transform(tm, p);
  66 +}
  67 +
  68 +void polyeder::project_2d(double lcx, double sw, double sh,
  69 + double ph_ar, double sy, int p) {
  70 + for(unsigned i=0; i<count; i++) {
  71 + content[i].project_2d(lcx, sw, sh, ph_ar, sy, p+1);
  72 + }
  73 + for(unsigned i=0; i<vl.card(); i++) {
  74 + vl[i].set_trans_stage(p);
  75 + }
  76 +}
  1 +/**
  2 + * \file polyeder.h
  3 + *
  4 + * \brief Ein Polyeder (eine gruppe von Polygonen)
  5 + *
  6 + * Ein Polyeder organisier die Vertexliste und Anordnung von Polygonen
  7 + * die zu einem K&ouml;rper geh&ouml;ren.
  8 + *
  9 + * \author Georg Steffers <georg@steffers.org> [gs]
  10 + *
  11 + * \date 19.12.2003
  12 + *
  13 + * \version ..2002 [gs]: erste Implementation
  14 + * \version 19.12.2003 [gs]: <ul><li>
  15 + * Vergleichsoperator hinzugef&uuml;gt
  16 + * </li><li>
  17 + * polyeder_movable von gra_app nach hier hin
  18 + * &uuml;bertragen
  19 + * </li><li>
  20 + * Member world_coordinate rausgesmissen, vielleicht
  21 + * bau ich den noch mal wieder ein, aber er darf nie
  22 + * implizit benutzt werden, ich denke es ist besser
  23 + * Alle Positionen und Ausrichtungen von Objekten in
  24 + * einer Weltklasse zu speichern.
  25 + * </li></ul>
  26 + */
  27 +
  28 +/*
  29 + * Copyright (C)2003 Georg Steffers
  30 + *
  31 + * This program is free software; you can redistribute it and/or modify
  32 + * it under the terms of the GNU General Public License as published by
  33 + * the Free Software Foundation; either version 2 of the License, or
  34 + * (at your option) any later version.
  35 + *
  36 + * This program is distributed in the hope that it will be useful,
  37 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  38 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  39 + * GNU General Public License for more details.
  40 + *
  41 + * You should have received a copy of the GNU General Public License
  42 + * along with this program; if not, write to the Free Software
  43 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  44 + */
  45 +
  46 +#ifndef __polyeder_h__
  47 +#define __polyeder_h__
  48 +
  49 +#include "../helper/container.h"
  50 +#include "../math/Mmn.h"
  51 +#include "polygon.h"
  52 +#include "vertex.h"
  53 +#include "movable.h"
  54 +
  55 +class polyeder : public container<polygon> {
  56 + public:
  57 + vertex_list vl;
  58 +
  59 + public:
  60 + polyeder() : container<polygon>() {}
  61 + polyeder(const polygon&, const vertex_list&);
  62 + polyeder(const polygon*, unsigned, const vertex_list&);
  63 + polyeder(const polyeder&);
  64 + ~polyeder() {}
  65 +
  66 + const polyeder& operator=(const polyeder&);
  67 + const polygon& operator[](unsigned index) const {
  68 + return content[index];
  69 + }
  70 + polygon& operator[](unsigned index) {
  71 + return content[index];
  72 + }
  73 +
  74 + virtual void transform(const Mmn<double>&, int=0);
  75 + virtual void transform_normals(const Mmn<double>&, int=0);
  76 + void trans_poly(unsigned, const Mmn<double>&, int=0);
  77 + virtual void reset(void);
  78 + /**
  79 + * \param lcx (lens coverage(x)) = Sichtfeld(x)
  80 + * \param sw (screen width) = Breite des Projektionsfensters
  81 + * \param sh (screen height) = Hoehe des Projektionsfensters
  82 + * \param ph_ar (physical aspect ratio) = Seitenverhaeltnis des
  83 + * Anzeigegeraets
  84 + * \param sy (scale y) = Wenn Anzeigegeraet und Projektionfenster die
  85 + * selbe Groesse haben 1, ansonsten der Wert um y proportional
  86 + * zu x zu projezieren.
  87 + * \param p Transformationsstufe
  88 + */
  89 + void project_2d(double lcx, double sw, double sh,
  90 + double ph_ar, double sy=1, int p=0);
  91 +};
  92 +
  93 +class polyeder_movable : public polyeder, public movable {
  94 + public:
  95 + polyeder_movable() : polyeder(), movable() {}
  96 + polyeder_movable(const polygon& p, const vertex_list& vl) :
  97 + polyeder(p, vl) {}
  98 + polyeder_movable(const polygon* p, unsigned c, const vertex_list& vl) :
  99 + polyeder(p, c, vl) {}
  100 + polyeder_movable(const polyeder& p) :
  101 + polyeder(p) {}
  102 +
  103 + void transform(int transstage) {
  104 + polyeder::transform(t_mat, transstage);
  105 + movable::transform(transstage);
  106 + }
  107 +
  108 + void transform_normals(int p) {
  109 + polyeder::transform_normals(t_mat, p);
  110 + }
  111 +
  112 + void reset(void) {
  113 + polyeder::reset();
  114 + movable::reset();
  115 + }
  116 +};
  117 +
  118 +#endif
  1 +#include "polygon.h"
  2 +
  3 +void polygon::_init_normal_(void) {
  4 + if(vl && count>0) {
  5 + for(unsigned i=0; i<count; i++) {
  6 + center[O_X]+=(*vl)[content[i]][O_X];
  7 + center[O_Y]+=(*vl)[content[i]][O_Y];
  8 + center[O_Z]+=(*vl)[content[i]][O_Z];
  9 + }
  10 +
  11 + center[X]=center[O_X]/=count;
  12 + center[Y]=center[O_Y]/=count;
  13 + center[Z]=center[O_Z]/=count;
  14 + center[W]=center[O_W]=1;
  15 +
  16 + normal=center+
  17 + (((*vl)[content[1]]-(*vl)[content[0]])|
  18 + ((*vl)[content[count-1]]-(*vl)[content[0]])).norm();
  19 + }
  20 + else {
  21 + center=vertex();
  22 + normal=vertex();
  23 + }
  24 +}
  25 +
  26 +void polygon::transform(const Mmn<double>& tm, int p) {
  27 + for(unsigned i=0; i<count; i++) {
  28 + (*vl)[content[i]].transform(tm, p);
  29 + }
  30 +
  31 + transform_normal(tm, p);
  32 +}
  33 +
  34 +void polygon::transform_normal(const Mmn<double>& tm, int p) {
  35 + center.transform(tm, p);
  36 + normal.transform(tm, p);
  37 +}
  38 +
  39 +void polygon::reset(void) {
  40 +/* for(unsigned i=0; i<count; i++) {
  41 + (*vl)[content[i]].reset();
  42 + }*/
  43 +
  44 + center.reset();
  45 + normal.reset();
  46 +}
  47 +
  48 +/**
  49 + * \brief Clipping gegen eine vordere Z-Ebene
  50 + *
  51 + * Dieser Algorithmus clippt das polygon gegen eine vordere Z-Ebene
  52 + *
  53 + * \param this Das ungeclippte unprojezierte Polygon.
  54 + * \return ein geclipptes Polygon.
  55 + */
  56 +polygon polygon::clip_front_z(double min_Z) const {
  57 + container<unsigned> clip;
  58 + polygon ret;
  59 +
  60 + for(unsigned j=0; j<(*this).card(); j++) {
  61 + double x0=(*vl)[container<unsigned>::operator[](j)][X],
  62 + y0=(*vl)[container<unsigned>::operator[](j)][Y],
  63 + z0=(*vl)[container<unsigned>::operator[](j)][Z],
  64 + x1=(*vl)[container<unsigned>::operator[]((j+1)%(*this).card())][X],
  65 + y1=(*vl)[container<unsigned>::operator[]((j+1)%(*this).card())][Y],
  66 + z1=(*vl)[container<unsigned>::operator[]((j+1)%(*this).card())][Z];
  67 +
  68 + // Wenn beide drin sind den zweiten übernehmen.
  69 + if(z0>min_Z && z1>min_Z)
  70 + // Nur P2 nach clip übernehmen
  71 + clip[clip.card()]=
  72 + container<unsigned>::operator[]((j+1)%(*this).card());
  73 +
  74 + // Wenn nur P2 drin ist
  75 + if(z0<=min_Z && z1>min_Z) {
  76 + // Schnittpunkt berechnen und nach temp übernehmen
  77 + unsigned idx=(*vl).card();
  78 + double t=(min_Z-z0)/(z1-z0);
  79 + double x=x0+t*(x1-x0);
  80 + double y=y0+t*(y1-y0);
  81 +
  82 + // neuen Vertex zur Vertexliste.
  83 + (*vl)[idx]=vertex(x, y, min_Z, COORD);
  84 +
  85 + // und ins geclippte polygon
  86 + clip[clip.card()]=idx;
  87 + // und P2 ins geclippte polygon
  88 + clip[clip.card()]=
  89 + container<unsigned>::operator[]((j+1)%(*this).card());
  90 + }
  91 +
  92 + // Wenn nur P1 drin ist
  93 + if(z0>min_Z && z1<=min_Z) {
  94 + // Schnittpunkt berechnen und nach temp übernehmen
  95 + unsigned idx=(*vl).card();
  96 + double t=(min_Z-z1)/(z0-z1);
  97 + double x=x1+t*(x0-x1);
  98 + double y=y1+t*(y0-y1);
  99 +
  100 + // neuen Vertex zur Vertexliste.
  101 + (*vl)[idx]=vertex(x, y, min_Z, COORD);
  102 +
  103 + // und ins geclippte polygon
  104 + clip[clip.card()]=idx;
  105 + }
  106 + }
  107 +
  108 + // Das geclippte Polygon zurückliefern.
  109 + ret=polygon(clip, vl);
  110 + ret.set_id(id);
  111 + return ret;
  112 +}
  113 +
  114 +/**
  115 +* \brief Clippings nach Sutherland-Hodgman
  116 +*
  117 +* Cliped das Polygon an dem Polygon p. Es wird ein neues Polygon
  118 +* erzeugt, das diesem Polygon innerhalb des Polygons p entspricht.
  119 +* Dieses neue Polygon nutzt die selbe Vertexliste.
  120 +*
  121 +* \param p Das Polygon an dem geclipped werden soll.
  122 +* \returns Ein in p passendes Polygon.
  123 +*/
  124 +polygon polygon::clip_2d(const polygon& p) const {
  125 + //! enth&auml;lt w&auml;hrend des clippings die aktuellen
  126 + //! Vertex_listen indizies.
  127 + container<unsigned> clip;
  128 +
  129 + // Zuerst Origialdaten sichern.
  130 + clip=(container<unsigned>)*this;
  131 +
  132 + // Solange unbearbeitete Kanten im Clippolygon sind...
  133 + for(unsigned i=0; i<p.card(); i++) {
  134 + //! enth&auml;lt immer die neuen geclippten VL-Indizies
  135 + container<unsigned> temp;
  136 +
  137 + //! Hole nächste Kante des Clippolygons und sichere sie als
  138 + //! Vektor. Diese ist definiert über die beiden Punkte
  139 + //! p[i] und p[(i+1)%p.card()]
  140 + double x0=p[i][X],
  141 + y0=p[i][Y],
  142 + x1=p[(i+1)%p.card()][X],
  143 + y1=p[(i+1)%p.card()][Y];
  144 +
  145 + // Jetzt muss zunaechst ein Vektor erzeugt werden der senkrecht
  146 + // von der Kante ins Poligon zeigt
  147 + // chk=(X=P1.Y-P2.Y, Y=P2.X-P1.X, 0)
  148 + vertex chk(y0-y1, x1-x0, 0, VEKTOR);
  149 +
  150 + // Solange Kanten nicht bearbeitet wurden
  151 + for(unsigned j=0; j<clip.card(); j++) {
  152 + //! hole nächste Kante aus clipped Prüfe ob Punkt1 und/oder
  153 + //! Punkt2 immerhalb des Clippolygons sind.
  154 + //! Kante ist (*vl)[clip[j]] und (*vl)[clip[(j+1)%clip.count]]
  155 + double x0s=(*vl)[clip[j]][X],
  156 + y0s=(*vl)[clip[j]][Y],
  157 + x1s=(*vl)[clip[(j+1)%clip.card()]][X],
  158 + y1s=(*vl)[clip[(j+1)%clip.card()]][Y];
  159 +
  160 + //! Liegt der erste Punkt innerhalb des Clippolygons
  161 + //! chk%(P1 - clipP1) > 0.05 und/oder
  162 + double chk_p1=chk%((*vl)[clip[j]] - (*p.vl)[i]);
  163 + //! liegt der zweite Punkt innerhalb des Clippolygons
  164 + //! chk%(P2 - clipP1) > 0.05
  165 + double chk_p2=chk%((*vl)[clip[(j+1)%clip.card()]] -
  166 + (*p.vl)[i]);
  167 +
  168 + // 0.05 ist ein Epsilon um Ungenauigkeiten auszugleichen und
  169 + // ganz sicher zu gehen das der Punkt wirklich innerhalb liegt.
  170 +
  171 + // Wenn beide drin sind
  172 + if(chk_p1>0.05 && chk_p2>0.05)
  173 + // Nur P2 nach temp übernehmen
  174 + temp[temp.card()]=clip[(j+1)%clip.card()];
  175 +
  176 + // Wenn nur P1 drin ist
  177 + if(chk_p1>0.05 && chk_p2<=0.05) {
  178 + // Schnittpunkt berechnen und nach temp übernehmen
  179 + unsigned idx=(*vl).card();
  180 + double x,y;
  181 +
  182 + x=x0+((((x1s-x0s)*(y0-y0s))+((y1s-y0s)*(x0s-x0)))/
  183 + (((x1-x0)*(y1s-y0s))-((y1-y0)*(x1s-x0s))))*(x1-x0);
  184 +
  185 + y=y0+((((x1s-x0s)*(y0-y0s))+((y1s-y0s)*(x0s-x0)))/
  186 + (((x1-x0)*(y1s-y0s))-((y1-y0)*(x1s-x0s))))*(y1-y0);
  187 +
  188 + // neuen Vertex zur Vertexliste.
  189 + (*vl)[idx]=vertex(x, y, 0, COORD);
  190 +
  191 + temp[temp.card()]=idx;
  192 + }
  193 +
  194 + // Wenn nur P2 drin ist
  195 + if(chk_p1<=0.05 && chk_p2>0.05) {
  196 + // Schnittpunkt berechnen und nach temp übernehmen
  197 + unsigned idx=(*vl).card();
  198 + double x,y;
  199 +
  200 + x=x0+((((x1s-x0s)*(y0-y0s))+((y1s-y0s)*(x0s-x0)))/
  201 + (((x1-x0)*(y1s-y0s))-((y1-y0)*(x1s-x0s))))*(x1-x0);
  202 +
  203 + y=y0+((((x1s-x0s)*(y0-y0s))+((y1s-y0s)*(x0s-x0)))/
  204 + (((x1-x0)*(y1s-y0s))-((y1-y0)*(x1s-x0s))))*(y1-y0);
  205 +
  206 + // neuen Vertex zur Vertexliste.
  207 + (*vl)[idx]=vertex(x, y, 0, COORD);
  208 +
  209 + temp[temp.card()]=idx;
  210 +
  211 + // P2 nach temp übernehmen
  212 + temp[temp.card()]=clip[(j+1)%clip.card()];
  213 + }
  214 +
  215 + // Wenn keiner drin ist
  216 + // Nichts nach temp
  217 + }
  218 +
  219 + // temp enth&auml;lt jetzt die aktuellen Vertexindizies,
  220 + // f&uuml;r den n&auml;chsten durchlauf mu&szlig; clip
  221 + // darauf gesetzt werden.
  222 + clip=temp;
  223 + }
  224 +
  225 + // Das geclippte Polygon zurückliefern.
  226 + return polygon(clip, vl);
  227 +}
  228 +
  229 +void polygon::project_2d(double lcx, double sw, double sh,
  230 + double ph_ar, double sy, int p) {
  231 + for(unsigned i=0; i<count; i++) {
  232 + (*vl)[content[i]].project_2d(lcx, sw, sh, ph_ar, sy, p);
  233 + }
  234 +}
  1 +/**
  2 + * \file polygon.h
  3 + *
  4 + * \brief definiert alle Klassen zu Polygonen (Gruppen mehrerer Vertexe die
  5 + * eine Fl&auml;che bilden.
  6 + *
  7 + * Hier ist die Klasse polygon definiert, die die zentrale Klasse der
  8 + * 3D-Application ist. Es werden immer Polygone dargestellt.
  9 + *
  10 + * \author Georg Steffers <georg@steffers.org> [gs]
  11 + *
  12 + * \date 16.12.2003
  13 + *
  14 + * \version ..2002 [gs]: erste Implementation
  15 + * \version 16.12.2003 [gs]: <ul><li>
  16 + * Beginn der Dokumentation mir Doxygen
  17 + * </li><li>
  18 + * Den Sutherland-Hodgman Clipping Algorithmus
  19 + * eingebaut. Er scheint zu funktionieren, muss
  20 + * aber noch ausgiebig getestet werden.
  21 + * </li></ul>
  22 + * \version 19.12.2003 [gs]: <ul><li>
  23 + * Vergleichsoprator hinzugef&uuml;gt
  24 + * </li><li>
  25 + * polygon_movable von gra_app &uuml;bertragen
  26 + * </li></ul>
  27 + * \version 21.12.2003 [gs]: vorderes z-clipping eingebaut.
  28 + */
  29 +
  30 +/*
  31 + * Copyright (C)2003 Georg Steffers
  32 + *
  33 + * This program is free software; you can redistribute it and/or modify
  34 + * it under the terms of the GNU General Public License as published by
  35 + * the Free Software Foundation; either version 2 of the License, or
  36 + * (at your option) any later version.
  37 + *
  38 + * This program is distributed in the hope that it will be useful,
  39 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  40 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  41 + * GNU General Public License for more details.
  42 + *
  43 + * You should have received a copy of the GNU General Public License
  44 + * along with this program; if not, write to the Free Software
  45 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  46 + */
  47 +
  48 +#ifndef __polygon_h__
  49 +#define __polygon_h__
  50 +
  51 +#include "../helper/container.h"
  52 +#include "../math/Mmn.h"
  53 +#include "vertex.h"
  54 +#include "movable.h"
  55 +
  56 +
  57 +class polyeder;
  58 +
  59 +class polygon : public container<unsigned> {
  60 + private:
  61 + vertex_list* vl;
  62 + vertex center;
  63 + vertex normal;
  64 +
  65 + polyeder* pe;
  66 + char id[30];
  67 +
  68 + public:
  69 + polygon()
  70 + : container<unsigned>(), vl(NULL), center(vertex()),
  71 + normal(vertex()), pe(NULL) {}
  72 + polygon(vertex_list *const vl)
  73 + : container<unsigned>(), vl(vl), center(vertex()),
  74 + normal(vertex()), pe(NULL) {}
  75 + polygon(const unsigned& p, vertex_list *const vl)
  76 + : container<unsigned>(p), vl(vl), pe(NULL) { _init_normal_(); }
  77 + polygon(const container<unsigned>& p, vertex_list *const vl)
  78 + : container<unsigned>(p), vl(vl), pe(NULL) { _init_normal_(); }
  79 + polygon(const unsigned* idxs, unsigned count, vertex_list *const vl)
  80 + : container<unsigned>(idxs, count), vl(vl),
  81 + pe(NULL) { _init_normal_(); }
  82 + polygon(const polygon& p)
  83 + : container<unsigned>(p), vl(p.vl),
  84 + center(p.center), normal(p.normal), pe(p.pe) { strncpy(id, p.id, 29); }
  85 + ~polygon() {}
  86 +
  87 + virtual void _init_normal_();
  88 +
  89 + virtual bool operator==(const polygon& p) const {
  90 + if(this->container<unsigned>::operator==((container<unsigned>)p)&&
  91 + center==p.center &&
  92 + normal==p.normal)
  93 + return true;
  94 +
  95 + return false;
  96 + }
  97 +
  98 + void set_id(const char* i) { strncpy(id, i, 29); }
  99 + const char* get_id(void) const { return id; }
  100 +
  101 + virtual polygon clip_2d(const polygon& p) const;
  102 + virtual polygon clip_front_z(double min_Z) const;
  103 +
  104 + virtual const polygon& operator=(const polygon& p) {
  105 + if(this==&p)
  106 + return *this;
  107 +
  108 + container<unsigned>::operator=(p);
  109 + vl=p.vl;
  110 + center=p.center;
  111 + normal=p.normal;
  112 + pe=p.pe;
  113 + strncpy(id, p.id, 29);
  114 +
  115 + return *this;
  116 + }
  117 + virtual void set_vertex_list(vertex_list *const vl) {
  118 + this->vl=vl;
  119 + // dachte ich zuerst, aber eigentlich sollte alles richtig
  120 + // gesetzt sein, da sich ja die indizies in der neuen Vertexliste
  121 + // nicht aender sondern nur die Adressen!
  122 + //if(normal==0 || center==0)
  123 + // _init_normal_();
  124 + }
  125 + virtual void set_polyeder(polyeder *const pe) {
  126 + this->pe=pe;
  127 + }
  128 + virtual const polyeder& get_polyeder(void) {
  129 + return *pe;
  130 + }
  131 + virtual const vertex& operator[](unsigned index) const {
  132 + return (*vl)[content[index]];
  133 + }
  134 + virtual vertex& operator[](unsigned index) {
  135 + return (*vl)[content[index]];
  136 + }
  137 +
  138 + virtual unsigned vl_idx(unsigned index) {
  139 + return content[index];
  140 + }
  141 +
  142 + /*
  143 + * Ich sollte den Normalenvektor aus der Vertexliste nehmen und
  144 + * bei bedarf neu berechnen oder aber die transformation für
  145 + * normalenvektoren benutzen wenn ich ihn transformiere.
  146 + */
  147 + virtual vertex const& center_p(void) {
  148 + return center;
  149 + }
  150 +
  151 + virtual vertex const& normal_p(void) const {
  152 + return normal;
  153 + }
  154 +
  155 + virtual void transform(const Mmn<double>&, int=0);
  156 + virtual void transform_normal(const Mmn<double>&, int=0);
  157 + virtual void reset(void);
  158 + virtual void project_2d(double lcx, double sw, double sh,
  159 + double ph_ar, double sy=1, int p=0);
  160 +};
  161 +
  162 +class polygon_movable : public polygon, public movable {
  163 + public:
  164 + polygon_movable() : polygon(), movable() {}
  165 + polygon_movable(vertex_list *const vl) :
  166 + polygon(vl) {}
  167 + polygon_movable(const unsigned& p, vertex_list *const vl) :
  168 + polygon(p, vl) {}
  169 + polygon_movable(const unsigned* idxs, unsigned count,
  170 + vertex_list *const vl) :
  171 + polygon(idxs, count, vl) {}
  172 + polygon_movable(const polygon& p) :
  173 + polygon(p) {}
  174 +
  175 + void transform(int transstage) {
  176 + polygon::transform(t_mat, transstage);
  177 + movable::transform(transstage);
  178 + }
  179 +
  180 + void transform_normal(int p) {
  181 + polygon::transform_normal(t_mat, p);
  182 + }
  183 +
  184 + void reset(void) {
  185 + polygon::reset();
  186 + movable::reset();
  187 + }
  188 +};
  189 +
  190 +
  191 +#endif // __polygon_h__
  1 +#include "vertex.h"
  2 +
  3 +const vertex& vertex::operator=(const vertex& v) {
  4 + if(this==&v)
  5 + return *this;
  6 +
  7 + original=v.original;
  8 + transformed=v.transformed;
  9 + trans_stage=v.trans_stage;
  10 +
  11 + return *this;
  12 +}
  13 +
  14 +vertex operator*(const double& a, const vertex& v) {
  15 + return v * a;
  16 +}
  17 +
  18 +vertex vertex::operator*(const double& a) const {
  19 + vertex v=*this;
  20 + v.original=v.original*a;
  21 + v.transformed=v.transformed*a;
  22 + return v;
  23 +}
  24 +
  25 +double vertex::operator% (const vertex& v) const {
  26 + return transformed%v.transformed;
  27 +}
  28 +
  29 +vertex vertex::operator| (const vertex& v) const {
  30 + vertex w=*this;
  31 + w.original=w.original|v.original;
  32 + w.transformed=w.transformed|v.transformed;
  33 + return w;
  34 +}
  35 +
  36 +vertex vertex::operator+ (const vertex& v) const {
  37 + vertex w=*this;
  38 + w.original=w.original+v.original;
  39 + w.transformed=w.transformed+v.transformed;
  40 + return w;
  41 +}
  42 +
  43 +vertex vertex::operator- (const vertex& v) const {
  44 + vertex w=*this;
  45 + w.original=w.original-v.original;
  46 + w.transformed=w.transformed-v.transformed;
  47 + return w;
  48 +}
  49 +
  50 +vertex vertex::norm(void) const {
  51 + vertex w;
  52 + w.original=original*(1/original.v_betr());
  53 + w.transformed=transformed*(1/transformed.v_betr());
  54 + return w;
  55 +}
  56 +
  57 +double vertex::betr(void) const {
  58 + return transformed.v_betr();
  59 +}
  60 +
  61 +void vertex::reset(void) {
  62 + if(trans_stage!=0) {
  63 + trans_stage=0;
  64 + transformed=original;
  65 + }
  66 +}
  67 +
  68 +void vertex::transform(const Mmn<double>& t_mat, int p) {
  69 + if(trans_stage < p) {
  70 + transformed=t_mat % transformed;
  71 + trans_stage=p;
  72 + }
  73 +}
  74 +
  75 +void vertex::project_2d(double lcx, double sw, double sh,
  76 + double ph_ar, double sy, int p) {
  77 + if(trans_stage < p) {
  78 + transformed[X]=transformed[X]/transformed[Z] *
  79 + (lcx * sw) + 0.5*sw;
  80 + transformed[Y]=-transformed[Y]/transformed[Z] *
  81 + (lcx * ph_ar * sh) + 0.5*sy*sh;
  82 + transformed[Z]=1/transformed[Z]; // 1/Z ist linear im projezierten
  83 + // Polygon kann ich also über die
  84 + // Polygonkanten interpolieren
  85 + // brauche ich fuer z-Buffer,
  86 + // Texturemapping und evtl. noch mehr.
  87 +
  88 + trans_stage=p;
  89 + }
  90 +}
  91 +
  92 +inline double vertex::unproject_X(double tx, double tz,
  93 + double lcx, double sw) {
  94 + return (tx - 0.5*sw) / (lcx * sw) / tz;
  95 +}
  96 +
  97 +inline double vertex::unproject_Y(double ty, double tz,
  98 + double lcx, double sh,
  99 + double ph_ar, double sy) {
  100 + return (ty - 0.5*sy*sh) / (lcx * ph_ar * sh) / tz;
  101 +}
  102 +
  103 +inline double vertex::unproject_Z(double tz) {
  104 + return 1/tz;
  105 +}
  106 +
  107 +inline double vertex::unproject_U(double tu, double tz,
  108 + double lcx, double sw) {
  109 + return (tu - 0.5*sw) / (lcx * sw) / tz;
  110 +}
  111 +
  112 +inline double vertex::unproject_V(double tv, double tz,
  113 + double lcx, double sh,
  114 + double ph_ar, double sy) {
  115 + return (tv - 0.5*sy*sh) / (lcx * ph_ar * sh) / tz;
  116 +}
  117 +
  118 +void vertex_list::reset(void) {
  119 + for(unsigned i=0; i<count; i++)
  120 + content[i].reset();
  121 +
  122 + if(variable) {
  123 + delete [] variable;
  124 + variable=NULL;
  125 + var_count=0;
  126 + }
  127 +}
  1 +/**
  2 + * \file vertex.h
  3 + *
  4 + * \brief Definiert eine Klasse f&uuml;r einen Vertex und eine Klasse f&uuml;
  5 + * einen Vertexliste
  6 + *
  7 + * Ein Vertex ist bei mir ein transformbares 4-Tupel, das sowohl einen Vektor
  8 + * als auch eine Coordinate darstellen kann. Ich bezeichne beides als Vertex,
  9 + * weil auch der Vektor einen Coordinate darstellen kann (falls man ihn als
  10 + * Ursprungsvektor betrachtet)
  11 + * Eine Vertexliste ist ein Container der Vertexe aufnehmen kann und
  12 + * insbesondere zwei getrennte Sepicherbereiche zur aufnahme von Vertexen hat,
  13 + * &uuml;ber die aber mit dem gleichen Zugriffsmechanismus zugegriffen wird.
  14 + * Die wird gebraucht um leicht Vertexe f&uuml;r das clipping hinzuf&uuml;gen
  15 + * zu k&ouml;nnen.
  16 + *
  17 + * \author Georg Steffers <georg@steffers.org> [gs]
  18 + *
  19 + * \date 16.12.2003
  20 + *
  21 + * \version ..2002 [gs]: erste Implementation
  22 + * \version 16.12.2003 [gs]: <ul><li>
  23 + * Beginn der Dokumentation mir Doxygen
  24 + * </li><li>
  25 + * Vertexlist zu einer zweiteiligen Liste gemacht,
  26 + * damit Sie f&uuml;r clipping geeignet ist.
  27 + * </li></ul>
  28 + * \version 19.12.2003 [gs]: Vergleichsoperator hinzugef&uuml;gt und
  29 + * clip_2d_mask rausgeshmissen.
  30 + */
  31 +
  32 +/*
  33 + * Copyright (C)2003 Georg Steffers
  34 + *
  35 + * This program is free software; you can redistribute it and/or modify
  36 + * it under the terms of the GNU General Public License as published by
  37 + * the Free Software Foundation; either version 2 of the License, or
  38 + * (at your option) any later version.
  39 + *
  40 + * This program is distributed in the hope that it will be useful,
  41 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  42 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  43 + * GNU General Public License for more details.
  44 + *
  45 + * You should have received a copy of the GNU General Public License
  46 + * along with this program; if not, write to the Free Software
  47 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  48 + */
  49 +
  50 +#ifndef __vertex_h__
  51 +#define __vertex_h__
  52 +
  53 +#include "../math/Mmn.h"
  54 +#include "../math/V_K4.h"
  55 +#include "../helper/container.h"
  56 +
  57 +#define X 0
  58 +#define Y 1
  59 +#define Z 2
  60 +#define W 3
  61 +#define O_X 4
  62 +#define O_Y 5
  63 +#define O_Z 6
  64 +#define O_W 7
  65 +
  66 +//! W=0 hei&szlig;t der Vertex stellt einen Vektor dar.
  67 +#define VEKTOR 0
  68 +//! W=0 hei&szlig;t der Vertex stellt einen Coordinate dar.
  69 +#define COORD 1
  70 +
  71 +class vertex {
  72 + private:
  73 + V_K4<double> original;
  74 + V_K4<double> transformed;
  75 + int trans_stage;
  76 +// char clip_mask_2d;
  77 +
  78 + public:
  79 + vertex() : trans_stage(0) {}
  80 + vertex(double x, double y, double z, double w=VEKTOR)
  81 + : original(x,y,z,w), transformed(x,y,z,w),
  82 + trans_stage(0) {}
  83 + vertex(const vertex& v) : original(v.original),
  84 + transformed(v.transformed),
  85 + trans_stage(v.trans_stage) {}
  86 +
  87 + const vertex& operator=(const vertex& v);
  88 + const double& operator[](unsigned xyzw) const {
  89 + if(xyzw < X) { xyzw=X; }
  90 + if(xyzw > O_W) { xyzw=O_W; }
  91 +
  92 + if(xyzw <= W)
  93 + return transformed.a(xyzw, 0);
  94 + else
  95 + return original.a(xyzw-O_X, 0);
  96 + }
  97 + double& operator[](unsigned xyzw) {
  98 + if(xyzw < X) { xyzw=X; }
  99 + if(xyzw > O_W) { xyzw=O_W; }
  100 +
  101 + if(xyzw <= W)
  102 + return transformed.a(xyzw, 0);
  103 + else
  104 + return original.a(xyzw-O_X, 0);
  105 + }
  106 + vertex operator*(const double&) const;
  107 + friend vertex operator*(const double&, const vertex&);
  108 +
  109 + double operator% (const vertex&) const;
  110 + vertex operator| (const vertex&) const;
  111 + vertex operator+ (const vertex&) const;
  112 + vertex operator- (const vertex&) const;
  113 + bool operator== (const vertex& v) const {
  114 + if(this->original == v.original &&
  115 + this->transformed == v.transformed &&
  116 + this->trans_stage == v.trans_stage)
  117 + return true;
  118 +
  119 + return false;
  120 + }
  121 +
  122 + vertex norm(void) const;
  123 + double betr(void) const;
  124 +
  125 + void reset(void);
  126 + void set_trans_stage(int p=0) { trans_stage=p; }
  127 + unsigned get_trans_stage(void) const { return trans_stage; }
  128 + V_K4<double> const& get_o(void) const {return original;}
  129 + V_K4<double> const& get_t(void) const {return transformed;}
  130 +
  131 + void transform(const Mmn<double>&, int=0);
  132 + void project_2d(double lcx, double sw, double sh,
  133 + double ph_ar, double sy, int p);
  134 +
  135 + double unproject_X(double, double, double, double);
  136 + double unproject_Y(double, double, double, double, double, double);
  137 + double unproject_Z(double);
  138 + double unproject_U(double, double, double, double);
  139 + double unproject_V(double, double, double, double, double, double);
  140 +
  141 + void print() {
  142 + original.print();
  143 + transformed.print();
  144 + cout << "---\n";
  145 + }
  146 +};
  147 +
  148 +vertex operator*(const double& a, const vertex& v);
  149 +
  150 +class vertex_list : public container<vertex> {
  151 + protected:
  152 + vertex* variable;
  153 + unsigned var_count;
  154 +
  155 + public:
  156 + vertex_list()
  157 + : container<vertex>(), variable(NULL), var_count(0) {}
  158 + vertex_list(const vertex& v)
  159 + : container<vertex>(v), variable(NULL), var_count(0) {}
  160 + vertex_list(const vertex* idxs, unsigned count)
  161 + : container<vertex>(idxs, count), variable(NULL), var_count(0) {}
  162 + vertex_list(const vertex_list& v)
  163 + : container<vertex>(v), var_count(v.var_count) {
  164 + if(var_count > 0)
  165 + variable=new vertex[var_count];
  166 + else
  167 + variable=NULL;
  168 +
  169 + for(unsigned i=0; i<var_count; i++)
  170 + variable[i]=v.variable[i];
  171 + }
  172 + ~vertex_list() {
  173 + if(variable) {
  174 + delete [] variable;
  175 + variable=NULL;
  176 + var_count=0;
  177 + }
  178 + }
  179 +
  180 + vertex& operator[](unsigned index) {
  181 + if(index+1 <= count)
  182 + return content[index];
  183 + else
  184 + index-=count-1;
  185 +
  186 + if(index+1 > var_count) {
  187 + vertex* content_tmp=new vertex[index+1];
  188 +
  189 + for(unsigned i=0; i<var_count; i++)
  190 + content_tmp[i]=variable[i];
  191 +
  192 + delete [] variable;
  193 + variable=content_tmp;
  194 + var_count=index+1;
  195 + }
  196 +
  197 + return variable[index];
  198 + }
  199 +
  200 + void resize(unsigned size) {
  201 + if(size < count) {
  202 + if(variable) {
  203 + delete [] variable;
  204 + variable=NULL;
  205 + var_count=0;
  206 + }
  207 + return;
  208 + }
  209 + else
  210 + size-=count;
  211 +
  212 + vertex* content_tmp;
  213 + if(size>0) {
  214 + content_tmp=new vertex[size];
  215 +
  216 + for(unsigned i=0; i<size<var_count?size:var_count; i++)
  217 + content_tmp[i]=variable[i];
  218 + }
  219 + else
  220 + content_tmp=NULL;
  221 +
  222 + delete [] variable;
  223 + variable=content_tmp;
  224 + var_count=size;
  225 + }
  226 +
  227 + unsigned fix_card(void) { return container<vertex>::card(); }
  228 + unsigned var_card(void) { return var_count; }
  229 + unsigned card(void) { return fix_card()+var_card(); }
  230 + void reset(void);
  231 +};
  232 +
  233 +#endif // __vertex_h__
  1 +/**
  2 + * \file gra_app.cpp
  3 + *
  4 + * \brief Testapplication zu engage
  5 + *
  6 + * Dieses kleine Prog testet die bestehenden Funktionen von engage und
  7 + * dient dazu neue Funktionen testweise einzubauen, bevor sie endg&uuml;ltig
  8 + * in die lib kommen.
  9 + *
  10 + * \author Georg Steffers <georg@steffers.org> [gs]
  11 + *
  12 + * \date 16.12.2003
  13 + *
  14 + * \version ..2002 [gs]: erste Implementation
  15 + * \version 13.12.2003 [gs]: movable eingefügt mit Funktionen f&uuml;r die
  16 + * wichtigsten Bewegungen (muss aber noch eine
  17 + * gro&szlig;es cleanup und fixing her) schient aber
  18 + * f&uuml;r die momentanen bed&uuml;rfnisse zu
  19 + * reichen.
  20 + * \version 16.12.2003 [gs]: <ul><li>
  21 + * Beginn der Dokumentation mit Doxygen
  22 + * </li><li>
  23 + * einige kleinere Fixes an movable
  24 + * </li></ul>
  25 + * \version 19.12.2003 [gs]: <ul><li>
  26 + * Eine Polygonliste eingebaut und diese sortiert,
  27 + * so das die am Weitesten vom Betrachter entfernten
  28 + * Polygone zuerst gezeichnet werden.
  29 + * Dazu musste auch eine Methode geschaffen werden
  30 + * mit der man feststellen konnte zu welchem Polyeder
  31 + * welches Polygon geh&ouml;rt. Dies habe ich mit
  32 + * der Methode contains in der Klasse container
  33 + * eingebaut.
  34 + * </li><li>
  35 + * Die Klasse movable in eine eigenen Datei verschoben
  36 + * geometry/movable.h. Au&szlig;erdem die Klassen
  37 + * polygon_movable nach geometry/polygon.h und
  38 + * polyeder_movable nach geometry/polyeder.h
  39 + * verschoben.
  40 + * </li><li>
  41 + * Ein viertes Polygon hinzugefügt, das erst
  42 + * verschoben und dann um die Weltachsen gedreht wird.
  43 + * Nur um zu demonstrieren was diese Reihenfolge
  44 + * der transformation f&uuml;r eine Wirkung hat.
  45 + * </li><li>
  46 + * kleinere &Auml;nderungen im Darstellungsteil.
  47 + * </li><li>
  48 + * &uuml;ber die in canvas neu geschaffene Methode
  49 + * draw_text die Zeit ss:ms die f&uuml;r einen
  50 + * kompletten Transformations/Zeichenvorgang
  51 + * ben&ouml;tigt wird angezeigt.
  52 + * </li></ul>
  53 + * \version 21.12.2003 [gs]: <ul><li>
  54 + * Herausgefunden warum die Würfel so gross sind
  55 + * obwohl sie nur eine Kantenl&auml;nge von 10 haben.
  56 + * Es ligt daran das sie mathematisch vor dem
  57 + * screen liegen, dadurch werden sie bei der
  58 + * projection gr&ouml;&szlig;er skaliert.
  59 + * </li><li>
  60 + * Die Klasse Camera eingef&uuml;gt und das
  61 + * Hauptprogramm so umgeschrieben das es eine
  62 + * Camera-Instanz nutzt um
  63 + * <ol><li>
  64 + * eine Kameratransformation zu machen
  65 + * </li><li>
  66 + * die 2D-Projektion durchzuf&uuml;hren.
  67 + * </li></ol>
  68 + * </li><li>
  69 + * so modifiziert das erst nur die Vertices von
  70 + * movable und die Normalenvektoren der Polygone
  71 + * berechnet werden, nur wenn das Polygon auch
  72 + * wirklich gezeichnet wird werden die weiteren
  73 + * Vertices transformiert und projeziert.
  74 + * </li><li>
  75 + * So umgebaut das das vordere z-clipping der
  76 + * Polygone genutzt wird.
  77 + * </li></ul>
  78 + * \version 22.12.2003 [gs]: Beleuchtung &uuml;ber die in canvas_imp neu
  79 + * eingebauten light_table eingebaut.
  80 + */
  81 +
  82 +/**
  83 + * \mainpage Referenzmanual zu ENGAGE
  84 + *
  85 + * \author Georg Steffers <georg@steffers.org> [gs]
  86 + * \date 22.12.2003
  87 + * \version 0.0.0: Erster Aufbau, jede Menge immer noch zu tun.
  88 + *
  89 + * Dies Projekt war zu anfang eine kleine app um ein wenig x-lib zu
  90 + * Programmieren. Als das ein wenig langweilig wurde und zumindest
  91 + * rudiment&auml;r funktionierte habe ich angefangen eine kleine 3D-Engine
  92 + * dazuzuschreiben.<br>
  93 + * Heute habe ich das Ziel dies ganze in irgendeinem Spiel zu verwenden.
  94 + * Bis dahin ist allerdings noch jede Menge zu tun.
  95 + * Was bislang fertig ist:
  96 + * <ul>
  97 + * <li>Klassen um die X-Lib auf einfacher Ebene anzusprechen, allerdings
  98 + * noch komplett ohne kommunikation mit dem Windowmanager.
  99 + * </li><li>
  100 + * Klasse um Manipulationen und Berechnungen verschiedenster Art an
  101 + * Matrizen und Vektoren mit 4 Tupeln zu machen, wie gauss, verschiedene
  102 + * Wege die Determinante zu berechnen, Inverse &uuml;ber Adjunkte oder
  103 + * &uuml;ber Gauss, Transponieren, Skalarprodukt, Matritzenprodunkt, Addition
  104 + * Subtraktion, etc.
  105 + * </li><li>
  106 + * Das Muster eines Event-Dispatchers sowie ein template von dem dich
  107 + * Klassen ableiten m&uuml;ssen, die Events f&uuml;r diesen erzeugen.
  108 + * </li><li>
  109 + * einen abstrakten canvas der events erzeugt, M&ouml;glihkeiten zur
  110 + * Farbverwaltung bietet und einen passenden rasterer erzeugt. Davon
  111 + * abgeleitet ein canvas f&uuml;r X11 und wiederum davon abgeleitete ein
  112 + * canvas f&uuml;r X11-SHM.
  113 + * rasterizer ist wiederum eine abstrakte Klasse die eine Schnittstelle bietet
  114 + * um auf einen canvas zu schreiben. davon abgeleitet existiert eine Klasse
  115 + * rasterizer_rgb, der speziell auf ein RGB Canvas schreibt, wie das z.B.
  116 + * in einem Truecolor Grafikmodus unter X11 n&ouml;tig ist.
  117 + * </li><li>
  118 + * Eine Helferklasse container, die verschiedene Daten speichen und
  119 + * organisieren kann. Diese sollte in zukunft abstrakt werden und
  120 + * Implementierungen versiedener Datenstrukturierungsmethoden verdecken,
  121 + * wie z.B. diverse Listenformen, B&auml;me oder einfache Arrays.
  122 + * Im Moment organisiert sie die Daten in einem Array. Einige wichtige Klassen
  123 + * (eigentlich alle die mehrere Elemente nicht bekannter Anzahl verwalten
  124 + * m&uuml;ssen) leiten sich von dieser Klasse ab. Das ist insbesondere
  125 + * vertex_list, polygon und polyeder.
  126 + * </li><li>
  127 + * Die grundlegenden Geometrieklassen (unterliegen nach wie vor starken
  128 + * Ver&auml;nderungen. Das sind im einzelnen:
  129 + * <ol><li>
  130 + * <b>vertex:</b> Diese Struktur nimmt einen 4-Tupel Vektor auf, der
  131 + * entweder eine 3D-Coordinate oder aber einen Vektor im 3D-Raum beschreibt.
  132 + * es werden sowohl die Originaldaten sowie transformierte Daten gespeichert.
  133 + * Au&szlig;erdem wird der transformationsstatus zwischengespeicher. (Das
  134 + * verhindert das, wenn sich z.B. ein Polygon einen Vertex mit einem anderen
  135 + * teilt, transformationen nur einmal an dem Vertex vorgenommen werden.
  136 + * </li><li>
  137 + * <b>vertex_list:</b> Eine Struktur um mehrere Vertexe zu verwalten.
  138 + * Sie besteht aus einem fixen und einem Variablen Teil, daher modifiziert
  139 + * sie einige Operatoren, die sie von container erbt. Die zweigeteiltheit
  140 + * ist wichtig, da bei einigen Operationen (insb. Clipping) zus&auml;tzliche
  141 + * Vertexe entstehen k&ouml;nnen, die aber nur tempor&auml;r wichtig sind.
  142 + * Durch die Zweigeteiltheit l&auml;&szlig;t sich immer genau unterscheiden
  143 + * was erzeugte und was originale Vertexe waren. Weiterhin ist wichtig,
  144 + * das auf beide Teile mit derselben Zugriffsfunktion zugegriffen werden kann.
  145 + * </li><li>
  146 + * <b>polygon:</b> ist eine Liste von Indexen in eine Vertexliste, die
  147 + * ein Polygon beschreibt. Leitet sich von container ab und verwaltet ihren
  148 + * container teil die indexe. Weiterhin enth&auml;lt polygon einen pointer auf
  149 + * eine vertex_list, auf die sich die Indexwerte bezieht und die Informationen
  150 + * zu einem Normalenvektor (als Basispunkt und Spitze Paar).
  151 + * Seit neustem enth&auml;lt ein Polygon auch noch einen pointer auf den
  152 + * polyeder zu dem es geh&ouml;rt (wenn es zu einem geh&ouml;rt, ansonsten null)
  153 + * und es sollte auch noch den index in diesem Polyeder enth&auml;ten.
  154 + * Damit w&auml;re es dann einfach von einem polygon wieder auf seinen
  155 + * Polyeder zu schlie&szlig;en (es kann aber auch sein das ich dieses Konzept
  156 + * wieder verwerfe und versuche irgendwie &uuml;ber den container eine
  157 + * M&ouml;glichkeit der zuordnung zu schaffen.<br>
  158 + * Da dies eine polygonale Engine ist enth&auml;lt polygon einige wichtige
  159 + * Methoden, wie das clipping zur vorderen z-ebene und das clipping ein einem
  160 + * weiteren polygon (nach der 2D-Projektion, um das Polygon gegen die
  161 + * Canvas (Rasterer)-Grenzen zu clippen.
  162 + * </li><li>
  163 + * <b>polyeder:</b> ist eine von container abgeleitete Klasse die eine
  164 + * Gruppe zusammengeh&ouml;riger polygone verwaltet. Zusammengeh&ouml;rend
  165 + * bedeutet in diesem Fall vor allem, das sie die gleiche Vertexliste nutzen.
  166 + * </li></ol></li></ul>
  167 + *
  168 + * Was die Engine bislang (mehr oder weniger sauber implementiert) macht:
  169 + * <ul><li>
  170 + * beliebige transformtion beliebiger polygone im 3D-Raum.
  171 + * </li><li>
  172 + * Perspektivische Projektion
  173 + * </li><li>
  174 + * clipping der projezierten Vertexe gegen die canvas-Grenzen
  175 + * </li><li>
  176 + * clipping der 3D-Coordinaten gegen eine vordere Z-Ebene
  177 + * </li><li>
  178 + * falls gew&uuml;nscht Backface-Culling
  179 + * </li><li>
  180 + * definieren einer Kamera und positionieren dieser.
  181 + * </li><li>
  182 + * Darstellung flatshaded, wireframe oder kombiniert.
  183 + * </li><li>
  184 + * Sortiert die polygone nach z, damit die hintersten zuerst gezeichnet werden.
  185 + * </li></ul>
  186 + *
  187 + * \bug [gs] Mein Backfaceculling funktioniert nicht, das scheint daran zu
  188 + * liegen, das eine projezierte Seite die 90 Grad zu mir aber stark am
  189 + * Rand des sichtbaren Bereichs ist sehr wohl von mir gesehen werden kann.
  190 + * In die berechnung des cullings muss also irgendwie das Scihtfeld
  191 + * bzw der Blickwinkel mit einbezogen werden.
  192 + * -- Gefixed: man muss als Blickwinkel nur den vrp nehmen, dann klappts.
  193 + * \bug [gs] Das Programm darf nicht mehr mit -ffast-math compiliert werden,
  194 + * da dann anscheinend irgendwas bei der berechnung der inversen
  195 + * Camera-Matrix kaputtoptimiert wird.
  196 + *
  197 + * \todo [gs] Evtl. sollte ich f&uuml;r den Rasterizer imlib2 oder evas
  198 + * verwenden (bzw ich baue einen rasterizer der diese Libs nutzt).
  199 + * Evtl. kann evas auch einen kompletten canvas für mich bilden, incl.
  200 + * Rasterizer. (Auch ein GL Rasterizer sollte noch geschrieben werden.
  201 + * \todo [gs] Eine menge cleanups.
  202 + * \todo [gs] Java Version schreiben und hoffen das sie schnell genug ist.
  203 + * \todo [gs] Nat&uuml;rlich noch jede Menge, Lightmapping, Texturemapping,
  204 + * Schadowmapping, vorne und hinten z-clipping usw.
  205 + * \todo [gs] gutes Konzept finden um z-clipping, transformieren und
  206 + * projezieren zu machen (es darf z.B. nich projeziert werden, solange
  207 + * das z-clipping l&auml;uft.
  208 + * \todo [gs] ein gutes konzept finden ein polygon einem polyeder zuzuweisen,
  209 + * und den index innerhalb des Polyeders zu bestimmen, auch wenn
  210 + * das polygon bereits transformiert wurde...in diesem zusammenhang
  211 + * glaube ich immer mehr, das es doch besser währe, das polygon
  212 + * wuerde beim clipping doch nicht einfach ein neues Polygon erzeugen
  213 + * und stattdessen sich selbst modifizieren und eine referenz auf
  214 + * sich zur&uuml;ckgeben. (Bei den == Operatoren würde ich dann immer
  215 + * checken ob es sich wirklich um eine Referenz auf die selbe Instanz
  216 + * (sprich Adressen gleich) ist.
  217 + *
  218 + * Copyright &copy;2003 Georg Steffers
  219 + *
  220 + * This program is free software; you can redistribute it and/or modify
  221 + * it under the terms of the GNU General Public License as published by
  222 + * the Free Software Foundation; either version 2 of the License, or
  223 + * (at your option) any later version.
  224 + *
  225 + * This program is distributed in the hope that it will be useful,
  226 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  227 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  228 + * GNU General Public License for more details.
  229 + *
  230 + * You should have received a copy of the GNU General Public License
  231 + * along with this program; if not, write to the Free Software
  232 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  233 + * <br><br><br>
  234 + */
  235 +
  236 +#ifndef __XProto_h__
  237 +#define __XProto_h__
  238 +
  239 +using namespace std;
  240 +
  241 +#include <cmath>
  242 +#include <time.h>
  243 +#include <unistd.h>
  244 +
  245 +#include "factory.h"
  246 +#include "dispatcher.h"
  247 +#include "canvas.h"
  248 +#include "rasterize.h"
  249 +#include "math/Mmn.h"
  250 +#include "math/V_K4.h"
  251 +#include "math/sin_cos.h"
  252 +#include "geometry/vertex.h"
  253 +#include "geometry/polygon.h"
  254 +#include "geometry/polyeder.h"
  255 +
  256 +#include <time.h>
  257 +#include <sys/timeb.h>
  258 +
  259 +int compf(const void* a, const void* b) {
  260 + polygon* _a=(polygon*)a;
  261 + polygon* _b=(polygon*)b;
  262 +
  263 + return (int)(_a->center_p()[Z] - _b->center_p()[Z])*-1;
  264 +}
  265 +
  266 +class light {
  267 + protected:
  268 + unsigned intensity;
  269 + double dist_falloff;
  270 +
  271 + public:
  272 + light(unsigned intense=255) : intensity(intense) {}
  273 +
  274 + virtual unsigned get_intensity(void) { return intensity; }
  275 + virtual void set_intensity(unsigned in) { intensity=in; }
  276 +};
  277 +
  278 +class ambient_light : public light {
  279 + public:
  280 + ambient_light(unsigned intense=255) : light(intense) {}
  281 +};
  282 +
  283 +// Diese Lampe ist &auml;hnlich wie die Sonne, sie beleuchtet die
  284 +// gesamte Scenen aus einer Richtung. Diese definiere ich einfach
  285 +// als fvw des movable.
  286 +class direct_light : public light, public movable {
  287 + public:
  288 + direct_light(unsigned intense=255) : light(intense), movable() {}
  289 +
  290 + const vertex& get_direction(void) {
  291 + return vfw;
  292 + }
  293 +};
  294 +
  295 +class camera : public movable {
  296 + private:
  297 + double lcxa; //!< (lens coverage(x) angle = Sichtfeld(x)-Winkle
  298 + double lcx; //!< (lens coverage(x)) = Sichtfeld(x)
  299 + double sw; //!< (screen width) = Breite des Projektionsfensters
  300 + double sh; //!< (screen height) = Hoehe des Projektionsfensters
  301 + double ph_ar; /**< \brief (physical aspect ratio) = Seitenverhaeltnis
  302 + * des Anzeigegeraets
  303 + */
  304 + double sy; //!< (scale y) = Wert um y proportional zu projezieren.
  305 + double dz; //!< (delta z) = Abstand des Auges zum screen
  306 +
  307 + Mmn<double> cam_trans;
  308 +
  309 + public:
  310 + camera(double lcxa=60) : movable() {
  311 + this->set_lens_coverage(lcxa);
  312 + }
  313 +
  314 + camera(const rasterizer& scr, double lcxa=60) : movable() {
  315 + this->set_lens_coverage(lcxa);
  316 + this->sw=scr.get_x_size();
  317 + this->sh=scr.get_y_size();
  318 + this->ph_ar=this->sw/this->sh;
  319 + this->sy=this->sh/this->sw*this->ph_ar;
  320 + this->dz=(this->sh/2)/tan(RAD(this->lcxa/2));
  321 + }
  322 +
  323 + camera(const rasterizer& scr, double ph_ar,
  324 + double lcxa) : movable() {
  325 + this->set_lens_coverage(lcxa);
  326 + this->sw=scr.get_x_size();
  327 + this->sh=scr.get_y_size();
  328 + this->ph_ar=ph_ar;
  329 + this->sy=this->sh/this->sw*this->ph_ar;
  330 + this->dz=(this->sh/2)/tan(RAD(this->lcxa/2));
  331 + }
  332 +
  333 + camera(double sw, double sh, double lcxa=60) : movable() {
  334 + this->set_lens_coverage(lcxa);
  335 + this->sw=sw;
  336 + this->sh=sh;
  337 + this->ph_ar=this->sw/this->sh;
  338 + this->sy=this->sh/this->sw*this->ph_ar;
  339 + this->dz=(this->sh/2)/tan(RAD(this->lcxa/2));
  340 + }
  341 +
  342 + camera(double sw, double sh,
  343 + double ph_ar, double lcxa=60) : movable() {
  344 + this->set_lens_coverage(lcxa);
  345 + this->sw=sw;
  346 + this->sh=sh;
  347 + this->ph_ar=ph_ar;
  348 + this->sy=this->sh/this->sw*this->ph_ar;
  349 + this->dz=(this->sh/2)/tan(RAD(this->lcxa/2));
  350 + }
  351 +
  352 + /**
  353 + * \brief Setze Sichtfeld. (zwischen 10 und 170)
  354 + *
  355 + * lcx ist eine Konstante die die gr&ouml;&szlig;e der Sichtfeldes
  356 + * beschreibt. Diese Funktion ermittelt diese Konstante anhand von
  357 + * Werten zwischen 10 und 170 wobei das volle menschliche Sichtfeld
  358 + * einem Wert von 100 entspricht. 10 ist extrem Tele und 170 extrem
  359 + * Weitwinkel.
  360 + *
  361 + * \param angle Winkel f&uuml;rs Sichtfeld (zwischen 10 und 170)
  362 + *
  363 + * \pre 10 < angel < 170
  364 + */
  365 + void set_lens_coverage(double angle) {
  366 + lcxa=angle;
  367 +
  368 + if(lcxa>170) lcxa=170;
  369 + if(lcxa<10) lcxa=10;
  370 +
  371 + lcx=0.5*(1/tan(lcxa*M_PI/(180.0*2.0)));
  372 + }
  373 +
  374 + const Mmn<double>& cam_trans_mat(void) {
  375 + cam_trans=t_mat.inv_Ad();
  376 +
  377 + if(cam_trans.is_null())
  378 + cam_trans=t_mat.gauss(INVERSE);
  379 +
  380 + return cam_trans;
  381 + }
  382 +
  383 + double get_lcx(void) const {
  384 + return lcx;
  385 + }
  386 +
  387 + double get_sw(void) const {
  388 + return sw;
  389 + }
  390 +
  391 + double get_sh(void) const {
  392 + return sh;
  393 + }
  394 +
  395 + double get_ph_ar(void) const {
  396 + return ph_ar;
  397 + }
  398 +
  399 + double get_sy(void) const {
  400 + return sy;
  401 + }
  402 +
  403 + double get_dz(void) const {
  404 + return dz;
  405 + }
  406 +};
  407 +
  408 +/**
  409 + * \brief Das eigentliche Programm
  410 + *
  411 + * Hier werden alle Teile zu einem kleinen Testprogramm zusammengef&uuml;gt.
  412 + */
  413 +class app {
  414 + private:
  415 + canvas* scr; //!< Der Canvas auf dem gezeichnet wird
  416 + rasterizer* ras; //!< Der Rasterizer zu dem \ref scr
  417 + dispatcher* d; //!< Der X11-Dispatcher
  418 + disp_manager manager; //!< Der Dispatcher-Manager
  419 +
  420 + polyeder_movable p; //!< erster Polyeder
  421 + polyeder_movable p2; //!< zweiter Polyeder
  422 + polyeder_movable p3; //!< dritter Polyeder
  423 + polyeder_movable p4; //!< und weils so lustig ist noch einer
  424 +
  425 + camera cam;
  426 + direct_light li;
  427 + direct_light li2;
  428 + ambient_light li3;
  429 +
  430 + double winkel;
  431 + int stepping;
  432 + double cam_winkel;
  433 + int cam_stepping;
  434 + double li_winkel;
  435 + int li_stepping;
  436 + double li2_winkel;
  437 + int li2_stepping;
  438 +
  439 + double clip_front;
  440 +
  441 + unsigned secs, secs_tmp;
  442 + unsigned short ms;
  443 +
  444 + /**
  445 + * \brief Bringt den Canvas auf den Bildschirm
  446 + *
  447 + * Dies ist eine Callback-Methode die zu jedem expose-event u.&auml;.
  448 + * aufgerufen wird um den Inhalt des Canvas auf das Fenster zu
  449 + * &uuml;bertragen. Diese Methode wird ausschlie&szlig;lich vom
  450 + * Dispatcher \ref d aufgerufen.
  451 + *
  452 + * \param es Die Quelle des Events, in diesem Fall also der canvas
  453 + * \param key Wird nicht benutzt
  454 + *
  455 + * \pre redraw mu&szlig; als callback in \ref d registriert sein.
  456 + * \pre \ref scr mu&szlig; ein g&uuml;ltiger canvas sein.
  457 + */
  458 + void redraw(event_source* es, void* key) {
  459 + char buffer[10]="\0";
  460 +
  461 + sprintf(buffer, "%02d:%03d", secs, ms);
  462 +
  463 + scr->blit_screen();
  464 + scr->draw_text(5,15,buffer,strlen(buffer));
  465 + //usleep(10);
  466 + }
  467 +
  468 + /**
  469 + * \brief verarbeitet Tastendr&uuml;cke im Canvas
  470 + *
  471 + * Dies ist eine Callback-Methode die zu jedem keypress-event
  472 + * im Canvas aufgerufen wird. Hier&uuml;ber ist es m&ouml;glich
  473 + * das Programm zu steuern. Diese Methode wird ausschlie&szlig;lich
  474 + * vom Dispatcher \ref d aufgerufen.
  475 + *
  476 + * \param es Die Quelle des Events, in diesem Fall also der Canvas
  477 + * \param key Der Ascii-Code der gedr&uuml;ckten Taste.
  478 + *
  479 + * \pre exitOnEsc mu&szlig; als callback in \ref d registriert sein.
  480 + * \pre \ref scr mu&szlig; ein g&uuml;ltiger canvas sein.
  481 + *
  482 + * \post Falls ESC gedr&uuml;ckt wurde -> Programmende
  483 + * \post Falls s oder S gedr&uuml;ckt wurde Dispatcher anhalten
  484 + * \post Falls c oder C gedr%uuml;ckt wurde Dispatcher starten
  485 + */
  486 + void exitOnEsc(event_source* es, void* key) {
  487 + switch (*(char*)key) {
  488 + case 27:
  489 + d->trigger_event(Stop);
  490 + case 'x':
  491 + case 'X':
  492 + d->halt();
  493 + break;
  494 + case 'c':
  495 + case 'C':
  496 + d->cont();
  497 + break;
  498 + case '+':
  499 + cam_stepping=(cam_stepping+1)%11;
  500 + break;
  501 + case '-':
  502 + cam_stepping=cam_stepping>0?(cam_stepping-1)%11:10;
  503 + break;
  504 + case 'q':
  505 + case 'Q':
  506 + clip_front=clip_front>0?clip_front-10:0;
  507 + break;
  508 + case 'w':
  509 + case 'W':
  510 + clip_front=clip_front<100?clip_front+10:100;
  511 + break;
  512 + case 'r':
  513 + case 'R':
  514 + li_stepping=(li_stepping+1)%11;
  515 + break;
  516 + case 'e':
  517 + case 'E':
  518 + li_stepping=li_stepping>0?(li_stepping-1)%11:10;
  519 + break;
  520 + case 'z':
  521 + case 'Z':
  522 + li2_stepping=(li2_stepping+1)%11;
  523 + break;
  524 + case 't':
  525 + case 'T':
  526 + li2_stepping=li2_stepping>0?(li2_stepping-1)%11:10;
  527 + break;
  528 + case 'd':
  529 + case 'D':
  530 + stepping=(stepping+1)%11;
  531 + break;
  532 + case 's':
  533 + case 'S':
  534 + stepping=0;
  535 + break;
  536 + case 'a':
  537 + case 'A':
  538 + stepping=stepping>0?(stepping-1)%11:10;
  539 + default:
  540 + break;
  541 + }
  542 + }
  543 +
  544 + /**
  545 + * \brief Rotiert, projeziert und zeichnet die drei Polyeder
  546 + * \ref p, \ref p2 und \ref p3
  547 + *
  548 + * Hier werden mit Hilfe der Klassen aus \ref Mmn.h, \ref sin_cos.h und
  549 + * \ref V_K4.h die Polyeder gedreht, skaliert, projeziert und
  550 + * schlie&szlig;lich mit Hilfe der Methoden des Rasterizers \ref ras
  551 + * auch noch gezeichnet. Am ende wird dann ein Expose-Event
  552 + * ausgel&ouml;st, damit die &Auml;nderungen auch am Bildschirm
  553 + * sichtbar werden.
  554 + *
  555 + * \note Im Moment wir rotate auch über disp_x11 aufgerufen, das ist
  556 + * nicht notwendig, und eigentlich sogar falsch, denn es wird überhaupt
  557 + * nicht auf ein X-Event reagiert. Was ich brauche ist ein weiteren
  558 + * Dispatcher (disp_app) der Application-Events aufführt,
  559 + * Die Rotation müsste dann quasi im idle-Fall ausgeführt werden.
  560 + * Es würde sicherlich Sinn machen diesen dispatcher dann irgendwie
  561 + * als thread zu implementieren. Immerhin ist X ja auch ein eigener
  562 + * Prozess. (OK, der Vergleich hinkt, da ich die XEvents auch im
  563 + * Hauptprozess abarbeite.
  564 + *
  565 + * \param es Die Quelle des Events, in diesem Fall also der canvas
  566 + * \param dummy Wird nicht benutzt
  567 + *
  568 + * \pre redraw mu&szlig; als callback in \ref d registriert sein.
  569 + * \pre \ref scr mu&szlig; ein g&uuml;ltiger canvas sein.
  570 + *
  571 + * \post Die Polyeder sind transformiert und auf dem Canvas
  572 + * gezeichnet. Ein Expose-Event wurde ausgel&ouml;st.
  573 + */
  574 + void rotate(event_source* es, void* dummy) {
  575 + struct timeb tb1;
  576 + struct timeb tb2;
  577 +
  578 + ftime(&tb1);
  579 +
  580 + winkel=WINKEL(winkel+stepping);
  581 +
  582 + cam_winkel=WINKEL(cam_winkel+cam_stepping);
  583 + li_winkel=WINKEL(li_winkel-li_stepping);
  584 + li2_winkel=WINKEL(li2_winkel+li2_stepping);
  585 +
  586 + container<polygon> po_list, po_list_zclipped;
  587 +
  588 + //if(winkel==3)
  589 + // sleep(10);
  590 +
  591 + p.rotate_im_g_x(45);
  592 + p.translate_im_global(-30.0*sin(RAD(winkel)),
  593 + 5.0*cos(RAD(winkel)),
  594 + 10.0*cos(RAD(winkel)));
  595 + p.rotate_im_vfw(WINKEL(2*winkel));
  596 +
  597 + p2.translate_im_global(5.0*cos(RAD(winkel)),
  598 + 20.0*sin(RAD(winkel)),
  599 + 20.0*cos(RAD(winkel)));
  600 + p2.rotate_im_l_z(WINKEL(winkel));
  601 + p2.rotate_im_l_y(WINKEL(360-winkel));
  602 + p2.translate_im_global(0,0,-5);
  603 +
  604 + //p3.translate_im_global(0,0,5);
  605 +
  606 + p4.translate_im_global(0,0,15);
  607 + p4.rotate_im_g_x(WINKEL(winkel));
  608 + p4.rotate_im_g_y(WINKEL(winkel));
  609 + p4.translate_im_global(0,0,5);
  610 +
  611 + cam.translate_im_global(0,0,-60);
  612 + cam.rotate_im_g_y(WINKEL(-cam_winkel));
  613 + cam.rotate_im_axis(WINKEL(cam_winkel),
  614 + vertex(1,0,1,COORD), vertex(0,0,0,COORD));
  615 +
  616 + li.translate_im_global(0,0,-10);
  617 + li.rotate_im_g_y(WINKEL(45.0));
  618 + li.rotate_im_axis(WINKEL(li_winkel),
  619 + vertex(1,0,-1,COORD), vertex(0,0,0,COORD));
  620 +
  621 + li2.translate_im_global(0,0,-10);
  622 + li2.rotate_im_g_x(WINKEL(li2_winkel));
  623 +
  624 + Mmn<double> ctm(cam.cam_trans_mat());
  625 +
  626 + p.move_im(ctm);
  627 + p2.move_im(ctm);
  628 + p3.move_im(ctm);
  629 + p4.move_im(ctm);
  630 + li.move_im(ctm);
  631 + li2.move_im(ctm);
  632 +
  633 + /* p.transform(1);
  634 + p2.transform(1);
  635 + p3.transform(1);
  636 + p4.transform(1);
  637 +
  638 + cam.transform(1); */
  639 +
  640 + // Zu Anfang reicht es die Vertexe für die Objektposition und
  641 + // die Normalenvertexe zu transformieren, dann kommt das
  642 + // backface culling und nur wenn ein polygon wirklich gezeichnet
  643 + // wird mache ich die letzten transformationen und die
  644 + // projektion.
  645 + p.transform_normals(1);
  646 + p2.transform_normals(1);
  647 + p3.transform_normals(1);
  648 + p4.transform_normals(1);
  649 +
  650 + p.movable::transform(1);
  651 + p2.movable::transform(1);
  652 + p3.movable::transform(1);
  653 + p4.movable::transform(1);
  654 +
  655 + li.transform(1);
  656 + li2.transform(1);
  657 +
  658 + /* p.project_2d(cam.get_lcx(), cam.get_sw(), cam.get_sh(),
  659 + cam.get_ph_ar(), cam.get_sy(), 2);
  660 + p2.project_2d(cam.get_lcx(), cam.get_sw(), cam.get_sh(),
  661 + cam.get_ph_ar(), cam.get_sy(), 2);
  662 + p3.project_2d(cam.get_lcx(), cam.get_sw(), cam.get_sh(),
  663 + cam.get_ph_ar(), cam.get_sy(), 2);
  664 + p4.project_2d(cam.get_lcx(), cam.get_sw(), cam.get_sh(),
  665 + cam.get_ph_ar(), cam.get_sy(), 2); */
  666 +
  667 + // Ich muss nach einem verdammt guten Weg suchen herauszufinden
  668 + // zu welchem polyeder ein polygon gehoert, ich denke das beste ist
  669 + // einen pointer auf den polyeder im polygon zu speichern wenn
  670 + // es einem polyeder zugeordnet wird.
  671 + vertex view, normal, center, norm_v;
  672 +
  673 + for(unsigned i=0; i<p.card(); i++) {
  674 + view=p.get_vrp();
  675 +
  676 + center=p[i].center_p();
  677 + normal=p[i].normal_p();
  678 + norm_v=normal-center;
  679 +
  680 + if(((norm_v%view)/(norm_v.betr()*view.betr())) < 0.0) {
  681 + po_list[po_list.card()]=p[i];
  682 + po_list[po_list.card()-1].transform(p.get_t_mat(), 1);
  683 + }
  684 + }
  685 +
  686 + for(unsigned i=0; i<p2.card(); i++) {
  687 + view=p2.get_vrp();
  688 +
  689 + center=p2[i].center_p();
  690 + normal=p2[i].normal_p();
  691 + norm_v=normal-center;
  692 +
  693 + if(((norm_v%view)/(norm_v.betr()*view.betr())) < 0.0) {
  694 + po_list[po_list.card()]=p2[i];
  695 + po_list[po_list.card()-1].transform(p2.get_t_mat(), 1);
  696 + }
  697 + }
  698 +
  699 + for(unsigned i=0; i<p3.card(); i++) {
  700 + //hier kein backface-culling...
  701 +
  702 + //view=p3.get_vrp();
  703 +
  704 + //center=p3[i].center_p();
  705 + //normal=p3[i].normal_p();
  706 + //norm_v=normal-center;
  707 +
  708 + //if(((norm_v%view)/(norm_v.betr()*view.betr())) < 0.0) {
  709 + po_list[po_list.card()]=p3[i];
  710 + po_list[po_list.card()-1].transform(p3.get_t_mat(), 1);
  711 + //}
  712 + }
  713 +
  714 + for(unsigned i=0; i<p4.card(); i++) {
  715 + view=p4.get_vrp();
  716 +
  717 + center=p4[i].center_p();
  718 + normal=p4[i].normal_p();
  719 + norm_v=normal-center;
  720 +
  721 + if(((norm_v%view)/(norm_v.betr()*view.betr())) < 0.0) {
  722 + po_list[po_list.card()]=p4[i];
  723 + po_list[po_list.card()-1].transform(p4.get_t_mat(), 1);
  724 + }
  725 + }
  726 +
  727 + po_list.sort(compf);
  728 +
  729 + for(unsigned i=0; i<po_list.card(); i++) {
  730 + po_list_zclipped[i]=po_list[i].clip_front_z(clip_front);
  731 + }
  732 +
  733 + ras->clear_buffer();
  734 +
  735 + double normal_X[6];
  736 + double normal_Y[6];
  737 +
  738 + for(unsigned i=0; i<po_list.card(); i++) {
  739 + int idx;
  740 +
  741 + if((idx=p3.contains(po_list[i])) >= 0) {
  742 + unsigned long col;
  743 +
  744 + vertex center=po_list[i].center_p();
  745 + vertex normal=po_list[i].normal_p();
  746 + vertex norm_v=normal-center;
  747 +
  748 +
  749 + if(idx==1)
  750 + col=scr->get_color(0,0,255);
  751 + else
  752 + col=scr->get_color(0,255,255);
  753 +
  754 + vertex light(li.get_direction());
  755 +
  756 + unsigned in=0, in_tmp;
  757 + double intense=(norm_v.norm()%light.norm())*-1;
  758 + intense=intense<0.02?0.02:intense;
  759 + intense=intense>1.0?1.0:intense;
  760 +
  761 + in_tmp=(unsigned)(intense*li.get_intensity());
  762 + in=in_tmp>in?in_tmp:in;
  763 +
  764 + light=li2.get_direction();
  765 +
  766 + intense=(norm_v.norm()%light.norm())*-1;
  767 + intense=intense<0.02?0.02:intense;
  768 + intense=intense>1.0?1.0:intense;
  769 +
  770 + in_tmp=(unsigned)(intense*li2.get_intensity());
  771 + in=in_tmp>in?in_tmp:in;
  772 + in_tmp=(unsigned)(li3.get_intensity());
  773 + in=in_tmp>in?in_tmp:in;
  774 +
  775 + scr->light_native(&col, in);
  776 +
  777 + if(po_list_zclipped[i].card() >= 3) {
  778 + po_list_zclipped[i].project_2d(cam.get_lcx(), cam.get_sw(),
  779 + cam.get_sh(), cam.get_ph_ar(),
  780 + cam.get_sy(), 2);
  781 + ras->draw_polygon_flat(po_list_zclipped[i], col);
  782 + }
  783 + }
  784 +
  785 + if((idx=p4.contains(po_list[i])) >= 0) {
  786 + unsigned long col=scr->get_color(0,0,255);
  787 +
  788 + vertex center=po_list[i].center_p();
  789 + vertex normal=po_list[i].normal_p();
  790 + vertex norm_v=normal-center;
  791 +
  792 + vertex light(li.get_direction());
  793 +
  794 + unsigned in=0, in_tmp;
  795 + double intense=(norm_v.norm()%light.norm())*-1;
  796 + intense=intense<0.02?0.02:intense;
  797 + intense=intense>1.0?1.0:intense;
  798 +
  799 + in_tmp=(unsigned)(intense*li.get_intensity());
  800 + in=in_tmp>in?in_tmp:in;
  801 +
  802 + light=li2.get_direction();
  803 +
  804 + intense=(norm_v.norm()%light.norm())*-1;
  805 + intense=intense<0.02?0.02:intense;
  806 + intense=intense>1.0?1.0:intense;
  807 +
  808 + in_tmp=(unsigned)(intense*li2.get_intensity());
  809 + in=in_tmp>in?in_tmp:in;
  810 + in_tmp=(unsigned)(li3.get_intensity());
  811 + in=in_tmp>in?in_tmp:in;
  812 +
  813 + scr->light_native(&col, in);
  814 +
  815 + if(po_list_zclipped[i].card() >= 3) {
  816 + po_list_zclipped[i].project_2d(cam.get_lcx(), cam.get_sw(),
  817 + cam.get_sh(), cam.get_ph_ar(),
  818 + cam.get_sy(), 2);
  819 + ras->draw_polygon_flat(po_list_zclipped[i], col);
  820 + //ras->draw_polygon_wire(po_list_zclipped[i],
  821 + // scr->get_color(255, 255, 255));
  822 + }
  823 + }
  824 +
  825 + if((idx=p.contains(po_list[i])) >= 0) {
  826 + unsigned long col=scr->get_color(255,0,0);
  827 +
  828 + vertex center=po_list[i].center_p();
  829 + vertex normal=po_list[i].normal_p();
  830 + vertex norm_v=normal-center;
  831 +
  832 + vertex light(li.get_direction());
  833 +
  834 + unsigned in=0, in_tmp;
  835 + double intense=(norm_v.norm()%light.norm())*-1;
  836 + intense=intense<0.02?0.02:intense;
  837 + intense=intense>1.0?1.0:intense;
  838 +
  839 + in_tmp=(unsigned)(intense*li.get_intensity());
  840 + in=in_tmp>in?in_tmp:in;
  841 +
  842 + light=li2.get_direction();
  843 +
  844 + intense=(norm_v.norm()%light.norm())*-1;
  845 + intense=intense<0.02?0.02:intense;
  846 + intense=intense>1.0?1.0:intense;
  847 +
  848 + in_tmp=(unsigned)(intense*li2.get_intensity());
  849 + in=in_tmp>in?in_tmp:in;
  850 + in_tmp=(unsigned)(li3.get_intensity());
  851 + in=in_tmp>in?in_tmp:in;
  852 +
  853 + scr->light_native(&col, in);
  854 +
  855 + center.project_2d(cam.get_lcx(), cam.get_sw(),
  856 + cam.get_sh(), cam.get_ph_ar(),
  857 + cam.get_sy(),
  858 + center.get_trans_stage()+1);
  859 + normal.project_2d(cam.get_lcx(), cam.get_sw(),
  860 + cam.get_sh(), cam.get_ph_ar(),
  861 + cam.get_sy(),
  862 + center.get_trans_stage()+1);
  863 +
  864 + if(po_list_zclipped.card() >= 3) {
  865 + po_list_zclipped[i].project_2d(cam.get_lcx(), cam.get_sw(),
  866 + cam.get_sh(), cam.get_ph_ar(),
  867 + cam.get_sy(), 2);
  868 + ras->draw_polygon_flat(po_list_zclipped[i], col);
  869 + //ras->draw_polygon_wire(po_list_zclipped[i],
  870 + // scr->get_color(255, 255, 255));
  871 + ras->line(center[X], center[Y], normal[X], normal[Y],
  872 + scr->get_color(0, 0, 0));
  873 + }
  874 + }
  875 +
  876 + if((idx=p2.contains(po_list[i])) >= 0) {
  877 + unsigned long col=scr->get_color(0,255,0);
  878 +
  879 + vertex center=po_list[i].center_p();
  880 + vertex normal=po_list[i].normal_p();
  881 + vertex norm_v=normal-center;
  882 +
  883 + vertex light(li.get_direction());
  884 +
  885 + unsigned in=0, in_tmp;
  886 + double intense=(norm_v.norm()%light.norm())*-1;
  887 + intense=intense<0.02?0.02:intense;
  888 + intense=intense>1.0?1.0:intense;
  889 +
  890 + in_tmp=(unsigned)(intense*li.get_intensity());
  891 + in=in_tmp>in?in_tmp:in;
  892 +
  893 + light=li2.get_direction();
  894 +
  895 + intense=(norm_v.norm()%light.norm())*-1;
  896 + intense=intense<0.02?0.02:intense;
  897 + intense=intense>1.0?1.0:intense;
  898 +
  899 + in_tmp=(unsigned)(intense*li2.get_intensity());
  900 + in=in_tmp>in?in_tmp:in;
  901 + in_tmp=(unsigned)(li3.get_intensity());
  902 + in=in_tmp>in?in_tmp:in;
  903 +
  904 + scr->light_native(&col, in);
  905 +
  906 + center.project_2d(cam.get_lcx(), cam.get_sw(), cam.get_sh(),
  907 + cam.get_ph_ar(), cam.get_sy(),
  908 + center.get_trans_stage()+1);
  909 + normal.project_2d(cam.get_lcx(), cam.get_sw(), cam.get_sh(),
  910 + cam.get_ph_ar(), cam.get_sy(),
  911 + center.get_trans_stage()+1);
  912 +
  913 + if(po_list_zclipped[i].card() >= 3) {
  914 + po_list_zclipped[i].project_2d(cam.get_lcx(), cam.get_sw(),
  915 + cam.get_sh(), cam.get_ph_ar(),
  916 + cam.get_sy(), 2);
  917 + ras->draw_polygon_flat(po_list_zclipped[i], col);
  918 + //ras->draw_polygon_wire(po_list_zclipped[i],
  919 + // scr->get_color(255, 255, 255));
  920 + ras->line(center[X], center[Y], normal[X], normal[Y],
  921 + scr->get_color(0, 0, 0));
  922 + }
  923 + }
  924 + }
  925 +
  926 + //ras->draw_polyeder_wire(p, scr->get_color(255,255,255));
  927 + //ras->draw_polyeder_wire(p2, scr->get_color(255,255,255));
  928 +
  929 + p.reset();
  930 + p2.reset();
  931 + p3.reset();
  932 + p4.reset();
  933 + cam.reset();
  934 + li.reset();
  935 + li2.reset();
  936 +
  937 + ftime(&tb2);
  938 +
  939 + secs_tmp=tb2.time-tb1.time;
  940 + ms=(secs_tmp*1000+tb2.millitm)-tb1.millitm;
  941 + secs=(secs_tmp>0)?ms/(secs_tmp*1000):0;
  942 + ms=(secs_tmp>0)?ms%(secs_tmp*1000):ms;
  943 +
  944 + d->trigger_event(Draw);
  945 + }
  946 +
  947 + public:
  948 + /**
  949 + * \brief Konstruktor
  950 + *
  951 + * Alle Grundlegenden Initialisierungen. Canvas, Dispatcher und
  952 + * Rasterizer erzeugen. Callbacks registrieren und
  953 + * Polyeder erzeugen. Eckwerte f&uuml;r die 2D-Projektion festlegen.
  954 + */
  955 + app() {
  956 + // Der factory_manager erzeugt mir den gew&uuml;nschten
  957 + // Canvas und Dispatcher.
  958 + factory_manager f;
  959 +
  960 + // Erzeuge den Canvas, Dispatcher und Rasterizer
  961 + scr=f.canvas_f->create(400, 300);
  962 + d=f.dispatcher_f->create(scr);
  963 + ras=scr->create_rasterizer();
  964 +
  965 + // Registriere die Callbacks und trage Dispatcher in Manager ein
  966 + d->register_callback(Key, mk_callback(*this, &app::exitOnEsc));
  967 + d->register_callback(Idle, mk_callback(*this, &app::rotate));
  968 + d->register_callback(Draw, mk_callback(*this, &app::redraw));
  969 +
  970 + manager[0]=d;
  971 + d->register_callback(Stop,
  972 + mk_callback(manager, &disp_manager::stop));
  973 +
  974 + // Dann wolln wir die cam mal initilisieren.
  975 + cam=camera(*ras, 50.0);
  976 + li2.set_intensity(127);
  977 + li3.set_intensity(40);
  978 +
  979 + // zuerst werden alle n&ouml;tigen Vertexe erzeugt
  980 + vertex v[]={vertex(5,5,5,1),
  981 + vertex(5,-5,5,1),
  982 + vertex(-5,-5,5,1),
  983 + vertex(-5,5,5,1),
  984 + vertex(5,5,-5,1),
  985 + vertex(5,-5,-5,1),
  986 + vertex(-5,-5,-5,1),
  987 + vertex(-5,5,-5,1)};
  988 +
  989 + // und in einer Vertexliste gespeicher.
  990 + vertex_list vl(v, 8);
  991 +
  992 + // ein Hilfsarray erzeugt um damit
  993 + unsigned v_idx[][4]={{3,2,1,0}, // hinten
  994 + {0,1,5,4}, // rechts
  995 + {4,5,6,7}, // vorne
  996 + {7,6,2,3}, // links
  997 + {4,0,3,7}, // oben
  998 + {1,5,6,2}}; // unten
  999 +
  1000 + // die Polygone zu definieren.
  1001 + // (Der letzte Parameter ist die Vertexliste die das Polygon
  1002 + // nutzen soll. Hier kann ich NULL nehmen, da sie beim erzeugen
  1003 + // der Polyeders auf dessen Vertexliste gesetzt werden.
  1004 + // (siehe unten))
  1005 + /*polygon_movable pa[]={
  1006 + polygon_movable((unsigned*)v_idx[0], 4, NULL),
  1007 + polygon_movable((unsigned*)v_idx[1], 4, NULL),
  1008 + polygon_movable((unsigned*)v_idx[2], 4, NULL),
  1009 + polygon_movable((unsigned*)v_idx[3], 4, NULL),
  1010 + polygon_movable((unsigned*)v_idx[4], 4, NULL),
  1011 + polygon_movable((unsigned*)v_idx[5], 4, NULL)};*/
  1012 + polygon pa[]={
  1013 + polygon((unsigned*)v_idx[0], 4, NULL),
  1014 + polygon((unsigned*)v_idx[1], 4, NULL),
  1015 + polygon((unsigned*)v_idx[2], 4, NULL),
  1016 + polygon((unsigned*)v_idx[3], 4, NULL),
  1017 + polygon((unsigned*)v_idx[4], 4, NULL),
  1018 + polygon((unsigned*)v_idx[5], 4, NULL)};
  1019 +
  1020 +
  1021 + // Jetzt definieren wir mit der oben erzeugten Vertexlist und
  1022 + // dem Array aus Polygonen 2 Polyeder, die wir beide vom
  1023 + // Ursprung auf der Z-Achse weg bewegen.
  1024 + p=polyeder(pa, 6, vl);
  1025 + p2=polyeder(pa, 6, vl);
  1026 + p4=polyeder(pa, 6, vl);
  1027 +
  1028 + p[2].set_id("DEBUG");
  1029 + cout << "BLA: " << p[2].get_id() << "\n";
  1030 +
  1031 + polygon pa3[]={polygon((unsigned*)v_idx[0], 4, NULL),
  1032 + polygon((unsigned*)v_idx[2], 4, NULL)};
  1033 + p3=polyeder(pa3, 2, vl);
  1034 +
  1035 + winkel=0;
  1036 + stepping=0;
  1037 + cam_winkel=0;
  1038 + cam_stepping=0;
  1039 + li_winkel=WINKEL(-45.0);
  1040 + li_stepping=0;
  1041 + li2_winkel=WINKEL(90.0);
  1042 + li2_stepping=0;
  1043 + clip_front=0;
  1044 + //halt=false;
  1045 + }
  1046 +
  1047 + /**
  1048 + * \brief Destruktor
  1049 + *
  1050 + * freigeben und entfernen alles dynamisch erzeugten Elemente.
  1051 + */
  1052 + ~app() {
  1053 + delete ras;
  1054 + delete d;
  1055 + delete scr;
  1056 + }
  1057 +
  1058 + /**
  1059 + * \brief startet den Manager und damit das Programm.
  1060 + */
  1061 + void go(void) {
  1062 + manager.start();
  1063 + }
  1064 +};
  1065 +
  1066 +int main(int argc, char* argv[]) {
  1067 + app a;
  1068 +
  1069 + a.go();
  1070 +
  1071 + // cout << "jokus\n";
  1072 +
  1073 + return 0;
  1074 +}
  1075 +
  1076 +#endif
  1 +CC=gcc
  2 +CPP=g++
  3 +#CFLAGS=-ggdb
  4 +CXXFLAGS=
  5 +MAKE=make
  6 +
  7 +OBJECTS=
  8 +
  9 +%.o: %.cpp
  10 + $(CPP) $(CFLAGS) $(CXXFLAGS) -c $*.cpp
  11 +
  12 +.PHONY : all clean
  13 +
  14 +all: $(OBJECTS)
  15 +
  16 +clean:
  17 + @rm -f *.o
  1 +/**
  2 + * \file container.h
  3 + *
  4 + * \brief Definition eines Container-Templates
  5 + *
  6 + * Hiermit k&ouml;nnen alle m&ouml;glichen Daten organisiert werden.
  7 +
  8 + * \author Georg Steffers <georg@steffers.org> [gs]
  9 + *
  10 + * \date 04.12.2003
  11 + *
  12 + * \version ..2002 [gs]: erste funktionierende Implementation
  13 + * \version 04.12.2003 [gs]: beginn der Dokumentation via doxygen
  14 + * \version 19.12.2003 [gs]: <ul><li>
  15 + * Vergleichsoperator hinzugef&uuml;gt.
  16 + * </li><li>
  17 + * die Methode contains hinzugefügt, die
  18 + * &uuml;ber den Vergleichsoperator eines
  19 + * Elements pr&uuml;ft ob es in diesem Container
  20 + * existiert.
  21 + * </li></ul>
  22 + */
  23 +
  24 +/*
  25 + * Copyright (C)2003 Georg Steffers
  26 + *
  27 + * This program is free software; you can redistribute it and/or modify
  28 + * it under the terms of the GNU General Public License as published by
  29 + * the Free Software Foundation; either version 2 of the License, or
  30 + * (at your option) any later version.
  31 + *
  32 + * This program is distributed in the hope that it will be useful,
  33 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  34 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  35 + * GNU General Public License for more details.
  36 + *
  37 + * You should have received a copy of the GNU General Public License
  38 + * along with this program; if not, write to the Free Software
  39 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  40 + */
  41 +
  42 +#ifndef __container_h__
  43 +#define __container_h__
  44 +
  45 +#include <stdlib.h>
  46 +
  47 +template <class C>
  48 +class container {
  49 + protected:
  50 + C* content;
  51 + unsigned count;
  52 +
  53 + public:
  54 + container();
  55 + container(const C& c);
  56 + container(const C* c, unsigned co);
  57 + container(const container<C>& c);
  58 + virtual ~container();
  59 +
  60 + virtual const container<C>& operator=(const container<C>& c);
  61 + virtual bool operator==(const container<C>& c) const {
  62 + if(count==c.count) {
  63 + for(unsigned i=0; i<count; i++)
  64 + if(!(content[i]==c[i]))
  65 + return false;
  66 + }
  67 + else
  68 + return false;
  69 +
  70 + return true;
  71 + }
  72 +
  73 + const C& operator[](unsigned index) const;
  74 + C& operator[](unsigned index);
  75 +
  76 + //! Pr&uuml;ft ob ein Element in dem Container ist.
  77 + //! Gibt -1 zur&uuml;ck falls nicht, ansonsten den index an dem
  78 + //! sich das Element vefindet
  79 + int contains(const C& c) {
  80 + for(unsigned i=0; i<count; i++)
  81 + if(content[i]==c)
  82 + return i;
  83 +
  84 + return -1;
  85 + }
  86 +
  87 + void sort(int (*comp)(const void*, const void*)) {
  88 + qsort(content, count, sizeof(C), comp);
  89 + }
  90 +
  91 + void resize(unsigned size);
  92 + unsigned card(void) const { return count; }
  93 + virtual void insert(unsigned idx, const C& value);
  94 +};
  95 +
  96 +#include "container_tpl.h"
  97 +
  98 +#endif // __container_h__
  1 +/**
  2 + * \file container_tpl.h
  3 + *
  4 + * \brief ein Template das als Behälter für alles mögliche dient.
  5 + *
  6 + * \author Georg Steffers <georg@steffers.org> [gs]
  7 + *
  8 + * \date 16.12.2003
  9 + *
  10 + * \version ..2002 [gs]: erste Implementation
  11 + * \version 16.12.2003 [gs]: <ul><li>
  12 + * Beginn der Dokumentaion mit Doxygen
  13 + * </li><li>
  14 + * Einige &Auml;nderungen, so das
  15 + * content in einem leeren container
  16 + * NULL ist und dann entsprechen auch
  17 + * nicht alle Aktionen mit diesem
  18 + * container m&ouml;glich sind.
  19 + * </li></ul>
  20 + */
  21 +
  22 +/*
  23 + * Copyright (C)2003 Georg Steffers
  24 + *
  25 + * This program is free software; you can redistribute it and/or modify
  26 + * it under the terms of the GNU General Public License as published by
  27 + * the Free Software Foundation; either version 2 of the License, or
  28 + * (at your option) any later version.
  29 + *
  30 + * This program is distributed in the hope that it will be useful,
  31 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  32 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  33 + * GNU General Public License for more details.
  34 + *
  35 + * You should have received a copy of the GNU General Public License
  36 + * along with this program; if not, write to the Free Software
  37 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  38 + */
  39 +
  40 +using namespace std;
  41 +
  42 +#include <cstring>
  43 +#include "container.h"
  44 +
  45 +template <class C>
  46 +container<C>::container() : content(NULL), count(0) {
  47 + //content=new C[1];
  48 +}
  49 +
  50 +template <class C>
  51 +container<C>::container(const C& c) : count(1) {
  52 + content=new C[1];
  53 + content[0]=c;
  54 +}
  55 +
  56 +template <class C>
  57 +container<C>::container(const C* c, unsigned co) : count(co) {
  58 + if(count > 0)
  59 + content=new C[count];
  60 + else
  61 + content=NULL;
  62 +
  63 + for(unsigned i=0; i<count; i++)
  64 + content[i]=c[i];
  65 +}
  66 +
  67 +template <class C>
  68 +container<C>::container(const container<C>& c) : count(c.count) {
  69 + if(count > 0)
  70 + content=new C[count];
  71 + else
  72 + content=NULL;
  73 +
  74 + for(unsigned i=0; i<count; i++)
  75 + content[i]=c.content[i];
  76 +}
  77 +
  78 +template <class C>
  79 +container<C>::~container() {
  80 + if(content) {
  81 + delete [] content;
  82 + content=NULL;
  83 + }
  84 + count=0;
  85 +}
  86 +
  87 +template <class C>
  88 +const container<C>& container<C>::operator=(const container<C>& c) {
  89 + if(this==&c)
  90 + return *this;
  91 +
  92 + if(count != c.count) {
  93 + delete [] content;
  94 + if(c.count > 0)
  95 + content=new C[c.count];
  96 + else
  97 + content=NULL;
  98 + }
  99 +
  100 + count=c.count;
  101 +
  102 + for(unsigned i=0; i<count; i++)
  103 + content[i]=c.content[i];
  104 +
  105 + return *this;
  106 +}
  107 +
  108 +template <class C>
  109 +const C& container<C>::operator[](unsigned index) const {
  110 + if(index+1 > count)
  111 + return content[0];
  112 +
  113 + return content[index];
  114 +}
  115 +
  116 +template <class C>
  117 +C& container<C>::operator[](unsigned index) {
  118 + if(index+1 > count) {
  119 + C* content_tmp=new C[index+1];
  120 +
  121 + for(unsigned i=0; i<count; i++)
  122 + content_tmp[i]=content[i];
  123 +// memcpy(content_tmp, content, count*sizeof(C));
  124 +
  125 + delete [] content;
  126 + content=content_tmp;
  127 + count=index+1;
  128 + }
  129 +
  130 + return content[index];
  131 +}
  132 +
  133 +// WARNUNG!!! Diese funktion verkleiner auch ohne weitern check. d.h. ist
  134 +// size < count, dann verliert man alle Einträge >size.
  135 +template <class C>
  136 +void container<C>::resize(unsigned size) {
  137 + C* content_tmp;
  138 +
  139 + if(size>0) {
  140 + content_tmp=new C[size];
  141 +
  142 + for(unsigned i=0; i<size<count?size:count; i++)
  143 + content_tmp[i]=content[i];
  144 + }
  145 + else
  146 + content_tmp=NULL;
  147 +
  148 + delete [] content;
  149 + content=content_tmp;
  150 + count=size;
  151 +}
  152 +
  153 +template <class C>
  154 +void container<C>::insert(unsigned idx, const C& value) {
  155 + C* content_tmp=new C[count+1];
  156 +
  157 + memcpy(content_tmp, content, idx*sizeof(C));
  158 + content_tmp[idx]=value;
  159 +
  160 + for(unsigned i=0; i<count; i++)
  161 + content_tmp[i]=content[i];
  162 +// memcpy(&content_tmp[idx+1], &content[idx], (count-idx)*sizeof(C));
  163 +
  164 + delete [] content;
  165 + content=content_tmp;
  166 + count++;
  167 +}
  1 +CC=gcc
  2 +CPP=g++
  3 +#CFLAGS=-ggdb
  4 +CXXFLAGS=
  5 +MAKE=make
  6 +
  7 +OBJECTS=sin_cos.o
  8 +
  9 +%.o: %.cpp
  10 + $(CPP) $(CFLAGS) $(CXXFLAGS) -c $*.cpp
  11 +
  12 +.PHONY : all clean
  13 +
  14 +all: $(OBJECTS)
  15 +
  16 +clean:
  17 + @rm -f *.o
  1 +/**
  2 + * \file Mmn.h
  3 + *
  4 + * \brief Matrizenmanipulation beliebiger Matrizen
  5 + *
  6 + * Stellt eine Klasse zur verf&uuml;gung, mit der sich alle denkbaren
  7 + * algebraischen Manipulationen an Matrizen beliebiger gr&ouml;&szlig;e
  8 + * ausf&uuml;hren lassen, incl. l&ouml;sen eines Gleichungssystems dessen
  9 + * erweiterte Koeffizientenmatrix diese Matrix ist.
  10 + *
  11 + * \author Georg Steffers <georg@steffers.org> [GS]
  12 + *
  13 + * \date 06.12.2003
  14 + *
  15 + * \version ..2002 erste funktionierende Version [GS]
  16 + * \version 06.12.2003 beginn der Dokumentation via doxygen [GS]
  17 + */
  18 +
  19 +/*
  20 + * Copyright (C)2003 Georg Steffers
  21 + *
  22 + * This program is free software; you can redistribute it and/or modify
  23 + * it under the terms of the GNU General Public License as published by
  24 + * the Free Software Foundation; either version 2 of the License, or
  25 + * (at your option) any later version.
  26 + *
  27 + * This program is distributed in the hope that it will be useful,
  28 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  29 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  30 + * GNU General Public License for more details.
  31 + *
  32 + * You should have received a copy of the GNU General Public License
  33 + * along with this program; if not, write to the Free Software
  34 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  35 + */
  36 +
  37 +#ifndef __MMN_H__
  38 +#define __MMN_H__
  39 +
  40 +using namespace std;
  41 +
  42 +#include <cmath>
  43 +#include <iostream>
  44 +
  45 +#include "sin_cos.h"
  46 +
  47 +typedef enum gauss_typ {TREPPENNORMALE, INVERSE}; //!< \brief Was soll mit dem
  48 + //! Gauss-Algorithmus
  49 + //! ermittelt werden?
  50 +
  51 +template <class K>
  52 +class Mmn;
  53 +
  54 +//! Skalarmultiplikation Skalar * Matrize
  55 +template <class K>
  56 +Mmn<K> operator*(const K&, const Mmn<K>&);
  57 +
  58 +/**
  59 + * \brief Darstellung einer Matrize und der auf ihr m&ouml;glichen
  60 + * algebraischen Operationen
  61 + *
  62 + * Diese Klasse stellt meinen Lernerfolg in Lineare Algebra I dar.
  63 + */
  64 +template <class K>
  65 +class Mmn {
  66 + protected:
  67 + K** _a; //!< \brief Die Matrize als doppelter Pointer auf
  68 + //! den skalaren Typ K
  69 + unsigned m, n; //!< Zeilen, Spalten der Matrize
  70 + unsigned Rg; //!< \brief Der Rang der Matrize
  71 + //!
  72 + //! wird nur gefüllt wenn die Matrize &uuml;ber
  73 + //! Gauss in Treppennormalform gebracht wurde.
  74 + bool Det_F; //!< enth&auml;lt Det einen g&uuml;ltigen Wert?
  75 + K Det; //!< \brief Die Determinante der Matrize
  76 + //!
  77 + //! Sobald sie errechnet wurde wird sie hier
  78 + //! gespeichert, bis die Matrize ver&auml;ndert
  79 + //! wird, damit sie nicht immer wieder neu berechnet
  80 + //! werden mu&szlig;
  81 +
  82 + void freeall(void); //!< die matrize wieder freigeben
  83 + K sarrus(void) const; //!< \brief Sarrusregel
  84 + //!
  85 + //! zum ermitteln
  86 + //! der Determinante einer 3x3 Matrize
  87 + K laplace(void) const; //!< \brief Laplace'scher Entwicklungssatz
  88 + //!
  89 + //! zum ermitteln der Determinante bei
  90 + //! gr&ouml;&szlig;eren Matrizen als 3x3
  91 +
  92 + public:
  93 + // Konstruktoren
  94 + //! Defaultkontruktor
  95 + Mmn() : _a(NULL), m(0), n(0), Rg(0), Det_F(false) {}
  96 + Mmn(unsigned); //!< EinheitsMatrix
  97 + Mmn(unsigned, unsigned); //!< NullMatrix
  98 + Mmn(K*, unsigned, unsigned); //!< \brief Konstruktor für eine
  99 + //! beliebige Matrix
  100 + Mmn(const Mmn<K>&); //!< Copykonstruktor
  101 + virtual ~Mmn(); //!< Destruktor
  102 +
  103 + //! Zuweisungsoperator
  104 + const Mmn<K>& operator=(const Mmn<K>&);
  105 +
  106 + //! Skalarmultiplikation (Matrix * Skalar)
  107 + Mmn<K> operator*(const K&) const;
  108 + //! Als friend damit auch Parameter 1 ein Skalar sein kann
  109 + friend Mmn<K> operator*<>(const K&, const Mmn<K>&);
  110 +
  111 + // Hier können eh nur Matrizen verwendet werden. Daher sind
  112 + // keine weiteren friends nötig
  113 + Mmn<K> operator%(const Mmn<K>&) const; //!< Matrizenprodukt
  114 + Mmn<K> operator+(const Mmn<K>&) const; //!< Matrizensumme
  115 + Mmn<K> operator-(void) const; //!< Negation
  116 + Mmn<K> operator-(const Mmn<K>&) const; //!< Subtraktion
  117 +
  118 + //! eine NullMatrix derselben Groesse
  119 + Mmn<K> null(void) const { return Mmn<K>(m,n); }
  120 +
  121 + bool is_null(void) const {
  122 + for(unsigned i=0; i<m; i++)
  123 + for(unsigned j=0; j<n; j++)
  124 + if(_a[i][j]!=(K)0)
  125 + return false;
  126 +
  127 + return true;
  128 + }
  129 +
  130 + // Einheitsmatrizen, entweder zu Anzahl Spalten, oder Zeilen
  131 + //! Einheitsmatrizen zu Anzahl Spalten
  132 + Mmn<K> In(void) const { return Mmn<K>(n); }
  133 + //! Einheitsmatrizen zu Anzahl Zeilen
  134 + Mmn<K> Im(void) const { return Mmn<K>(m); }
  135 +
  136 + //! Ein Element aij der Matrize
  137 + K& a(unsigned i, unsigned j) { Det_F=false; return _a[i][j]; }
  138 + const K& a(unsigned i, unsigned j) const { return _a[i][j]; }
  139 +
  140 + //! Determinante
  141 + K det(void);
  142 + K det(void) const;
  143 +
  144 + //! Transponierte
  145 + Mmn<K> T(void) const;
  146 +
  147 + // Zeile und/oder Spalte aus matrize enftfernen
  148 + //! Zeile aus matrize enftfernen
  149 + Mmn<K> Ai(unsigned) const;
  150 + //! Spalte aus matrize enftfernen
  151 + Mmn<K> Aj(unsigned) const;
  152 + //! Zeile und Spalte aus matrize enftfernen
  153 + Mmn<K> Aij(unsigned, unsigned) const;
  154 +
  155 + // Adjunkten ermitteln (2 verschiedene Verfahren)
  156 + Mmn<K> Ad_det(void) const; //!< Adjunkte ueber Determinanten entwickelt
  157 + Mmn<K> Ad_inv(void) const; //!< Inverse=>Adjunkte / gauss=>Adj.-Satz
  158 +
  159 + // Inverse ermitteln (2 verschiedene Verfahren)
  160 + Mmn<K> gauss(gauss_typ) const; //!< \brief inverse Matrix ueber
  161 + //! Gauss-Algorithmus
  162 + Mmn<K> inv_Ad(void) const; //!< \brief Adjunkte=>Inverse /
  163 + //! Ad_det=>Adj.-Satz
  164 +
  165 + // lineare Gleichungssysteme
  166 + Mmn<K> solve(void) const; //!< Gleichungssystem loesen
  167 + Mmn<K> special_solve(void) const; //!< \brief eine Spezielle Loesung des
  168 + //! mit an=1, damit alle xi!=0
  169 +
  170 + // formatierte Ausgabe
  171 + void print(ostream& = cout) const; //!< Daten der Matrize ausgeben
  172 +};
  173 +
  174 +template <class K>
  175 +Mmn<K> operator*(const K& a, const Mmn<K>& A) {
  176 + return A * a;
  177 +}
  178 +
  179 +template <class K>
  180 +inline ostream& operator<<(ostream& strm, const Mmn<K>& A) {
  181 + A.print(strm);
  182 +
  183 + return strm;
  184 +}
  185 +
  186 +template <class K>
  187 +inline void Mmn<K>::print(ostream& strm) const {
  188 + strm << "lines: " << m << "\n";
  189 + strm << "cols: " << n << "\n";
  190 +
  191 + for(unsigned i=0; i<m; i++) {
  192 + for(unsigned j=0; j<n; j++)
  193 + strm << _a[i][j] << "\t";
  194 + strm << "\n";
  195 + }
  196 +}
  197 +
  198 +#include "Mmn_tpl.h"
  199 +#endif // __MMN_H__
  1 +using namespace std;
  2 +
  3 +#include <cstdio>
  4 +
  5 +#include "Mmn.h"
  6 +
  7 +/****************************************************************
  8 + * die Klasse "Mmn" *
  9 + ****************************************************************/
  10 +//------ Kontruktoren -------------------------------------------
  11 +template <class K>
  12 +Mmn<K>::Mmn(K* a, unsigned m, unsigned n) : m(m), n(n), Rg(0), Det_F(false) {
  13 + _a=new (K*)[m];
  14 +
  15 + for(unsigned i=0; i<m; i++) {
  16 + _a[i]=new K[n];
  17 + for(unsigned j=0; j<n; j++)
  18 + _a[i][j]=*(a+n*i+j);
  19 + }
  20 +}
  21 +
  22 +template <class K>
  23 +Mmn<K>::Mmn(unsigned m) : m(m), n(m), Rg(0), Det_F(false) {
  24 + _a=new (K*)[m];
  25 +
  26 + for(unsigned i=0; i<m; i++) {
  27 + _a[i]=new K[n];
  28 + for(unsigned j=0; j<n; j++)
  29 + _a[i][j]=(j==i)?1:0;
  30 + }
  31 +}
  32 +
  33 +template <class K>
  34 +Mmn<K>::Mmn(unsigned m, unsigned n) : m(m), n(n), Rg(0), Det_F(false) {
  35 + _a=new (K*)[m];
  36 + for(unsigned i=0; i<m; i++) {
  37 + _a[i]=new K[n];
  38 + for(unsigned j=0; j<n; j++)
  39 + _a[i][j]=0;
  40 + }
  41 +}
  42 +
  43 +template <class K>
  44 +Mmn<K>::Mmn(const Mmn<K>& A)
  45 + : m(A.m), n(A.n), Rg(A.Rg), Det(A.Det), Det_F(A.Det_F) {
  46 + _a=new (K*)[m];
  47 +
  48 + for(unsigned i=0; i<m; i++) {
  49 + _a[i]=new K[n];
  50 + for(unsigned j=0; j<n; j++)
  51 + _a[i][j]=A._a[i][j];
  52 + }
  53 +}
  54 +
  55 +template <class K>
  56 +Mmn<K>::~Mmn() {
  57 + freeall();
  58 +}
  59 +//---------------------------------------------------------------
  60 +
  61 +//------ Operatoren ---------------------------------------------
  62 +template <class K>
  63 +const Mmn<K>& Mmn<K>::operator=(const Mmn<K>& A) {
  64 + if(this==&A)
  65 + return *this;
  66 +
  67 + if(!_a || m != A.m || n != A.n) {
  68 + freeall();
  69 +
  70 + _a=new (K*)[A.m];
  71 + for(unsigned i=0; i<A.m; i++)
  72 + _a[i]=new K[A.n];
  73 + }
  74 +
  75 + m=A.m;
  76 + n=A.n;
  77 + Rg=A.Rg;
  78 + Det=A.Det;
  79 + Det_F=A.Det_F;
  80 +
  81 + for(unsigned i=0; i<m; i++)
  82 + for(unsigned j=0; j<n; j++)
  83 + _a[i][j]=A._a[i][j];
  84 +
  85 + return *this;
  86 +}
  87 +
  88 +template <class K>
  89 +Mmn<K> Mmn<K>::operator*(const K& a) const {
  90 + Mmn<K> A(m,n);
  91 +
  92 + for(unsigned i=0; i<m; i++)
  93 + for(unsigned j=0; j<n; j++)
  94 + A._a[i][j]=_a[i][j]*a;
  95 +
  96 + return A;
  97 +}
  98 +
  99 +template <class K>
  100 +Mmn<K> Mmn<K>::operator%(const Mmn<K>& A) const {
  101 + if(n != A.m)
  102 + return null();
  103 +
  104 + Mmn<K> B(m,A.n);
  105 +
  106 + for(unsigned i=0; i<m; i++)
  107 + for(unsigned j=0; j<A.n; j++) {
  108 + B._a[i][j]=0;
  109 +
  110 + for(unsigned ji=0; ji<n; ji++)
  111 + B._a[i][j]+=_a[i][ji]*A._a[ji][j];
  112 + }
  113 +
  114 + return B;
  115 +}
  116 +
  117 +template <class K>
  118 +Mmn<K> Mmn<K>::operator+(const Mmn<K>& A) const {
  119 + if(n != A.n || m != A.m)
  120 + return null();
  121 +
  122 + Mmn<K> B(m,n);
  123 +
  124 + for(unsigned i=0; i<m; i++)
  125 + for(unsigned j=0; j<n; j++)
  126 + B._a[i][j]=_a[i][j]+A._a[i][j];
  127 +
  128 + return B;
  129 +}
  130 +
  131 +template <class K>
  132 +Mmn<K> Mmn<K>::operator-(const Mmn<K>& A) const {
  133 + Mmn<K> B(m,n);
  134 +
  135 + for(unsigned i=0; i<m; i++)
  136 + for(unsigned j=0; j<n; j++)
  137 + B._a[i][j]=-A._a[i][j];
  138 +
  139 + return *this+B;
  140 +}
  141 +//---------------------------------------------------------------
  142 +
  143 +//------ Hilfsfunktionen ----------------------------------------
  144 +template <class K>
  145 +void Mmn<K>::freeall(void) {
  146 + if(_a) {
  147 + for(unsigned i=0; i<m; i++) {
  148 + delete [] _a[i];
  149 + }
  150 + delete [] _a;
  151 + _a=NULL;
  152 + }
  153 +
  154 + m=n=Rg=0;
  155 + Det_F=false;
  156 +}
  157 +//---------------------------------------------------------------
  158 +
  159 +//------ Determinantenberechnung --------------------------------
  160 +template <class K>
  161 +K Mmn<K>::sarrus(void) const {
  162 + return _a[0][0]*_a[1][1]*_a[2][2]\
  163 + +_a[0][1]*_a[1][2]*_a[2][0]\
  164 + +_a[0][2]*_a[1][0]*_a[2][1]\
  165 + -_a[0][1]*_a[1][0]*_a[2][2]\
  166 + -_a[0][0]*_a[1][2]*_a[2][1]\
  167 + -_a[0][2]*_a[1][1]*_a[2][0];
  168 +}
  169 +
  170 +template <class K>
  171 +K Mmn<K>::laplace(void) const {
  172 + K detA=0;
  173 + Mmn<K> A;
  174 +
  175 + // analytisches optimieren des Laplace-Algorithmus, durch finden der
  176 + // Zeile/Spalte mit den meisten Nullen.
  177 + //-------------------------------------------------------------------
  178 + unsigned nulls_in_line[m];
  179 + for(unsigned i=0; i<m; nulls_in_line[i++]=0);
  180 + unsigned nulls_in_col[n];
  181 + for(unsigned j=0; j<m; nulls_in_col[j++]=0);
  182 + unsigned max_nulls=0;
  183 + int max_nulls_line=0;
  184 + int max_nulls_col=0;
  185 +
  186 + for(unsigned i=0; i<m; i++)
  187 + for(unsigned j=0; j<n; j++)
  188 + if(_a[i][j]==(K)0) {
  189 + nulls_in_line[i]++;
  190 + nulls_in_col[j]++;
  191 +
  192 + if(nulls_in_line[i]>max_nulls)
  193 + max_nulls=nulls_in_line[i];
  194 + if(nulls_in_col[i]>max_nulls)
  195 + max_nulls=nulls_in_col[i];
  196 +
  197 + // ist eine komplette Zeile oder Spalte 0, so koennen wir
  198 + // direkt abbrechen und 0 zurueckgeben.
  199 + if(max_nulls==m)
  200 + return (K)0;
  201 +
  202 + max_nulls_line=(max_nulls==nulls_in_line[i])?i:max_nulls_line;
  203 + max_nulls_col=(max_nulls==nulls_in_col[j])?j:max_nulls_col;
  204 + }
  205 +
  206 + if(nulls_in_line[max_nulls_line] > nulls_in_col[max_nulls_col]) {
  207 + A=T();
  208 + max_nulls_col=max_nulls_line;
  209 + }
  210 + else
  211 + A=*this;
  212 + //-------------------------------------------------------------------
  213 +
  214 + for(unsigned i=0; i<A.m; i++)
  215 + if(A._a[i][0]!=(K)0)
  216 + detA+=((K)(int)pow((double)-1,(double)(i+max_nulls_col)))
  217 + *A._a[i][max_nulls_col]
  218 + *A.Aij(i,max_nulls_col).det();
  219 +
  220 + return detA;
  221 +}
  222 +
  223 +template <class K>
  224 +K Mmn<K>::det(void) const {
  225 + K Det=(K)0;
  226 +
  227 + if(m!=n) {
  228 + return Det;
  229 + }
  230 + else {
  231 + switch(m) {
  232 + case 1: Det=_a[0][0];
  233 + break;
  234 + case 2: Det=_a[0][0]*_a[1][1]-_a[0][1]*_a[1][0];
  235 + break;
  236 + case 3: Det=sarrus();
  237 + break;
  238 + default: Det=laplace();
  239 + }
  240 +
  241 + return Det;
  242 + }
  243 +}
  244 +
  245 +template <class K>
  246 +K Mmn<K>::det(void) {
  247 + if(m!=n) {
  248 + Det=(K)0;
  249 + Det_F=false;
  250 +
  251 + return Det;
  252 + }
  253 + else {
  254 + switch(m) {
  255 + case 1: Det=_a[0][0];
  256 + break;
  257 + case 2: Det=_a[0][0]*_a[1][1]-_a[0][1]*_a[1][0];
  258 + break;
  259 + case 3: Det=sarrus();
  260 + break;
  261 + default: Det=laplace();
  262 + }
  263 +
  264 + Det_F=true;
  265 + return Det;
  266 + }
  267 +}
  268 +//---------------------------------------------------------------
  269 +
  270 +//------ Matrizenmanipulationen ---------------------------------
  271 +template <class K>
  272 +Mmn<K> Mmn<K>::Aij(unsigned i, unsigned j) const {
  273 + Mmn<K> A(m-1,n-1);
  274 + unsigned _i, _l, _j, _k;
  275 +
  276 + for(_i=0, _l=0; _i<m; _i++, _l++) {
  277 + if(_i==i) _i++;
  278 + if(_i>=m) break;
  279 +
  280 + for(_j=0, _k=0; _j<n; _j++, _k++) {
  281 + if(_j==j) _j++;
  282 + if(_j>=n) break;
  283 +
  284 + A._a[_l][_k]=_a[_i][_j];
  285 + }
  286 + }
  287 +
  288 + return A;
  289 +}
  290 +
  291 +template <class K>
  292 +Mmn<K> Mmn<K>::Ai(unsigned i) const {
  293 + Mmn<K> A(m-1,n);
  294 + unsigned _i, l;
  295 +
  296 + for(_i=0, l=0; i<m; _i++, l++) {
  297 + if(_i==i) _i++;
  298 + if(_i>=m) break;
  299 +
  300 + for(unsigned j=0; j<n; j++)
  301 + A._a[l][j]=_a[_i][j];
  302 + }
  303 +
  304 + return A;
  305 +}
  306 +
  307 +template <class K>
  308 +Mmn<K> Mmn<K>::Aj(unsigned j) const {
  309 + Mmn<K> A(m,n-1);
  310 + unsigned _j, k;
  311 +
  312 + for(unsigned i=0; i<m; i++)
  313 + for(_j=0, k=0; _j<n; _j++, k++) {
  314 + if(_j==j) _j++;
  315 + if(_j>=n) break;
  316 +
  317 + A._a[i][k]=_a[i][_j];
  318 + }
  319 +
  320 + return A;
  321 +}
  322 +
  323 +template <class K>
  324 +Mmn<K> Mmn<K>::T(void) const {
  325 + Mmn<K> A(n,m);
  326 +
  327 + for(unsigned i=0; i<m; i++)
  328 + for(unsigned j=0; j<n; j++)
  329 + A._a[j][i]=_a[i][j];
  330 +
  331 + return A;
  332 +}
  333 +
  334 +template <class K>
  335 +Mmn<K> Mmn<K>::Ad_det(void) const {
  336 + Mmn<K> A(n,m);
  337 +
  338 + for(unsigned i=0; i<m; i++)
  339 + for(unsigned j=0; j<n; j++)
  340 + A._a[j][i]=((K)(int)pow((double)-1,(double)(i+j)))*Aij(i,j).det();
  341 +
  342 + return A;
  343 +}
  344 +
  345 +template <class K>
  346 +Mmn<K> Mmn<K>::Ad_inv(void) const {
  347 + // Das geht nur wenn die Determinante nicht 0 ist, da sonst die ganze
  348 + // Ergebnismatrix automatisch 0 wird, was aber nicht unbedingt sein muß.
  349 + // Dies gilt insbesondere Wenn die Matrize eine Null-Zeile oder Spalte
  350 + // enthaelt.
  351 + K d=Det_F?Det:det();
  352 +
  353 + if(d != (K)0)
  354 + return d*gauss(INVERSE);
  355 + else
  356 + return Ad_det();
  357 +}
  358 +
  359 +template <class K>
  360 +Mmn<K> Mmn<K>::inv_Ad(void) const {
  361 + K Adet;
  362 +
  363 + if((Adet=Det_F?Det:det())==(K)0) {
  364 + return null();
  365 + }
  366 + else {
  367 + return Ad_det()*((K)1/Adet);
  368 + }
  369 +}
  370 +
  371 +template <class K>
  372 +Mmn<K> Mmn<K>::gauss(gauss_typ T) const {
  373 + Mmn<K> A=*this;
  374 + Mmn<K> B(m);
  375 +
  376 + for(unsigned i=0; i<A.m; i++) {
  377 + unsigned j;
  378 +
  379 + for(j=i; j<A.n; j++) {
  380 + unsigned k;
  381 +
  382 + for(k=i; k<A.m && A._a[k][j]==(K)0; k++);
  383 + if(k==A.m)
  384 + continue;
  385 + if(k!=i) {
  386 + K* tmp=A._a[i];
  387 + A._a[i]=A._a[k];
  388 + A._a[k]=tmp;
  389 +
  390 + if(T==INVERSE) {
  391 + tmp=B._a[i];
  392 + B._a[i]=B._a[k];
  393 + B._a[k]=tmp;
  394 + }
  395 + }
  396 + break;
  397 + }
  398 +
  399 + if(j==A.m) break;
  400 +
  401 + if(A._a[i][j]!=(K)0) {
  402 + K aii_inv=(K)1/A._a[i][j];
  403 + A._a[i][j]=1;
  404 + A.Rg++;
  405 + B.Rg++;
  406 +
  407 + for(unsigned k=j+1; k<A.n; k++)
  408 + A._a[i][k]*=aii_inv;
  409 + if(T==INVERSE) {
  410 + for(unsigned k=0; k<B.n; k++)
  411 + B._a[i][k]*=aii_inv;
  412 + }
  413 +
  414 + for(unsigned k=0; k<A.m; k++) {
  415 + if(k != i) {
  416 + K akj_neg=-A._a[k][j];
  417 +
  418 + for(unsigned l=j; l<A.n; l++)
  419 + A._a[k][l]+=A._a[i][l]*akj_neg;
  420 + if(T==INVERSE) {
  421 + for(unsigned l=0; l<B.n; l++)
  422 + B._a[k][l]+=B._a[i][l]*akj_neg;
  423 + }
  424 + }
  425 + }
  426 + }
  427 + }
  428 +
  429 + if(T==TREPPENNORMALE)
  430 + return A;
  431 + else {
  432 + // Es gibt nur eine Inverse wenn Rg(A)=m ist
  433 + if(B.Rg==m)
  434 + return B;
  435 + else
  436 + return null();
  437 + }
  438 +}
  439 +//---------------------------------------------------------------
  440 +
  441 +//------ lineare Gleichungssysteme ------------------------------
  442 +template <class K>
  443 +Mmn<K> Mmn<K>::solve(void) const {
  444 + Mmn<K> A=gauss(TREPPENNORMALE);
  445 + Mmn<K> B=Aj(n-1).gauss(TREPPENNORMALE);
  446 +
  447 + // Gibt es eine Loesung???
  448 + if(B.Rg != A.Rg)
  449 + return null();
  450 + else {
  451 + K l[B.n][B.n-B.Rg+1];
  452 + K a[B.n][A.n];
  453 +
  454 + for(unsigned i=0, j=0; j<B.n && i<B.n; j++) {
  455 + if(i>=A.m || A._a[i][j] != (K)1) {
  456 + for(unsigned k=0; k<A.n; k++) {
  457 + if(k==j)
  458 + a[j][k]=(K)-1;
  459 + else
  460 + a[j][k]=(K)0;
  461 + }
  462 + }
  463 + else {
  464 + for(unsigned k=0; k<A.n; k++)
  465 + a[j][k]=A._a[i][k];
  466 + i++;
  467 + }
  468 + }
  469 +
  470 + unsigned j=0;
  471 + for (unsigned i=0; i<B.n; i++)
  472 + l[i][j]=a[i][A.n-1];
  473 + j++;
  474 +
  475 + for(unsigned k=0; k<B.n; k++) {
  476 + if(a[k][k]==(K)-1) {
  477 + for (unsigned i=0; i<B.n; i++)
  478 + l[i][j]=a[i][k];
  479 + j++;
  480 + }
  481 + }
  482 +
  483 + return Mmn<K>((K*)l, B.n, B.n-B.Rg+1);
  484 + }
  485 +}
  486 +
  487 +template <class K>
  488 +Mmn<K> Mmn<K>::special_solve(void) const {
  489 + Mmn<K> S=solve();
  490 + Mmn<K> A(S.m,1);
  491 +
  492 + for(unsigned i=0; i<S.m; i++) {
  493 + A._a[i][0]=(K)0;
  494 +
  495 + for(unsigned j=0; j<S.n; j++)
  496 + A._a[i][0]+=S._a[i][j];
  497 + }
  498 +
  499 + return A;
  500 +}
  501 +
  502 +//---------------------------------------------------------------
  503 +/****************************************************************/
  1 +/**
  2 + * \file V_K4.h
  3 + *
  4 + * \brief Klasse die einen 4er-Vektor mathematisch beschreibt und handled.
  5 + *
  6 + * Hier gibt alles was man f&uuml;r Vektoren so braucht (Vektorprodukt,
  7 + * Skalarprodukt, Addition, Subtraktion, Multiplikation mit Matrize)
  8 + *
  9 + * \author Georg Steffers <georg@steffers.org> [gs]
  10 + *
  11 + * \date 04.12.2003
  12 + *
  13 + * \version ..2002 [gs]: erste funktionierende Implementation
  14 + * \version 18.12.2003 [gs]: Vergleichsoperator hinzugef&uuml;gt.
  15 + */
  16 +
  17 +/*
  18 + * Copyright (C)2003 Georg Steffers
  19 + *
  20 + * This program is free software; you can redistribute it and/or modify
  21 + * it under the terms of the GNU General Public License as published by
  22 + * the Free Software Foundation; either version 2 of the License, or
  23 + * (at your option) any later version.
  24 + *
  25 + * This program is distributed in the hope that it will be useful,
  26 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  27 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  28 + * GNU General Public License for more details.
  29 + *
  30 + * You should have received a copy of the GNU General Public License
  31 + * along with this program; if not, write to the Free Software
  32 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  33 + */
  34 +
  35 +#ifndef __V_K4_H__
  36 +#define __V_K4_H__
  37 +
  38 +#include <cmath>
  39 +#include <iostream>
  40 +
  41 +#include "Mmn.h"
  42 +
  43 +/**
  44 + * \brief Winkel auf -360 bis +360 beschr&auml;nken und als double
  45 + * handhaben.
  46 + *
  47 + * Wird ein Winkel < -360 oder > +360 angegeben, so wird sein Vorkommateil
  48 + * auf diesen Bereich gestuzt und der Nachkommateil hinzuaddiert.
  49 + */
  50 +#define WINKEL(x) ((double)((int)(x)%360)+(double)(x)-(int)(x))
  51 +#define BOGENMASS(x) (WINKEL((x))*M_PI/180)
  52 +#define RAD(x) (BOGENMASS((x)))
  53 +#define GRAD(x) (WINKEL((x))*180/M_PI)
  54 +#define SQR(x) ((x)*(x))
  55 +
  56 +using namespace std;
  57 +
  58 +template <class K>
  59 +class V_K4 : public Mmn<K> {
  60 + public:
  61 + V_K4() : Mmn<K>(4, 1) {}
  62 + V_K4(Mmn<K> m) : Mmn<K>(m) {}
  63 + V_K4(K* a) : Mmn<K>(a, 4, 1) {}
  64 + V_K4(K e1, K e2, K e3, K e4=0) : Mmn<K>(4,1) {
  65 + _a[0][0]=e1; _a[1][0]=e2;
  66 + _a[2][0]=e3; _a[3][0]=e4;
  67 + }
  68 +
  69 + const K& operator[](unsigned i) const { return _a[i>m-1?m-1:i][0]; }
  70 + K& operator[](unsigned i) { return _a[i>m-1?m-1:i][0]; }
  71 + K& X(unsigned i) { return (*this)[0]; }
  72 + K& Y(unsigned i) { return (*this)[1]; }
  73 + K& Z(unsigned i) { return (*this)[2]; }
  74 + K& W(unsigned i) { return (*this)[3]; }
  75 +
  76 + K v_betr(void) const { return sqrt(*this % *this); }
  77 +
  78 + V_K4<K> v_norm(void) const { return *this * (1/v_betr()); }
  79 +
  80 + K operator% (const V_K4<K>&) const;
  81 + V_K4<K> operator| (const V_K4<K>&) const;
  82 + bool operator== (const V_K4<K>& v) const {
  83 + if(this->m==v.m &&
  84 + this->n==v.n) {
  85 + for(unsigned i=0; i<m; i++)
  86 + for(unsigned j=0; j<n; j++)
  87 + if(_a[i][j]!=v._a[i][j])
  88 + return false;
  89 + }
  90 + else
  91 + return false;
  92 +
  93 + return true;
  94 + }
  95 +};
  96 +
  97 +template <class K>
  98 +inline ostream& operator<<(ostream& strm, const V_K4<K>& A) {
  99 + A.print(strm);
  100 +
  101 + return strm;
  102 +}
  103 +
  104 +#include "V_K4_tpl.h"
  105 +
  106 +/**
  107 + * \brief Liefert die Matrize zur Rotation eines Punktes um einen
  108 + * beliebigen Vektor
  109 + */
  110 +class mat_rot_axe : public Mmn<double> {
  111 + public:
  112 + mat_rot_axe(double* a) : Mmn<double>(a, 4, 4) {}
  113 + mat_rot_axe(double w=0,
  114 + V_K4<double> const& axe=V_K4<double>(0,0,1,0)) {
  115 + V_K4<double> u(axe.v_norm());
  116 +
  117 + double A[4][4]={{SQR(u[0])+cos(RAD(w))*(1-SQR(u[0])),
  118 + u[0]*u[1]*(1-cos(RAD(w)))-u[2]*sin(RAD(w)),
  119 + u[2]*u[0]*(1-cos(RAD(w)))+u[1]*sin(RAD(w)),
  120 + 0},
  121 + {u[0]*u[1]*(1-cos(RAD(w)))+u[2]*sin(RAD(w)),
  122 + SQR(u[1])+cos(RAD(w))*(1-SQR(u[1])),
  123 + u[1]*u[2]*(1-cos(RAD(w)))-u[0]*sin(RAD(w)),
  124 + 0},
  125 + {u[2]*u[0]*(1-cos(RAD(w)))-u[1]*sin(RAD(w)),
  126 + u[1]*u[2]*(1-cos(RAD(w)))+u[0]*sin(RAD(w)),
  127 + SQR(u[2])+cos(RAD(w))*(1-SQR(u[2])),
  128 + 0},
  129 + {0,0,0,1}};
  130 +
  131 + *this=mat_rot_axe((double*)A);
  132 + }
  133 +};
  134 +
  135 +/**
  136 + * \brief Liefert die Matrize zur Rotation eines Punktes um die
  137 + * X-Achse
  138 + */
  139 +class mat_rot_x : public Mmn<double> {
  140 + public:
  141 + mat_rot_x(double* a) : Mmn<double>(a, 4, 4) {}
  142 + mat_rot_x(double w=0) {
  143 + double A[4][4]={{1,0,0,0},
  144 + {0,cos(RAD(w)),-sin(RAD(w)),0},
  145 + {0,sin(RAD(w)),cos(RAD(w)),0},
  146 + {0,0,0,1}};
  147 +
  148 + *this=mat_rot_x((double*)A);
  149 + }
  150 +};
  151 +
  152 +/**
  153 + * \brief Liefert die Matrize zur Rotation eines Punktes um die
  154 + * Y-Achse
  155 + */
  156 +class mat_rot_y : public Mmn<double> {
  157 + public:
  158 + mat_rot_y(double* a) : Mmn<double>(a, 4, 4) {}
  159 + mat_rot_y(double w=0) {
  160 + double A[4][4]={{cos(RAD(w)),0,sin(RAD(w)),0},
  161 + {0,1,0,0},
  162 + {-sin(RAD(w)),0,cos(RAD(w)),0},
  163 + {0,0,0,1}};
  164 +
  165 + *this=mat_rot_y((double*)A);
  166 + }
  167 +};
  168 +
  169 +/**
  170 + * \brief Liefert die Matrize zur Rotation eines Punktes um die
  171 + * Z-Achse
  172 + */
  173 +class mat_rot_z : public Mmn<double> {
  174 + public:
  175 + mat_rot_z(double* a) : Mmn<double>(a, 4, 4) {}
  176 + mat_rot_z(double w=0) {
  177 + double A[4][4]={{cos(RAD(w)),-sin(RAD(w)),0,0},
  178 + {sin(RAD(w)),cos(RAD(w)),0,0},
  179 + {0,0,1,0},
  180 + {0,0,0,1}};
  181 +
  182 + *this=mat_rot_z((double*)A);
  183 + }
  184 +};
  185 +
  186 +/**
  187 + * \brief Liefert die Matrize zur Verschiebung eines Punktes um
  188 + * tx. ty und tz
  189 + */
  190 +class mat_translate : public Mmn<double> {
  191 + public:
  192 + mat_translate(double* a) : Mmn<double>(a, 4, 4) {}
  193 + mat_translate(double tx=0, double ty=0, double tz=0) {
  194 + double A[4][4]={{1,0,0,tx},
  195 + {0,1,0,ty},
  196 + {0,0,1,tz},
  197 + {0,0,0,1}};
  198 +
  199 + *this=mat_translate((double*)A);
  200 + }
  201 +};
  202 +
  203 +/**
  204 + * \brief Liefert die Matrize zur Verformung eines Punktes um
  205 + * sx. sy und sz
  206 + */
  207 +class mat_transform : public Mmn<double> {
  208 + public:
  209 + mat_transform(double* a) : Mmn<double>(a, 4, 4) {}
  210 + mat_transform(double sx=0, double sy=0, double sz=0) {
  211 + double A[4][4]={{sx,0,0,0},
  212 + {0,sy,0,0},
  213 + {0,0,sz,0},
  214 + {0,0,0,1}};
  215 +
  216 + *this=mat_transform((double*)A);
  217 + }
  218 +};
  219 +
  220 +#endif // __V_K4_H__
  1 +#include "V_K4.h"
  2 +
  3 +template <class K>
  4 +K V_K4<K>::operator% (const V_K4<K>& A) const {
  5 + return (T() % (Mmn<K>)A).a(0,0);
  6 +}
  7 +
  8 +template <class K>
  9 +V_K4<K> V_K4<K>::operator| (const V_K4<K>& A) const {
  10 + V_K4<K> B;
  11 +
  12 + // Was jetzt kommt ist eine Loesung (a,b,c) des folgenden Gleichungssystems
  13 + // a*v1+b*v2+c*v3=0 und a*w1+b*w2+c*w3=0. Das heißt es ist ein Vektor
  14 + // (a,b,c) der wenn man ihn mit den uebergebenen Vektoren v und w mult.
  15 + // jeweils Null ergibt. Dieser Sachverhalt bedeutet geometrisch betrachtet
  16 + // das dieser Vektor 90 Grad zu beiden übergebenen Vektoren bildet, also
  17 + // eine Senkrechte zu der Ebene die diese beiden Vektoren aufziehen
  18 + // bildet. (Den Beweis das es eine spezielle Lösung ist bleibe ich hier
  19 + // schuldig, wers ausprobieren möchte und nich weis wie kann sich gerne
  20 + // an mich wenden.)
  21 + B[0]=_a[1][0]*A[2] - _a[2][0]*A[1];
  22 + B[1]=_a[0][0]*A[2] - _a[2][0]*A[0];
  23 + B[2]=_a[0][0]*A[1] - _a[1][0]*A[0];
  24 + B[3]=0;
  25 +
  26 + return B;
  27 +}
  1 +using namespace std;
  2 +
  3 +#include <cmath>
  4 +
  5 +#include "sin_cos.h"
  6 +
  7 +const double SIN[360]={sin(0*M_PI/180), sin(1*M_PI/180), sin(2*M_PI/180), sin(3*M_PI/180), sin(4*M_PI/180),
  8 + sin(5*M_PI/180), sin(6*M_PI/180), sin(7*M_PI/180), sin(8*M_PI/180), sin(9*M_PI/180),
  9 + sin(10*M_PI/180), sin(11*M_PI/180), sin(12*M_PI/180), sin(13*M_PI/180), sin(14*M_PI/180),
  10 + sin(15*M_PI/180), sin(16*M_PI/180), sin(17*M_PI/180), sin(18*M_PI/180), sin(19*M_PI/180),
  11 + sin(20*M_PI/180), sin(21*M_PI/180), sin(22*M_PI/180), sin(23*M_PI/180), sin(24*M_PI/180),
  12 + sin(25*M_PI/180), sin(26*M_PI/180), sin(27*M_PI/180), sin(28*M_PI/180), sin(29*M_PI/180),
  13 + sin(30*M_PI/180), sin(31*M_PI/180), sin(32*M_PI/180), sin(33*M_PI/180), sin(34*M_PI/180),
  14 + sin(35*M_PI/180), sin(36*M_PI/180), sin(37*M_PI/180), sin(38*M_PI/180), sin(39*M_PI/180),
  15 + sin(40*M_PI/180), sin(41*M_PI/180), sin(42*M_PI/180), sin(43*M_PI/180), sin(44*M_PI/180),
  16 + sin(45*M_PI/180), sin(46*M_PI/180), sin(47*M_PI/180), sin(48*M_PI/180), sin(49*M_PI/180),
  17 + sin(50*M_PI/180), sin(51*M_PI/180), sin(52*M_PI/180), sin(53*M_PI/180), sin(54*M_PI/180),
  18 + sin(55*M_PI/180), sin(56*M_PI/180), sin(57*M_PI/180), sin(58*M_PI/180), sin(59*M_PI/180),
  19 + sin(60*M_PI/180), sin(61*M_PI/180), sin(62*M_PI/180), sin(63*M_PI/180), sin(64*M_PI/180),
  20 + sin(65*M_PI/180), sin(66*M_PI/180), sin(67*M_PI/180), sin(68*M_PI/180), sin(69*M_PI/180),
  21 + sin(70*M_PI/180), sin(71*M_PI/180), sin(72*M_PI/180), sin(73*M_PI/180), sin(74*M_PI/180),
  22 + sin(75*M_PI/180), sin(76*M_PI/180), sin(77*M_PI/180), sin(78*M_PI/180), sin(79*M_PI/180),
  23 + sin(80*M_PI/180), sin(81*M_PI/180), sin(82*M_PI/180), sin(83*M_PI/180), sin(84*M_PI/180),
  24 + sin(85*M_PI/180), sin(86*M_PI/180), sin(87*M_PI/180), sin(88*M_PI/180), sin(89*M_PI/180),
  25 + sin(90*M_PI/180), sin(91*M_PI/180), sin(92*M_PI/180), sin(93*M_PI/180), sin(94*M_PI/180),
  26 + sin(95*M_PI/180), sin(96*M_PI/180), sin(97*M_PI/180), sin(98*M_PI/180), sin(99*M_PI/180),
  27 + sin(100*M_PI/180), sin(101*M_PI/180), sin(102*M_PI/180), sin(103*M_PI/180), sin(104*M_PI/180),
  28 + sin(105*M_PI/180), sin(106*M_PI/180), sin(107*M_PI/180), sin(108*M_PI/180), sin(109*M_PI/180),
  29 + sin(110*M_PI/180), sin(111*M_PI/180), sin(112*M_PI/180), sin(113*M_PI/180), sin(114*M_PI/180),
  30 + sin(115*M_PI/180), sin(116*M_PI/180), sin(117*M_PI/180), sin(118*M_PI/180), sin(119*M_PI/180),
  31 + sin(120*M_PI/180), sin(121*M_PI/180), sin(122*M_PI/180), sin(123*M_PI/180), sin(124*M_PI/180),
  32 + sin(125*M_PI/180), sin(126*M_PI/180), sin(127*M_PI/180), sin(128*M_PI/180), sin(129*M_PI/180),
  33 + sin(130*M_PI/180), sin(131*M_PI/180), sin(132*M_PI/180), sin(133*M_PI/180), sin(134*M_PI/180),
  34 + sin(135*M_PI/180), sin(136*M_PI/180), sin(137*M_PI/180), sin(138*M_PI/180), sin(139*M_PI/180),
  35 + sin(140*M_PI/180), sin(141*M_PI/180), sin(142*M_PI/180), sin(143*M_PI/180), sin(144*M_PI/180),
  36 + sin(145*M_PI/180), sin(146*M_PI/180), sin(147*M_PI/180), sin(148*M_PI/180), sin(149*M_PI/180),
  37 + sin(150*M_PI/180), sin(151*M_PI/180), sin(152*M_PI/180), sin(153*M_PI/180), sin(154*M_PI/180),
  38 + sin(155*M_PI/180), sin(156*M_PI/180), sin(157*M_PI/180), sin(158*M_PI/180), sin(159*M_PI/180),
  39 + sin(160*M_PI/180), sin(161*M_PI/180), sin(162*M_PI/180), sin(163*M_PI/180), sin(164*M_PI/180),
  40 + sin(165*M_PI/180), sin(166*M_PI/180), sin(167*M_PI/180), sin(168*M_PI/180), sin(169*M_PI/180),
  41 + sin(170*M_PI/180), sin(171*M_PI/180), sin(172*M_PI/180), sin(173*M_PI/180), sin(174*M_PI/180),
  42 + sin(175*M_PI/180), sin(176*M_PI/180), sin(177*M_PI/180), sin(178*M_PI/180), sin(179*M_PI/180),
  43 + sin(180*M_PI/180), sin(181*M_PI/180), sin(182*M_PI/180), sin(183*M_PI/180), sin(184*M_PI/180),
  44 + sin(185*M_PI/180), sin(186*M_PI/180), sin(187*M_PI/180), sin(188*M_PI/180), sin(189*M_PI/180),
  45 + sin(190*M_PI/180), sin(191*M_PI/180), sin(192*M_PI/180), sin(193*M_PI/180), sin(194*M_PI/180),
  46 + sin(195*M_PI/180), sin(196*M_PI/180), sin(197*M_PI/180), sin(198*M_PI/180), sin(199*M_PI/180),
  47 + sin(200*M_PI/180), sin(201*M_PI/180), sin(202*M_PI/180), sin(203*M_PI/180), sin(204*M_PI/180),
  48 + sin(205*M_PI/180), sin(206*M_PI/180), sin(207*M_PI/180), sin(208*M_PI/180), sin(209*M_PI/180),
  49 + sin(210*M_PI/180), sin(211*M_PI/180), sin(212*M_PI/180), sin(213*M_PI/180), sin(214*M_PI/180),
  50 + sin(215*M_PI/180), sin(216*M_PI/180), sin(217*M_PI/180), sin(218*M_PI/180), sin(219*M_PI/180),
  51 + sin(220*M_PI/180), sin(221*M_PI/180), sin(222*M_PI/180), sin(223*M_PI/180), sin(224*M_PI/180),
  52 + sin(225*M_PI/180), sin(226*M_PI/180), sin(227*M_PI/180), sin(228*M_PI/180), sin(229*M_PI/180),
  53 + sin(230*M_PI/180), sin(231*M_PI/180), sin(232*M_PI/180), sin(233*M_PI/180), sin(234*M_PI/180),
  54 + sin(235*M_PI/180), sin(236*M_PI/180), sin(237*M_PI/180), sin(238*M_PI/180), sin(239*M_PI/180),
  55 + sin(240*M_PI/180), sin(241*M_PI/180), sin(242*M_PI/180), sin(243*M_PI/180), sin(244*M_PI/180),
  56 + sin(245*M_PI/180), sin(246*M_PI/180), sin(247*M_PI/180), sin(248*M_PI/180), sin(249*M_PI/180),
  57 + sin(250*M_PI/180), sin(251*M_PI/180), sin(252*M_PI/180), sin(253*M_PI/180), sin(254*M_PI/180),
  58 + sin(255*M_PI/180), sin(256*M_PI/180), sin(257*M_PI/180), sin(258*M_PI/180), sin(259*M_PI/180),
  59 + sin(260*M_PI/180), sin(261*M_PI/180), sin(262*M_PI/180), sin(263*M_PI/180), sin(264*M_PI/180),
  60 + sin(265*M_PI/180), sin(266*M_PI/180), sin(267*M_PI/180), sin(268*M_PI/180), sin(269*M_PI/180),
  61 + sin(270*M_PI/180), sin(271*M_PI/180), sin(272*M_PI/180), sin(273*M_PI/180), sin(274*M_PI/180),
  62 + sin(275*M_PI/180), sin(276*M_PI/180), sin(277*M_PI/180), sin(278*M_PI/180), sin(279*M_PI/180),
  63 + sin(280*M_PI/180), sin(281*M_PI/180), sin(282*M_PI/180), sin(283*M_PI/180), sin(284*M_PI/180),
  64 + sin(285*M_PI/180), sin(286*M_PI/180), sin(287*M_PI/180), sin(288*M_PI/180), sin(289*M_PI/180),
  65 + sin(290*M_PI/180), sin(291*M_PI/180), sin(292*M_PI/180), sin(293*M_PI/180), sin(294*M_PI/180),
  66 + sin(295*M_PI/180), sin(296*M_PI/180), sin(297*M_PI/180), sin(298*M_PI/180), sin(299*M_PI/180),
  67 + sin(300*M_PI/180), sin(301*M_PI/180), sin(302*M_PI/180), sin(303*M_PI/180), sin(304*M_PI/180),
  68 + sin(305*M_PI/180), sin(306*M_PI/180), sin(307*M_PI/180), sin(308*M_PI/180), sin(309*M_PI/180),
  69 + sin(310*M_PI/180), sin(311*M_PI/180), sin(312*M_PI/180), sin(313*M_PI/180), sin(314*M_PI/180),
  70 + sin(315*M_PI/180), sin(316*M_PI/180), sin(317*M_PI/180), sin(318*M_PI/180), sin(319*M_PI/180),
  71 + sin(320*M_PI/180), sin(321*M_PI/180), sin(322*M_PI/180), sin(323*M_PI/180), sin(324*M_PI/180),
  72 + sin(325*M_PI/180), sin(326*M_PI/180), sin(327*M_PI/180), sin(328*M_PI/180), sin(329*M_PI/180),
  73 + sin(330*M_PI/180), sin(331*M_PI/180), sin(332*M_PI/180), sin(333*M_PI/180), sin(334*M_PI/180),
  74 + sin(335*M_PI/180), sin(336*M_PI/180), sin(337*M_PI/180), sin(338*M_PI/180), sin(339*M_PI/180),
  75 + sin(340*M_PI/180), sin(341*M_PI/180), sin(342*M_PI/180), sin(343*M_PI/180), sin(344*M_PI/180),
  76 + sin(345*M_PI/180), sin(346*M_PI/180), sin(347*M_PI/180), sin(348*M_PI/180), sin(349*M_PI/180),
  77 + sin(350*M_PI/180), sin(351*M_PI/180), sin(352*M_PI/180), sin(353*M_PI/180), sin(354*M_PI/180),
  78 + sin(355*M_PI/180), sin(356*M_PI/180), sin(357*M_PI/180), sin(358*M_PI/180), sin(359*M_PI/180)};
  79 +
  80 +const double COS[360]={cos(0*M_PI/180), cos(1*M_PI/180), cos(2*M_PI/180), cos(3*M_PI/180), cos(4*M_PI/180),
  81 + cos(5*M_PI/180), cos(6*M_PI/180), cos(7*M_PI/180), cos(8*M_PI/180), cos(9*M_PI/180),
  82 + cos(10*M_PI/180), cos(11*M_PI/180), cos(12*M_PI/180), cos(13*M_PI/180), cos(14*M_PI/180),
  83 + cos(15*M_PI/180), cos(16*M_PI/180), cos(17*M_PI/180), cos(18*M_PI/180), cos(19*M_PI/180),
  84 + cos(20*M_PI/180), cos(21*M_PI/180), cos(22*M_PI/180), cos(23*M_PI/180), cos(24*M_PI/180),
  85 + cos(25*M_PI/180), cos(26*M_PI/180), cos(27*M_PI/180), cos(28*M_PI/180), cos(29*M_PI/180),
  86 + cos(30*M_PI/180), cos(31*M_PI/180), cos(32*M_PI/180), cos(33*M_PI/180), cos(34*M_PI/180),
  87 + cos(35*M_PI/180), cos(36*M_PI/180), cos(37*M_PI/180), cos(38*M_PI/180), cos(39*M_PI/180),
  88 + cos(40*M_PI/180), cos(41*M_PI/180), cos(42*M_PI/180), cos(43*M_PI/180), cos(44*M_PI/180),
  89 + cos(45*M_PI/180), cos(46*M_PI/180), cos(47*M_PI/180), cos(48*M_PI/180), cos(49*M_PI/180),
  90 + cos(50*M_PI/180), cos(51*M_PI/180), cos(52*M_PI/180), cos(53*M_PI/180), cos(54*M_PI/180),
  91 + cos(55*M_PI/180), cos(56*M_PI/180), cos(57*M_PI/180), cos(58*M_PI/180), cos(59*M_PI/180),
  92 + cos(60*M_PI/180), cos(61*M_PI/180), cos(62*M_PI/180), cos(63*M_PI/180), cos(64*M_PI/180),
  93 + cos(65*M_PI/180), cos(66*M_PI/180), cos(67*M_PI/180), cos(68*M_PI/180), cos(69*M_PI/180),
  94 + cos(70*M_PI/180), cos(71*M_PI/180), cos(72*M_PI/180), cos(73*M_PI/180), cos(74*M_PI/180),
  95 + cos(75*M_PI/180), cos(76*M_PI/180), cos(77*M_PI/180), cos(78*M_PI/180), cos(79*M_PI/180),
  96 + cos(80*M_PI/180), cos(81*M_PI/180), cos(82*M_PI/180), cos(83*M_PI/180), cos(84*M_PI/180),
  97 + cos(85*M_PI/180), cos(86*M_PI/180), cos(87*M_PI/180), cos(88*M_PI/180), cos(89*M_PI/180),
  98 + cos(90*M_PI/180), cos(91*M_PI/180), cos(92*M_PI/180), cos(93*M_PI/180), cos(94*M_PI/180),
  99 + cos(95*M_PI/180), cos(96*M_PI/180), cos(97*M_PI/180), cos(98*M_PI/180), cos(99*M_PI/180),
  100 + cos(100*M_PI/180), cos(101*M_PI/180), cos(102*M_PI/180), cos(103*M_PI/180), cos(104*M_PI/180),
  101 + cos(105*M_PI/180), cos(106*M_PI/180), cos(107*M_PI/180), cos(108*M_PI/180), cos(109*M_PI/180),
  102 + cos(110*M_PI/180), cos(111*M_PI/180), cos(112*M_PI/180), cos(113*M_PI/180), cos(114*M_PI/180),
  103 + cos(115*M_PI/180), cos(116*M_PI/180), cos(117*M_PI/180), cos(118*M_PI/180), cos(119*M_PI/180),
  104 + cos(120*M_PI/180), cos(121*M_PI/180), cos(122*M_PI/180), cos(123*M_PI/180), cos(124*M_PI/180),
  105 + cos(125*M_PI/180), cos(126*M_PI/180), cos(127*M_PI/180), cos(128*M_PI/180), cos(129*M_PI/180),
  106 + cos(130*M_PI/180), cos(131*M_PI/180), cos(132*M_PI/180), cos(133*M_PI/180), cos(134*M_PI/180),
  107 + cos(135*M_PI/180), cos(136*M_PI/180), cos(137*M_PI/180), cos(138*M_PI/180), cos(139*M_PI/180),
  108 + cos(140*M_PI/180), cos(141*M_PI/180), cos(142*M_PI/180), cos(143*M_PI/180), cos(144*M_PI/180),
  109 + cos(145*M_PI/180), cos(146*M_PI/180), cos(147*M_PI/180), cos(148*M_PI/180), cos(149*M_PI/180),
  110 + cos(150*M_PI/180), cos(151*M_PI/180), cos(152*M_PI/180), cos(153*M_PI/180), cos(154*M_PI/180),
  111 + cos(155*M_PI/180), cos(156*M_PI/180), cos(157*M_PI/180), cos(158*M_PI/180), cos(159*M_PI/180),
  112 + cos(160*M_PI/180), cos(161*M_PI/180), cos(162*M_PI/180), cos(163*M_PI/180), cos(164*M_PI/180),
  113 + cos(165*M_PI/180), cos(166*M_PI/180), cos(167*M_PI/180), cos(168*M_PI/180), cos(169*M_PI/180),
  114 + cos(170*M_PI/180), cos(171*M_PI/180), cos(172*M_PI/180), cos(173*M_PI/180), cos(174*M_PI/180),
  115 + cos(175*M_PI/180), cos(176*M_PI/180), cos(177*M_PI/180), cos(178*M_PI/180), cos(179*M_PI/180),
  116 + cos(180*M_PI/180), cos(181*M_PI/180), cos(182*M_PI/180), cos(183*M_PI/180), cos(184*M_PI/180),
  117 + cos(185*M_PI/180), cos(186*M_PI/180), cos(187*M_PI/180), cos(188*M_PI/180), cos(189*M_PI/180),
  118 + cos(190*M_PI/180), cos(191*M_PI/180), cos(192*M_PI/180), cos(193*M_PI/180), cos(194*M_PI/180),
  119 + cos(195*M_PI/180), cos(196*M_PI/180), cos(197*M_PI/180), cos(198*M_PI/180), cos(199*M_PI/180),
  120 + cos(200*M_PI/180), cos(201*M_PI/180), cos(202*M_PI/180), cos(203*M_PI/180), cos(204*M_PI/180),
  121 + cos(205*M_PI/180), cos(206*M_PI/180), cos(207*M_PI/180), cos(208*M_PI/180), cos(209*M_PI/180),
  122 + cos(210*M_PI/180), cos(211*M_PI/180), cos(212*M_PI/180), cos(213*M_PI/180), cos(214*M_PI/180),
  123 + cos(215*M_PI/180), cos(216*M_PI/180), cos(217*M_PI/180), cos(218*M_PI/180), cos(219*M_PI/180),
  124 + cos(220*M_PI/180), cos(221*M_PI/180), cos(222*M_PI/180), cos(223*M_PI/180), cos(224*M_PI/180),
  125 + cos(225*M_PI/180), cos(226*M_PI/180), cos(227*M_PI/180), cos(228*M_PI/180), cos(229*M_PI/180),
  126 + cos(230*M_PI/180), cos(231*M_PI/180), cos(232*M_PI/180), cos(233*M_PI/180), cos(234*M_PI/180),
  127 + cos(235*M_PI/180), cos(236*M_PI/180), cos(237*M_PI/180), cos(238*M_PI/180), cos(239*M_PI/180),
  128 + cos(240*M_PI/180), cos(241*M_PI/180), cos(242*M_PI/180), cos(243*M_PI/180), cos(244*M_PI/180),
  129 + cos(245*M_PI/180), cos(246*M_PI/180), cos(247*M_PI/180), cos(248*M_PI/180), cos(249*M_PI/180),
  130 + cos(250*M_PI/180), cos(251*M_PI/180), cos(252*M_PI/180), cos(253*M_PI/180), cos(254*M_PI/180),
  131 + cos(255*M_PI/180), cos(256*M_PI/180), cos(257*M_PI/180), cos(258*M_PI/180), cos(259*M_PI/180),
  132 + cos(260*M_PI/180), cos(261*M_PI/180), cos(262*M_PI/180), cos(263*M_PI/180), cos(264*M_PI/180),
  133 + cos(265*M_PI/180), cos(266*M_PI/180), cos(267*M_PI/180), cos(268*M_PI/180), cos(269*M_PI/180),
  134 + cos(270*M_PI/180), cos(271*M_PI/180), cos(272*M_PI/180), cos(273*M_PI/180), cos(274*M_PI/180),
  135 + cos(275*M_PI/180), cos(276*M_PI/180), cos(277*M_PI/180), cos(278*M_PI/180), cos(279*M_PI/180),
  136 + cos(280*M_PI/180), cos(281*M_PI/180), cos(282*M_PI/180), cos(283*M_PI/180), cos(284*M_PI/180),
  137 + cos(285*M_PI/180), cos(286*M_PI/180), cos(287*M_PI/180), cos(288*M_PI/180), cos(289*M_PI/180),
  138 + cos(290*M_PI/180), cos(291*M_PI/180), cos(292*M_PI/180), cos(293*M_PI/180), cos(294*M_PI/180),
  139 + cos(295*M_PI/180), cos(296*M_PI/180), cos(297*M_PI/180), cos(298*M_PI/180), cos(299*M_PI/180),
  140 + cos(300*M_PI/180), cos(301*M_PI/180), cos(302*M_PI/180), cos(303*M_PI/180), cos(304*M_PI/180),
  141 + cos(305*M_PI/180), cos(306*M_PI/180), cos(307*M_PI/180), cos(308*M_PI/180), cos(309*M_PI/180),
  142 + cos(310*M_PI/180), cos(311*M_PI/180), cos(312*M_PI/180), cos(313*M_PI/180), cos(314*M_PI/180),
  143 + cos(315*M_PI/180), cos(316*M_PI/180), cos(317*M_PI/180), cos(318*M_PI/180), cos(319*M_PI/180),
  144 + cos(320*M_PI/180), cos(321*M_PI/180), cos(322*M_PI/180), cos(323*M_PI/180), cos(324*M_PI/180),
  145 + cos(325*M_PI/180), cos(326*M_PI/180), cos(327*M_PI/180), cos(328*M_PI/180), cos(329*M_PI/180),
  146 + cos(330*M_PI/180), cos(331*M_PI/180), cos(332*M_PI/180), cos(333*M_PI/180), cos(334*M_PI/180),
  147 + cos(335*M_PI/180), cos(336*M_PI/180), cos(337*M_PI/180), cos(338*M_PI/180), cos(339*M_PI/180),
  148 + cos(340*M_PI/180), cos(341*M_PI/180), cos(342*M_PI/180), cos(343*M_PI/180), cos(344*M_PI/180),
  149 + cos(345*M_PI/180), cos(346*M_PI/180), cos(347*M_PI/180), cos(348*M_PI/180), cos(349*M_PI/180),
  150 + cos(350*M_PI/180), cos(351*M_PI/180), cos(352*M_PI/180), cos(353*M_PI/180), cos(354*M_PI/180),
  151 + cos(355*M_PI/180), cos(356*M_PI/180), cos(357*M_PI/180), cos(358*M_PI/180), cos(359*M_PI/180)};
  1 +#ifndef __sin_cos_h__
  2 +#define __sin_cos_h__
  3 +extern const double SIN[360];
  4 +extern const double COS[360];
  5 +#endif // __sin_cos_h__
  1 +/**
  2 + * \file rasterize.cpp
  3 + *
  4 + * \brief Implementation des Software-Rasterizers
  5 + *
  6 + * F&uuml;r eine detailierte Beschreibung von Rasterizer und
  7 + * Software-Rasterizer schauen Sie bitte unter \ref rasterize.h
  8 + *
  9 + * \author Georg Steffers <georg@steffers.org> [gs]
  10 + *
  11 + * \date 04.12.2003
  12 + *
  13 + * \version ..2002 [gs]: erste funktionierende Implementation
  14 + * \version 04.12.2003 [gs]: beginn der Dokumentation via doxygen
  15 + * \version 16.12.2003 [gs]: <ul><li>
  16 + * Linienclipping gefixed. Die alte
  17 + * Version versuchte Linien zu zeichnen
  18 + * die sich nach dem Clipping in
  19 + * Area 1001, 1010, 0101, 0110, also den
  20 + * Ecken rechtoben, linksoben,
  21 + * rechtsunten und linksunten neben dem
  22 + * darstellbaren Bereich befanden.
  23 + * </li><li>
  24 + * Außerdum mussten nach jedem Clipping
  25 + * die Masken aktualisiert werden, damit
  26 + * der Algoritmus abbricht wenn die
  27 + * Linie gezeichnet werden kann.
  28 + * Ansosnten führte weiters clipping zu
  29 + * fehlerhaften Ergebnissen.
  30 + * </li><li>
  31 + * draw_polygon_flat ruft jetzt den in
  32 + * polygon.h neu geschriebene
  33 + * Sutherland-Hodgen Clipper auf und
  34 + * zeichnet nur das geclippte Polygon
  35 + * das dieser Zurückliefert.
  36 + * </li></ul>
  37 + * \version 19.12.2003 [gs]: <ul><li>
  38 + * draw_polyeder_wire neu geschrieben. (Der
  39 + * alte Code existiert noch auskommentiert.
  40 + * </li><li>
  41 + * draw_polygon_wire geschrieben. Es macht was man
  42 + * sich denkt, es zeichnte ein Polygon alse linien.
  43 + * </li></ul>
  44 + *
  45 + * \todo (siehe \ref draw_polygon_flat)
  46 + */
  47 +
  48 +/*
  49 + * Copyright (C)2003 Georg Steffers
  50 + *
  51 + * This program is free software; you can redistribute it and/or modify
  52 + * it under the terms of the GNU General Public License as published by
  53 + * the Free Software Foundation; either version 2 of the License, or
  54 + * (at your option) any later version.
  55 + *
  56 + * This program is distributed in the hope that it will be useful,
  57 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  58 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  59 + * GNU General Public License for more details.
  60 + *
  61 + * You should have received a copy of the GNU General Public License
  62 + * along with this program; if not, write to the Free Software
  63 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  64 + */
  65 +
  66 +using namespace std;
  67 +
  68 +#include <cstdlib>
  69 +#include <climits>
  70 +#include <cstring>
  71 +#include <values.h>
  72 +
  73 +#include <iostream>
  74 +
  75 +#include "geometry/polygon.h"
  76 +#include "rasterize.h"
  77 +
  78 +#define CLIP_MASK_LEFT (0x1<<0)
  79 +#define CLIP_MASK_RIGHT (0x1<<1)
  80 +#define CLIP_MASK_BOTTOM (0x1<<2)
  81 +#define CLIP_MASK_TOP (0x1<<3)
  82 +
  83 +rasterizer::rasterizer(unsigned xs, unsigned ys, canvas_imp* ci) {
  84 + x_size=xs;
  85 + y_size=ys;
  86 +
  87 + sinfo=ci;
  88 +
  89 + zbuf=new (double*)[xs];
  90 + for(unsigned i=0; i<xs; i++) {
  91 + zbuf[i]=new double[ys];
  92 + for(unsigned j=0; j<ys; zbuf[i][j++]=MAXDOUBLE);
  93 + }
  94 +
  95 + unsigned sp[]={0,1,2,3};
  96 + vertex v[]={vertex(0,y_size,0,1),
  97 + vertex(0,0,0,1),
  98 + vertex(x_size,0,0,1),
  99 + vertex(x_size,y_size,0,1)};
  100 +
  101 + screen_p_vl=vertex_list(v, 4);
  102 + screen_p=polygon((unsigned*)sp, 4, &screen_p_vl);
  103 +}
  104 +
  105 +unsigned char* sw_rasterizer::adr_of_point(unsigned x, unsigned y) const {
  106 + return sinfo->p_screenbuf + (x+(y*x_size))*sinfo->bytes_per_pixel;
  107 +}
  108 +
  109 +void sw_rasterizer::draw_point_at_paddress(unsigned char** p,
  110 + unsigned long col) const {
  111 + unsigned long mask = 0xFF;
  112 + char shift = 0;
  113 +
  114 + // farbytes in Little-Endian order in den Puffer
  115 + for(int i=0; i<sinfo->bytes_per_pixel; i++) {
  116 + **p = (col & mask) >> shift;
  117 + (*p)++;
  118 + mask <<= 8;
  119 + shift += 8;
  120 + }
  121 +}
  122 +
  123 +void sw_rasterizer::clear_buffer(void) const {
  124 + memset(sinfo->p_screenbuf, 0x00,
  125 + (size_t)x_size*y_size*sinfo->bytes_per_pixel);
  126 +
  127 + for(unsigned i=0; i<x_size; i++) {
  128 + for(unsigned j=0; j<y_size; zbuf[i][j++]=MAXDOUBLE);
  129 + }
  130 +}
  131 +
  132 +void sw_rasterizer::draw_point(unsigned x, unsigned y,
  133 + unsigned long col) const {
  134 + unsigned char *p = adr_of_point(x, y);
  135 + draw_point_at_paddress(&p, col);
  136 +}
  137 +
  138 +void sw_rasterizer::line(double ax, double ay, double bx, double by,
  139 + unsigned long col) const {
  140 + /* Line-Clipping (nach Cohen-Sutherland) */
  141 + char clip_mask_a=0;
  142 + char clip_mask_b=0;
  143 + unsigned x_size=this->x_size-1;
  144 + unsigned y_size=this->y_size-1;
  145 +
  146 + if(ax<0) clip_mask_a |= CLIP_MASK_LEFT;
  147 + if(ax>x_size) clip_mask_a |= CLIP_MASK_RIGHT;
  148 + if(ay>y_size) clip_mask_a |= CLIP_MASK_BOTTOM;
  149 + if(ay<0) clip_mask_a |= CLIP_MASK_TOP;
  150 +
  151 + if(bx<0) clip_mask_b |= CLIP_MASK_LEFT;
  152 + if(bx>x_size) clip_mask_b |= CLIP_MASK_RIGHT;
  153 + if(by>y_size) clip_mask_b |= CLIP_MASK_BOTTOM;
  154 + if(by<0) clip_mask_b |= CLIP_MASK_TOP;
  155 +
  156 + if((clip_mask_a & clip_mask_b) != 0)
  157 + return;
  158 +
  159 + double dx=bx-ax;
  160 + double dy=by-ay;
  161 + double xinc=dx/dy;
  162 + double yinc=dy/dx;
  163 +
  164 + if(clip_mask_a != 0) {
  165 + if((clip_mask_a&CLIP_MASK_LEFT)!=0) {
  166 + ay+=(0-ax)*yinc;
  167 + ax=0;
  168 + }
  169 + else if(clip_mask_a & CLIP_MASK_RIGHT) {
  170 + ay+=(x_size-ax)*yinc;
  171 + ax=x_size;
  172 + }
  173 +
  174 + clip_mask_a=0;
  175 + if(ax<0) clip_mask_a |= CLIP_MASK_LEFT;
  176 + if(ax>x_size) clip_mask_a |= CLIP_MASK_RIGHT;
  177 + if(ay>y_size) clip_mask_a |= CLIP_MASK_BOTTOM;
  178 + if(ay<0) clip_mask_a |= CLIP_MASK_TOP;
  179 +
  180 + if(clip_mask_a & CLIP_MASK_TOP) {
  181 + ax+=(0-ay)*xinc;
  182 + ay=0;
  183 + }
  184 + else if(clip_mask_a & CLIP_MASK_BOTTOM) {
  185 + ax+=(y_size-ay)*xinc;
  186 + ay=y_size;
  187 + }
  188 + }
  189 +
  190 + if(clip_mask_b != 0) {
  191 + if(clip_mask_b & CLIP_MASK_LEFT) {
  192 + by+=(0-bx)*yinc;
  193 + bx=0;
  194 + }
  195 + else if(clip_mask_b & CLIP_MASK_RIGHT) {
  196 + by+=(x_size-bx)*yinc;
  197 + bx=x_size;
  198 + }
  199 +
  200 + clip_mask_b=0;
  201 + if(bx<0) clip_mask_b |= CLIP_MASK_LEFT;
  202 + if(bx>x_size) clip_mask_b |= CLIP_MASK_RIGHT;
  203 + if(by>y_size) clip_mask_b |= CLIP_MASK_BOTTOM;
  204 + if(by<0) clip_mask_b |= CLIP_MASK_TOP;
  205 +
  206 + if(clip_mask_b & CLIP_MASK_TOP) {
  207 + bx+=(0-by)*xinc;
  208 + by=0;
  209 + }
  210 + else if(clip_mask_b & CLIP_MASK_BOTTOM) {
  211 + bx+=(y_size-by)*xinc;
  212 + by=y_size;
  213 + }
  214 + }
  215 +
  216 + clip_mask_a=0;
  217 + if(ax<0) clip_mask_a |= CLIP_MASK_LEFT;
  218 + if(ax>x_size) clip_mask_a |= CLIP_MASK_RIGHT;
  219 + if(ay>y_size) clip_mask_a |= CLIP_MASK_BOTTOM;
  220 + if(ay<0) clip_mask_a |= CLIP_MASK_TOP;
  221 +
  222 + clip_mask_b=0;
  223 + if(bx<0) clip_mask_b |= CLIP_MASK_LEFT;
  224 + if(bx>x_size) clip_mask_b |= CLIP_MASK_RIGHT;
  225 + if(by>y_size) clip_mask_b |= CLIP_MASK_BOTTOM;
  226 + if(by<0) clip_mask_b |= CLIP_MASK_TOP;
  227 +
  228 + if((clip_mask_a | clip_mask_b) == (CLIP_MASK_LEFT | CLIP_MASK_TOP) ||
  229 + (clip_mask_a | clip_mask_b) == (CLIP_MASK_LEFT | CLIP_MASK_BOTTOM) ||
  230 + (clip_mask_a | clip_mask_b) == (CLIP_MASK_RIGHT | CLIP_MASK_TOP) ||
  231 + (clip_mask_a | clip_mask_b) == (CLIP_MASK_RIGHT | CLIP_MASK_BOTTOM))
  232 + return;
  233 + /* ----------- */
  234 +
  235 + /* Linie nach Bresenham */
  236 + int Ax=(int)ax;
  237 + int Bx=(int)bx;
  238 + int Ay=(int)ay;
  239 + int By=(int)by;
  240 +
  241 + int dX = abs(Bx-Ax);
  242 + int dY = abs(By-Ay);
  243 +
  244 + int Xincr=(Ax > Bx)?-1:1;
  245 + int Yincr=(Ay > By)?-1:1;
  246 +
  247 + if (dX >= dY) {
  248 + int dPr = dY<<1;
  249 + int dPru = dPr - (dX<<1);
  250 + int P = dPr - dX;
  251 +
  252 + for (; dX>=0; dX--) {
  253 + draw_point(Ax, Ay, col);
  254 + if (P > 0) {
  255 + Ax+=Xincr;
  256 + Ay+=Yincr;
  257 + P+=dPru;
  258 + }
  259 + else {
  260 + Ax+=Xincr;
  261 + P+=dPr;
  262 + }
  263 + }
  264 + }
  265 + else {
  266 + int dPr = dX<<1;
  267 + int dPru = dPr - (dY<<1);
  268 + int P = dPr - dY;
  269 +
  270 + for (; dY>=0; dY--) {
  271 + draw_point(Ax, Ay, col);
  272 + if (P > 0) {
  273 + Ax+=Xincr;
  274 + Ay+=Yincr;
  275 + P+=dPru;
  276 + }
  277 + else {
  278 + Ay+=Yincr;
  279 + P+=dPr;
  280 + }
  281 + }
  282 + }
  283 + /*------------------*/
  284 +}
  285 +
  286 +void sw_rasterizer::draw_polygon_wire(const polygon& p,
  287 + unsigned long col) const {
  288 + for(unsigned i=0; i<p.card(); i++) {
  289 + line((int)p[i][X], (int)p[i][Y],
  290 + (int)p[(i+1)%p.card()][X], (int)p[(i+1)%p.card()][Y], col);
  291 + }
  292 +}
  293 +
  294 +void sw_rasterizer::draw_polyeder_wire(const polyeder& p,
  295 + unsigned long col) const {
  296 +/* for(unsigned i=0; i<p.card(); i++) {
  297 + int oldx, oldy;
  298 + int firstx, firsty;
  299 +
  300 + oldx=oldy=firstx=firsty=0;
  301 +
  302 + for(unsigned j=0; j<p[i].card(); j++) {
  303 + if(oldx)
  304 + line(oldx, oldy, (int)p[i][j][X], (int)p[i][j][Y], col);
  305 +
  306 + oldx=(int)p[i][j][X], oldy=(int)p[i][j][Y];
  307 +
  308 + if(j==0)
  309 + firstx=(int)p[i][j][X], firsty=(int)p[i][j][Y];
  310 + }
  311 +
  312 + line(oldx, oldy, firstx, firsty, col);
  313 + }*/
  314 + for(unsigned i=0; i<p.card(); i++) {
  315 + for(unsigned j=0; j<p[i].card(); j++) {
  316 + line((int)p[i][j][X], (int)p[i][j][Y],
  317 + (int)p[i][(j+1)%p.card()][X],
  318 + (int)p[i][(j+1)%p.card()][Y], col);
  319 + }
  320 + }
  321 +}
  322 +
  323 +/**
  324 + * \todo Ein funktionierendes z-buffering und texturemapping usw.
  325 + * Aktuell ist ein Prototyp-Code f&uuml;r einen z-Buffer drin,
  326 + * aber der funktioniert aus irgendeinem Grund nicht richtig.
  327 + */
  328 +void sw_rasterizer::draw_polygon_flat(const polygon& p,
  329 + unsigned long col) const {
  330 + int top=0, bottom=0, o_top=0;
  331 + int start_left, end_left;
  332 + int start_right, end_right;
  333 +
  334 + /* Clipping..... */
  335 + /* Sutherland-Hodgman */
  336 + polygon clipped=p.clip_2d(screen_p);
  337 +
  338 + // Sind nach dem Clipping weniger als 3 Vertices übrig, so ist das
  339 + // Polygon nicht mehr im sichtbaren Bereich und darf nicht gezeichnet
  340 + // werden.
  341 + if(clipped.card()<3)
  342 + return;
  343 +
  344 + // oberes und unterstes Vertex finden...
  345 + // außerdem den oberen Vertex fuer die erste rechte und linke Kante
  346 + for(unsigned i=1; i<clipped.card(); i++) {
  347 + end_left=end_right=top=(clipped[i][Y]<clipped[top][Y])?i:top;
  348 + bottom=(clipped[i][Y]>clipped[bottom][Y])?i:bottom;
  349 + }
  350 +
  351 + for(unsigned i=1; i<p.card(); i++) {
  352 + o_top=(p[i][Y]<p[o_top][Y])?i:o_top;
  353 + }
  354 +
  355 + // Startpositionen
  356 + double act_y=clipped[top][Y];
  357 + int act_ceily=(int)ceil(act_y);
  358 + double act_x_l, act_x_r;
  359 + double act_z_l, act_z_r;
  360 +
  361 + // !!! Das erste mal wenn act_z ermittelt wird muss ich die Verchiebung
  362 + // auf die Integer Koordinaten (x,y) mit berechnen, da der gezeichnete Punkt
  363 + // nicht exact dem geometrischen entspricht.
  364 +
  365 + // calculate gradients (!!!NICHT VOM GECLIPPTEN!!!)
  366 + // nur anwendbar über Werte die über das gesamte Polygon (screenspace)
  367 + // linear interpolierbar sind, also nicht gourard-shading, da diese
  368 + // Werte nur entlang einer Kante linier sind.
  369 + // !!! Ich brauche eine Methode, ein Dreieck zu finden, das einen Punkt
  370 + // oben, den zweiten als linke Seite und den dritten als rechte Seite bildet
  371 + // dazu muss ich die x,y Werte der Puntke analysieren. Die Lage der
  372 + // Punkte ist wichtig, damit die Vorzeichen der Gradienten stimmen, bzw.
  373 + // überhaupt erstmal welche berechnet werden können, es gibt Punkt
  374 + // kombinationen für die die Gradientenberechnung kein Ergebnis liefert.
  375 + // Das ermittelte Dreieck lässt sich dann allerdings zur ermittlung aller
  376 + // Gradienten gebrauchen.
  377 +
  378 + // den obersten Vertex raussuchen, dann den davor und den danach.
  379 + // !!!ACHTUNG!!! Bei allen Berechnungen lasse ich im moment einen Fall
  380 + // ganz außer acht und zwar den, wenn das Dreiech zu einer Linie
  381 + // entartet.
  382 + unsigned gr_v0=o_top;
  383 + unsigned gr_v1=(o_top+1)%p.card();
  384 + unsigned gr_v2=(o_top-1<0)?o_top-1+p.card():o_top-1;
  385 +
  386 + // der kleinere X soll gr_v1 sein wenn sein Y größer ist.
  387 + if((p[gr_v1][X]>p[gr_v2][X] && p[gr_v1][Y]>=p[gr_v2][Y]) ||
  388 + (p[gr_v1][X]<p[gr_v2][X] && p[gr_v1][Y]<p[gr_v2][Y]))
  389 + swap<unsigned>(gr_v1, gr_v2);
  390 +
  391 + double dx21=p[gr_v2][X]-p[gr_v1][X];
  392 + double dx10=p[gr_v1][X]-p[gr_v0][X];
  393 + double dy21=p[gr_v2][Y]-p[gr_v1][Y];
  394 + double dy01=p[gr_v0][Y]-p[gr_v1][Y];
  395 + double d_z21=p[gr_v2][Z]-p[gr_v1][Z];
  396 + double d_z10=p[gr_v1][Z]-p[gr_v0][Z];
  397 +
  398 + double dx01=p[gr_v0][X]-p[gr_v1][X];
  399 + double dy10=p[gr_v1][Y]-p[gr_v0][Y];
  400 +
  401 + double v3_x=p[gr_v0][X];
  402 + double v4_y=p[gr_v0][Y];
  403 + double v3_y=((dy21*dx01) / dx21) + p[gr_v1][Y];
  404 + double v3_z=((d_z21*dx01) / dx21) + p[gr_v1][Z];
  405 + double v4_x=((dx21*dy01) / dy21) + p[gr_v1][X];
  406 + double v4_z=((d_z21*dy01) / dy21) + p[gr_v1][Z];
  407 +
  408 + // zuallererst müsste ich mal überprüfen ob alle drei Punkte in
  409 + // einer Linie liegen, also dx01/dy01 == dx02/dy02 ist...da ich aber
  410 + // noch nicht weiss wie ich diesen Fall behandeln soll ignorier ich
  411 + // ihn im moment und nehme die entstehenden Fehler in kauf.
  412 +
  413 + double d_zdx_denominator=0;
  414 + double d_zdy_denominator=0;
  415 + double d_zdx, d_zdy;
  416 + // zuerst dc/dx ermitteln. (einfach wenn y1==y2)
  417 + // zu den Bezeichnern: _x == 1/x, _? == 1/?
  418 + if(p[gr_v0][Y] == p[gr_v1][Y])
  419 + d_zdx=(p[gr_v1][Z]-p[gr_v0][Z]) / (p[gr_v1][X]-p[gr_v0][X]);
  420 + else if(p[gr_v0][Y] == p[gr_v2][Y])
  421 + d_zdx=(p[gr_v2][Z]-p[gr_v0][Z]) / (p[gr_v2][X]-p[gr_v0][X]);
  422 + else if(p[gr_v1][Y] == p[gr_v2][Y])
  423 + d_zdx=(p[gr_v2][Z]-p[gr_v1][Z]) / (p[gr_v2][X]-p[gr_v1][X]);
  424 + else {
  425 + d_zdx_denominator=(dx21*dy01)+(dx10*dy21);
  426 + d_zdx=((d_z21*dy01)+(d_z10*dy21))/d_zdx_denominator;
  427 + }
  428 +
  429 + // jetzt dc/dy...(einfach falls es eine Sekrechte gibt.)
  430 + if(p[gr_v0][X] == p[gr_v1][X])
  431 + d_zdy=(p[gr_v1][Z]-p[gr_v0][Z]) / p[gr_v1][Y]-p[gr_v0][Y];
  432 + else if(p[gr_v0][X] == p[gr_v2][X])
  433 + d_zdy=(p[gr_v2][Z]-p[gr_v0][Z]) / p[gr_v2][Y]-p[gr_v0][Y];
  434 + else if(p[gr_v1][X] == p[gr_v2][X])
  435 + d_zdy=(p[gr_v2][Z]-p[gr_v1][Z]) / p[gr_v2][Y]-p[gr_v1][Y];
  436 + else {
  437 + d_zdy_denominator=d_zdx_denominator!=0?-d_zdx_denominator:
  438 + (dy21*dx01)+(dy10*dx21);
  439 + d_zdy=((d_z21*dx01)+(d_z10*dx21))/d_zdy_denominator;
  440 + }
  441 +
  442 +/* if(!strncmp(p.get_id(), "DEBUG", 29)) {
  443 + cout << "---Polygon: " << &p << "----------\n";
  444 +
  445 + for(unsigned i=0; i<p.card(); i++) {
  446 + cout << "p[" << i << "][X]: " << p[i][X] << ", ";
  447 + cout << "p[" << i << "][Y]: " << p[i][Y] << ", ";
  448 + cout << "p[" << i << "][1/Z]: " << p[i][Z] << ", ";
  449 + cout << "p[" << i << "][Z]: " << 1/p[i][Z] << "\n";
  450 + }
  451 + for(unsigned i=0; i<clipped.card(); i++) {
  452 + cout << "clipped[" << i << "][X]: " << clipped[i][X] << ", ";
  453 + cout << "clipped[" << i << "][Y]: " << clipped[i][Y] << ", ";
  454 + cout << "clipped[" << i << "][1/Z]: " << clipped[i][Z] << ", ";
  455 + cout << "clipped[" << i << "][Z]: " << 1/clipped[i][Z] << "\n";
  456 + }
  457 + cout << "gr_v0: " << gr_v0 << " | ";
  458 + cout << "gr_v0[X]: " << p[gr_v0][X] << " | ";
  459 + cout << "gr_v0[Y]: " << p[gr_v0][Y] << " | ";
  460 + cout << "gr_v0[Z]: " << p[gr_v0][Z] << "\n";
  461 + cout << "gr_v1: " << gr_v1 << " | ";
  462 + cout << "gr_v1[X]: " << p[gr_v1][X] << " | ";
  463 + cout << "gr_v1[Y]: " << p[gr_v1][Y] << " | ";
  464 + cout << "gr_v1[Z]: " << p[gr_v1][Z] << "\n";
  465 + cout << "gr_v2: " << gr_v2 << " | ";
  466 + cout << "gr_v2[X]: " << p[gr_v2][X] << " | ";
  467 + cout << "gr_v2[Y]: " << p[gr_v2][Y] << " | ";
  468 + cout << "gr_v2[Z]: " << p[gr_v2][Z] << "\n";
  469 + cout << "d_zdx: " << d_zdx << "\n";
  470 + cout << "d_zdy: " << d_zdy << "\n";
  471 + cout << "-------------------------------\n";
  472 + } */
  473 +
  474 + //if(!strncmp(p.get_id(), "DEBUG", 29)) {
  475 + // solange zeichnen, bis der unterste y erreicht ist
  476 + while(act_ceily < y_size) {
  477 + double x_inc_l, x_inc_r, z_inc_l, z_inc_r;
  478 +
  479 + // naechste linke und rechte Kante finden deren hoehe>0 und
  480 + // das linke und rechte x-Increment ermitteln.
  481 + if((int)ceil(clipped[end_left][Y]) == act_ceily) {
  482 + do {
  483 + start_left=end_left;
  484 + if(start_left == bottom) {
  485 + return;
  486 + }
  487 + end_left=(end_left-1<0)?end_left-1+clipped.card():end_left-1;
  488 + } while((int)ceil(clipped[end_left][Y]) == act_ceily);
  489 +
  490 + act_y=clipped[start_left][Y];
  491 + act_ceily=(int)ceil(act_y);
  492 +
  493 + x_inc_l=(clipped[end_left][X]-clipped[start_left][X])/
  494 + (clipped[end_left][Y]-clipped[start_left][Y]);
  495 + z_inc_l=x_inc_l*d_zdx;
  496 +
  497 + act_x_l=clipped[start_left][X];
  498 + // Subpixelkorrektur
  499 + act_x_l+=((double)act_ceily-act_y)*x_inc_l;
  500 + act_z_l=clipped[start_left][Z];
  501 + act_z_l+=((double)act_ceily-act_y)*z_inc_l;
  502 + }
  503 + if((int)ceil(clipped[end_right][Y]) == act_ceily) {
  504 + do {
  505 + start_right=end_right;
  506 + if(start_right == bottom) {
  507 + return;
  508 + }
  509 + end_right=(end_right+1)%clipped.card();
  510 + } while((int)ceil(clipped[end_right][Y]) == act_ceily);
  511 +
  512 + act_y=clipped[start_right][Y];
  513 + act_ceily=(int)ceil(act_y);
  514 +
  515 + x_inc_r=(clipped[end_right][X]-clipped[start_right][X])/
  516 + (clipped[end_right][Y]-clipped[start_right][Y]);
  517 + z_inc_r=x_inc_r*d_zdx;
  518 +
  519 + act_x_r=clipped[start_right][X];
  520 + // Subpixelkorrektur
  521 + act_x_r+=((double)act_ceily-act_y)*x_inc_r;
  522 + act_z_r=clipped[start_right][Z];
  523 + act_z_r+=((double)act_ceily-act_y)*z_inc_r;
  524 + }
  525 +
  526 + // bis zu welchem der beiden Vertexe (links o. rechts) muss ich?
  527 + unsigned togo=((int)ceil(clipped[end_left][Y])-act_ceily <=
  528 + (int)ceil(clipped[end_right][Y])-act_ceily)?
  529 + end_left:end_right;
  530 +
  531 + for(; act_ceily < (int)ceil(clipped[togo][Y]); act_ceily++) {
  532 + unsigned char* adr=adr_of_point((act_x_l<act_x_r)?
  533 + (int)ceil(act_x_l):
  534 + (int)ceil(act_x_r),
  535 + act_ceily);
  536 +
  537 + unsigned len=abs((int)ceil(act_x_r)-(int)ceil(act_x_l));
  538 + int _X=(act_x_l<act_x_r)?(int)ceil(act_x_l):(int)ceil(act_x_r);
  539 +
  540 + //double act_z=(act_x_l<act_x_r)?act_z_l:act_z_r;
  541 + double act_row_z=(act_x_l<act_x_r)?act_z_l:act_z_r;
  542 +
  543 + for(unsigned i=0; i<len; i++) {
  544 + double _Z=1/act_row_z;
  545 + //if(zbuf[_X+i][act_ceily] > _Z) {
  546 + draw_point_at_paddress(&adr, col);
  547 + zbuf[_X+i][act_ceily]=_Z;
  548 + //}
  549 + // if(!strncmp(p.get_id(), "DEBUG", 29)) {
  550 + // printf("%03ld,%03ld,%10.7f ", _X+i, act_ceily, act_row_z);
  551 + // }
  552 + act_row_z+=d_zdx;
  553 + }
  554 +
  555 + act_x_l+=x_inc_l;
  556 + act_x_r+=x_inc_r;
  557 + act_z_l+=z_inc_l;
  558 + act_z_l+=d_zdy;
  559 + act_z_r+=z_inc_r;
  560 + act_z_r+=d_zdy;
  561 +
  562 + // if(!strncmp(p.get_id(), "DEBUG", 29)) {
  563 + // cout << "\n";
  564 + // }
  565 + }
  566 + }
  567 + //}
  568 +}
  1 +/**
  2 + * \file rasterize.h
  3 + *
  4 + * \brief Methoden um auf ein Canvas zu zeichnen
  5 + *
  6 + * Der rasterizer stellt Methoden zur verf&uuml;gung um auf ein canvas zu
  7 + * zeichnen. Darunter den Canvas zu leeren, Punkt, Linie, Polygon
  8 + * (gef&uuml;llt und ungef&uuml;llt) und Polyeder zeichnen und die Farbe
  9 + * eines bestimmten Punktes im Zeichenpuffer ermitteln.
  10 + * Diese Klasse ist abstrakt. Ein Rasterizer wird immer von einem
  11 + * Canvas erzeugt werden, damit man einen zu diesem Canvas passenden
  12 + * Rasteriser hat. Implementiert ist ein Software-Rasterizer zum zeichnen
  13 + * auf ein X11 oder X11-shm Canvas.
  14 + *
  15 + * \author Georg Steffers <georg@steffers.org>
  16 + *
  17 + * \date 04.12.2003
  18 + *
  19 + * \version ..2002 (Georg Steffers): erste funktionierende Implementation
  20 + * \version 04.12.2003 (Georg Steffers): beginn der Dokumentation via doxygen
  21 + */
  22 +
  23 +/*
  24 + * Copyright (C)2003 Georg Steffers
  25 + *
  26 + * This program is free software; you can redistribute it and/or modify
  27 + * it under the terms of the GNU General Public License as published by
  28 + * the Free Software Foundation; either version 2 of the License, or
  29 + * (at your option) any later version.
  30 + *
  31 + * This program is distributed in the hope that it will be useful,
  32 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  33 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  34 + * GNU General Public License for more details.
  35 + *
  36 + * You should have received a copy of the GNU General Public License
  37 + * along with this program; if not, write to the Free Software
  38 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  39 + */
  40 +
  41 +#ifndef __rasterizer_h__
  42 +#define __rasterizer_h__
  43 +
  44 +#include "canvas_imps/canvas_imp.h"
  45 +#include "geometry/polygon.h"
  46 +#include "geometry/polyeder.h"
  47 +
  48 +class rasterizer {
  49 + protected:
  50 + unsigned x_size;
  51 + unsigned y_size;
  52 +
  53 + canvas_imp* sinfo;
  54 +
  55 + vertex_list screen_p_vl;
  56 + polygon screen_p;
  57 +
  58 + double** zbuf;
  59 +
  60 + public:
  61 + rasterizer(unsigned = 0, unsigned = 0, canvas_imp* = NULL);
  62 +
  63 + virtual void clear_buffer(void) const=0;
  64 + virtual void draw_point(unsigned x, unsigned y,
  65 + unsigned long col) const=0;
  66 + virtual void line(double, double, double, double,
  67 + unsigned long) const=0;
  68 + virtual void draw_polygon_flat(const polygon&, unsigned long) const=0;
  69 + virtual void draw_polygon_wire(const polygon&, unsigned long) const=0;
  70 + virtual void draw_polyeder_wire(const polyeder&, unsigned long) const=0;
  71 + unsigned long get_color(unsigned red, unsigned green, unsigned blue) {
  72 + return sinfo->ext_to_native(red, green, blue);
  73 + }
  74 +
  75 + virtual unsigned get_x_size(void) const { return x_size; }
  76 + virtual unsigned get_y_size(void) const { return y_size; }
  77 +};
  78 +
  79 +class sw_rasterizer : public rasterizer {
  80 + private:
  81 + unsigned char* adr_of_point(unsigned, unsigned) const;
  82 + void draw_point_at_paddress(unsigned char**, unsigned long) const;
  83 +
  84 + public:
  85 + sw_rasterizer(unsigned xs, unsigned ys, canvas_imp* ci) :
  86 + rasterizer(xs, ys, ci) {}
  87 +
  88 + void clear_buffer(void) const;
  89 + void draw_point(unsigned x, unsigned y, unsigned long col) const;
  90 + void line(double, double, double, double, unsigned long) const;
  91 + void draw_polygon_flat(const polygon&, unsigned long) const;
  92 + void draw_polygon_wire(const polygon&, unsigned long) const;
  93 + void draw_polyeder_wire(const polyeder&, unsigned long) const;
  94 +};
  95 +
  96 +#endif // __rasterize_h__
  1 +#include "math/Mmn.h"
  2 +#include <time.h>
  3 +#include <sys/timeb.h>
  4 +
  5 +int main(void) {
  6 + double x0=-1, x1=1, y0=0, y1=0;
  7 + double x0s=-1, x1s=1, y0s=1, y1s=-2;
  8 + time_t secs;
  9 + unsigned short ms;
  10 + struct timeb tb1;
  11 + struct timeb tb2;
  12 + int i;
  13 + double x, y;
  14 +
  15 + double a[2][3]={{y1-y0, -(x1-x0), -(x1*y0-y1*x0)},
  16 + {y1s-y0s, -(x1s-x0s), -(x1s*y0s-y1s*x0s)}};
  17 + Mmn<double> mat((double*)a, 2, 3);
  18 +
  19 + mat.print();
  20 + ftime(&tb1);
  21 + for(i=0; i<1000; i++)
  22 + mat.solve();
  23 + ftime(&tb2);
  24 +
  25 + cout << tb1.time << ":" << tb1.millitm << "\n";
  26 + cout << tb2.time << ":" << tb2.millitm << "\n";
  27 + cout << tb2.time-tb1.time << ":" << tb2.millitm-tb1.millitm << "\n";
  28 +
  29 + ftime(&tb1);
  30 + for(i=0; i<1000; i++) {
  31 + x=x0+((((x1s-x0s)*(y0-y0s))+((y1s-y0s)*(x0s-x0)))/
  32 + (((x1-x0)*(y1s-y0s))-((y1-y0)*(x1s-x0s))))*(x1-x0);
  33 +
  34 + y=y0+((((x1s-x0s)*(y0-y0s))+((y1s-y0s)*(x0s-x0)))/
  35 + (((x1-x0)*(y1s-y0s))-((y1-y0)*(x1s-x0s))))*(y1-y0);
  36 + }
  37 + ftime(&tb2);
  38 +
  39 + cout << tb1.time << ":" << tb1.millitm << "\n";
  40 + cout << tb2.time << ":" << tb2.millitm << "\n";
  41 + cout << tb2.time-tb1.time << ":" << tb2.millitm-tb1.millitm << "\n";
  42 +
  43 + /*
  44 + * Fazit: nach einigen Testläufen mit diesem Programm hat sich ergeben, das
  45 + * beide Methoden keine messbaren Zeitunterschied im 1000stel Sekundenbereich
  46 + + haben, daher faworisiere ich die Methode über das lösen des
  47 + * Gleichungssystems, da diese universeller (auch mit 3 Geraden) einsetzbar
  48 + * und auch verständlicher ist (man braucht keine Formeln herleiten.
  49 + *
  50 + * Wenn ich die berechnungen 1000 mal ausführe habe die Gleichungen einen
  51 + * deutlichen vorteil. Daher nehme ich wohl doch sie...
  52 + */
  53 + return 0;
  54 +}
  1 +CC=gcc
  2 +CPP=g++
  3 +#CFLAGS=-ggdb
  4 +CXXFLAGS=
  5 +MAKE=make
  6 +
  7 +INC_X11=-I/usr/X11R6/include
  8 +
  9 +OBJECTS=canvas_x11.o canvas_x11_shm.o disp_x11.o xclass.o
  10 +
  11 +%.o: %.cpp
  12 + $(CPP) $(CFLAGS) $(CXXFLAGS) $(INC_X11) -c $*.cpp
  13 +
  14 +.PHONY : all clean
  15 +
  16 +all: $(OBJECTS)
  17 +
  18 +clean:
  19 + @rm -f *.o
  1 +using namespace std;
  2 +
  3 +#include <cstdlib>
  4 +
  5 +#include "canvas_x11.h"
  6 +#include "../canvas_imps/canvas_imp_rgb.h"
  7 +
  8 +canvas_x11::canvas_x11(unsigned xs, unsigned ys) : canvas(xs, ys) {
  9 + disp=new xdisplay();
  10 + scr=disp->defaultscreen();
  11 + win=new xwindow(scr->getrootwin(), 100, 100, 1, x_size, y_size);
  12 + win->map();
  13 +
  14 + switch(scr->getvisual()->c_class) {
  15 + XVisualInfo vi;
  16 + int result;
  17 +
  18 + case TrueColor:
  19 + result=XMatchVisualInfo(disp->getdisplay(), disp->defaultscreenid(),
  20 + scr->getdepth(), TrueColor, &vi);
  21 + if(result)
  22 + sinfo=new canvas_imp_rgb(scr->getvisual()->red_mask,
  23 + scr->getvisual()->green_mask,
  24 + scr->getvisual()->blue_mask,
  25 + scr->getbytespp(), vi.depth/8);
  26 + else {
  27 + exit(EXIT_FAILURE);
  28 + }
  29 + break;
  30 +
  31 + case PseudoColor:
  32 + case StaticColor:
  33 + case GrayScale:
  34 + case StaticGray:
  35 + case DirectColor:
  36 + exit(EXIT_FAILURE);
  37 + }
  38 +
  39 + sinfo->p_screenbuf=new unsigned char[x_size*y_size*scr->getbytespp()];
  40 +
  41 + ximg=XCreateImage(disp->getdisplay(), scr->getvisual(), scr->getdepth(),
  42 + ZPixmap, 0, (char*)sinfo->p_screenbuf,
  43 + x_size, y_size, scr->getscanlinepad(), 0);
  44 +}
  45 +
  46 +canvas_x11::~canvas_x11() {
  47 + delete sinfo;
  48 + if(ximg) {
  49 + XDestroyImage(ximg);
  50 + ximg=NULL;
  51 + }
  52 + delete disp;
  53 +}
  54 +
  55 +void canvas_x11::create_buffer(void) {
  56 + // wenn ich factorys habe sollte ich irgendwie das buffer erzeugen
  57 + // auslagern, da ich bei shm den buffer aus dem ximg erzeuge und
  58 + // ansonsten andersherum, sonst hab ich noch keine rechte idee wie
  59 + // ich das konsistent bewerkstelligen kann...
  60 +}
  61 +
  62 +void canvas_x11::blit_screen(void) {
  63 + while(blit != NO_BLIT) {}
  64 +
  65 + blit=BLIT;
  66 + XPutImage(disp->getdisplay(), win->getwindow(), scr->getgc(),
  67 + ximg, 0,0,0,0, x_size, y_size);
  68 + blit=NO_BLIT;
  69 +}
  1 +/**
  2 + * \file canvas_x11.h
  3 + *
  4 + * \brief Ein X11-Canvas
  5 + *
  6 + * Die X11-Implementaton eines Canvas, hier ist ein XImage der Speicherbereich
  7 + * in den geschrieben wird.
  8 + *
  9 + * \author Georg Steffers <georg@steffers.org> [gs]
  10 + *
  11 + * \date 04.12.2003
  12 + *
  13 + * \version ..2002 [gs]: erste funktionierende Implementation
  14 + * \version 04.12.2003 [gs]: beginn der Dokumentation via doxygen
  15 + * \version 19.12.2003 [gs]: draw_text hinzugefügt, es schreibt &uuml;ber
  16 + * XDrawImageString einen Text in meine
  17 + * Window. (Brauche ich f&uuml;r DEBUG-Ausgaben)
  18 + */
  19 +
  20 +/*
  21 + * Copyright (C)2003 Georg Steffers
  22 + *
  23 + * This program is free software; you can redistribute it and/or modify
  24 + * it under the terms of the GNU General Public License as published by
  25 + * the Free Software Foundation; either version 2 of the License, or
  26 + * (at your option) any later version.
  27 + *
  28 + * This program is distributed in the hope that it will be useful,
  29 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  30 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  31 + * GNU General Public License for more details.
  32 + *
  33 + * You should have received a copy of the GNU General Public License
  34 + * along with this program; if not, write to the Free Software
  35 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  36 + */
  37 +
  38 +#ifndef __canvas_x11_h__
  39 +#define __canvas_x11_h__
  40 +
  41 +#include "xclass.h"
  42 +#include "../canvas.h"
  43 +#include "../event_source.h"
  44 +
  45 +class disp_x11;
  46 +class canvas_x11 : public canvas {
  47 + friend class disp_x11;
  48 +
  49 + protected:
  50 + xdisplay* disp;
  51 + xscreen* scr;
  52 + xwindow* win;
  53 +
  54 + XImage* ximg;
  55 +
  56 + virtual void create_buffer(void);
  57 +
  58 + public:
  59 + virtual void draw_text(int x, int y, char* text, int length) {
  60 + XDrawImageString(disp->getdisplay(),
  61 + win->getwindow(),
  62 + scr->getgc(),
  63 + x, y, text, length);
  64 + }
  65 +
  66 + canvas_x11(unsigned, unsigned);
  67 + virtual ~canvas_x11();
  68 +
  69 + virtual rasterizer* create_rasterizer(void) {
  70 + return new sw_rasterizer(x_size, y_size, sinfo);
  71 + }
  72 + Display* get_display(void) { return disp->getdisplay(); }
  73 + Window get_window(void) { return win->getwindow(); }
  74 + virtual void open_screen(void) {}
  75 + virtual void blit_screen(void);
  76 +};
  77 +
  78 +class canvas_x11_factory : public canvas_factory {
  79 + public:
  80 + canvas* create(unsigned xs, unsigned ys) const {
  81 + return new canvas_x11(xs, ys);
  82 + }
  83 +};
  84 +
  85 +#endif // __canvas_x11_h__
  1 +using namespace std;
  2 +
  3 +#include <cstdlib>
  4 +
  5 +#include "canvas_x11_shm.h"
  6 +
  7 +canvas_x11_shm::canvas_x11_shm(unsigned xs, unsigned ys) :
  8 + canvas_x11(xs, ys) {
  9 + XDestroyImage(ximg);
  10 + //delete [] sinfo->p_screenbuf;
  11 +
  12 + ximg = XShmCreateImage(disp->getdisplay(), scr->getvisual(),
  13 + scr->getdepth(), ZPixmap, 0, &shminfo,
  14 + x_size, y_size);
  15 +
  16 + shminfo.shmid=shmget(IPC_PRIVATE, ximg->bytes_per_line*ximg->height,
  17 + IPC_CREAT | 0777);
  18 +
  19 + if(shminfo.shmid < 0) {
  20 + XDestroyImage(ximg);
  21 + ximg=NULL;
  22 + exit(EXIT_FAILURE);
  23 + }
  24 + else {
  25 + shminfo.shmaddr=ximg->data=(char*)shmat(shminfo.shmid,0,0);
  26 + if(shminfo.shmaddr == (char*)-1) {
  27 + XDestroyImage(ximg);
  28 + ximg=NULL;
  29 + exit(EXIT_FAILURE);
  30 + }
  31 + else {
  32 + shminfo.readOnly=false;
  33 + XShmAttach(disp->getdisplay(), &shminfo);
  34 + }
  35 + }
  36 +
  37 + sinfo->p_screenbuf=(unsigned char*)(ximg->data);
  38 +}
  39 +
  40 +canvas_x11_shm::~canvas_x11_shm() {
  41 + XShmDetach(disp->getdisplay(), &shminfo);
  42 + if(ximg) {
  43 + XDestroyImage(ximg);
  44 + ximg=NULL;
  45 + }
  46 + shmdt(shminfo.shmaddr);
  47 + shmctl(shminfo.shmid, IPC_RMID, NULL);
  48 +}
  49 +
  50 +void canvas_x11_shm::blit_screen(void) {
  51 + while(blit != NO_BLIT) {}
  52 +
  53 + blit=BLIT;
  54 + XShmPutImage(disp->getdisplay(), win->getwindow(), scr->getgc(),
  55 + ximg, 0,0,0,0, x_size, y_size, false);
  56 + blit=NO_BLIT;
  57 +}
  1 +#ifndef __canvas_x11_shm_h__
  2 +#define __canvas_x11_shm_h__
  3 +
  4 +#include <X11/Xlib.h>
  5 +#include <X11/extensions/XShm.h>
  6 +
  7 +#include <sys/ipc.h>
  8 +#include <sys/shm.h>
  9 +
  10 +#include "canvas_x11.h"
  11 +#include "xclass.h"
  12 +
  13 +class canvas_x11_shm : public canvas_x11 {
  14 + protected:
  15 + XShmSegmentInfo shminfo;
  16 +
  17 + virtual void create_buffer(void) {}
  18 +
  19 + public:
  20 + canvas_x11_shm(unsigned, unsigned);
  21 + virtual ~canvas_x11_shm();
  22 +
  23 + virtual void open_screen(void) {}
  24 + virtual void blit_screen(void);
  25 +};
  26 +
  27 +class canvas_x11_shm_factory : public canvas_factory {
  28 + public:
  29 + canvas* create(unsigned xs, unsigned ys) const {
  30 + return new canvas_x11_shm(xs, ys);
  31 + }
  32 +};
  33 +
  34 +#endif // __canvas_x11_shm_h__
  1 +using namespace std;
  2 +
  3 +#include <cstdlib>
  4 +#include <iostream>
  5 +
  6 +#include "disp_x11.h"
  7 +
  8 +void disp_x11::go(void) {
  9 + XEvent event;
  10 + char ch;
  11 + KeySym keysym;
  12 + bool e_chk;
  13 +
  14 + canvas_x11* screen=(canvas_x11*)e_src;
  15 + xwindow* win=screen->win;
  16 +
  17 + if(!halt_f)
  18 + e_chk=XCheckWindowEvent(win->getxscr()->getxdisp()->getdisplay(),
  19 + win->getwindow(), KeyPressMask|ExposureMask,
  20 + &event);
  21 + else {
  22 + e_chk=true;
  23 + XWindowEvent(win->getxscr()->getxdisp()->getdisplay(),
  24 + win->getwindow(), KeyPressMask|ExposureMask,
  25 + &event);
  26 + }
  27 + if(e_chk) {
  28 + switch(event.type) {
  29 + case KeyPress:
  30 + XLookupString(&event.xkey, &ch, 1, &keysym, NULL);
  31 + if(!cb[Key].is_null())
  32 + cb[Key](e_src, (void*)&ch);
  33 + break;
  34 +
  35 + case Expose:
  36 + if(event.xexpose.count==0) {
  37 + if(!cb[Draw].is_null()) {
  38 + //semop(working, &work, 1);
  39 + cb[Draw](e_src, (void*)&ch);
  40 + //semop(working, &no_work, 1);
  41 + }
  42 + }
  43 + break;
  44 + }
  45 + }
  46 + else {
  47 + if(!halt_f) {
  48 + if(!cb[Idle].is_null()) {
  49 + //semop(working, &work, 1);
  50 + cb[Idle](e_src, NULL);
  51 + //semop(working, &no_work, 1);
  52 + }
  53 + }
  54 + }
  55 +
  56 + if(!halt_f)
  57 + XSync(win->getxscr()->getxdisp()->getdisplay(), false);
  58 +}
  59 +
  60 +void disp_x11::trigger_event(event ev) {
  61 + canvas_x11* screen=(canvas_x11*)e_src;
  62 + xwindow* win=screen->win;
  63 +
  64 + switch(ev) {
  65 + case Draw:
  66 + XEvent e;
  67 + e.type = Expose;
  68 + e.xexpose.send_event = true;
  69 + e.xexpose.display = win->getxscr()->getxdisp()->getdisplay();
  70 + e.xexpose.window = win->getwindow();
  71 + e.xexpose.x = e.xexpose.y = 0;
  72 + e.xexpose.width = e.xexpose.height = 0;
  73 + e.xexpose.count = 0;
  74 +
  75 + XSendEvent(win->getxscr()->getxdisp()->getdisplay(),
  76 + win->getwindow(),
  77 + true,
  78 + ExposureMask,
  79 + &e);
  80 + break;
  81 +
  82 + case Stop:
  83 + if(!cb[Stop].is_null())
  84 + cb[Stop](e_src, NULL);
  85 + }
  86 +}
  1 +#ifndef __disp_x11_h__
  2 +#define __disp_x11_h__
  3 +
  4 +#include "canvas_x11.h"
  5 +#include "../dispatcher.h"
  6 +#include <sys/types.h>
  7 +#include <sys/ipc.h>
  8 +#include <sys/sem.h>
  9 +
  10 +class disp_x11 : public dispatcher {
  11 + private:
  12 + int working;
  13 + struct sembuf work;
  14 + struct sembuf no_work;
  15 +
  16 + public:
  17 + canvas_x11* a;
  18 +
  19 + disp_x11(event_source* w) : dispatcher(w) {
  20 + working=semget(IPC_PRIVATE, 1, IPC_CREAT);
  21 + work.sem_num=0;
  22 + work.sem_op=-1;
  23 + work.sem_flg=0;
  24 + no_work.sem_num=0;
  25 + no_work.sem_op=1;
  26 + no_work.sem_flg=0;
  27 + }
  28 + disp_x11(disp_x11& d) : dispatcher(d) {}
  29 + ~disp_x11() {
  30 + semctl(working, 0, IPC_RMID, NULL);
  31 + }
  32 +
  33 + void go(void);
  34 + void trigger_event(event);
  35 +};
  36 +
  37 +class disp_x11_factory : public dispatcher_factory {
  38 + public:
  39 + dispatcher* create(event_source* es) const {
  40 + return new disp_x11(es);
  41 + }
  42 +};
  43 +
  44 +#endif // __disp_x11__
  1 +using namespace std;
  2 +
  3 +#include <cstdio>
  4 +#include <cstdlib>
  5 +#include <cstring>
  6 +
  7 +#include "xclass.h"
  8 +
  9 +xdisplay::xdisplay(char* name) {
  10 + if(name) {
  11 + display_name=new char[strlen(name)+1];
  12 + strcpy(display_name, name);
  13 + }
  14 + else {
  15 + display_name=NULL;
  16 + }
  17 +
  18 + /* Connect to X server */
  19 + if ((display=XOpenDisplay(display_name)) == NULL)
  20 + throw noconnect_exception();
  21 +
  22 + wincount=0;
  23 + screen_anz=ScreenCount(display);
  24 + default_screen=DefaultScreen(display);
  25 + screens=new xscreen*[screen_anz];
  26 +
  27 + for(int i=0; i<screen_anz; i++) {
  28 + screens[i]=new xscreen(this, i);
  29 + }
  30 +
  31 + font_info=NULL;
  32 +}
  33 +
  34 +xdisplay::xdisplay(const xdisplay& xd) {
  35 + if(xd.display_name) {
  36 + display_name=new char[strlen(xd.display_name)+1];
  37 + strcpy(display_name, xd.display_name);
  38 + }
  39 + else {
  40 + display_name=NULL;
  41 + }
  42 +
  43 + display=xd.display;
  44 + wincount=xd.wincount;
  45 + screen_anz=xd.screen_anz;
  46 + default_screen=xd.default_screen;
  47 + screens=new xscreen*[screen_anz];
  48 +
  49 + for(int i=0; i<screen_anz; i++) {
  50 + screens[i]=(xd.screens)[i];
  51 + }
  52 +
  53 + font_info=NULL;
  54 +}
  55 +
  56 +xdisplay::~xdisplay() {
  57 + if(display_name)
  58 + delete [] display_name;
  59 +
  60 + // das ueberlass ich dem Destructor von xscreen!
  61 +// for(int i=0; i<wincount; i++)
  62 +// delete wins[i];
  63 +// delete [] wins;
  64 +
  65 + //for(int i=0; i<screen_anz; i++)
  66 + // delete screens[i];
  67 + //delete [] screens;
  68 +
  69 + XCloseDisplay(display);
  70 +}
  71 +
  72 +xdisplay& xdisplay::operator=(const xdisplay& xd) {
  73 + if(xd.display_name) {
  74 + display_name=new char[strlen(xd.display_name)+1];
  75 + strcpy(display_name, xd.display_name);
  76 + }
  77 + else {
  78 + display_name=NULL;
  79 + }
  80 +
  81 + display=xd.display;
  82 + wincount=xd.wincount;
  83 + screen_anz=xd.screen_anz;
  84 + default_screen=xd.default_screen;
  85 + screens=new xscreen*[screen_anz];
  86 +
  87 + for(int i=0; i<screen_anz; i++) {
  88 + screens[i]=(xd.screens)[i];
  89 + }
  90 +
  91 + font_info=NULL;
  92 +
  93 + return *this;
  94 +}
  95 +
  96 +xscreen* xdisplay::defaultscreen(void) {
  97 + return screens[default_screen];
  98 +}
  99 +
  100 +void xdisplay::loadfont(char* fname) {
  101 + /* Load font and get font information structure */
  102 + if((font_info = XLoadQueryFont(display,fname)) == NULL)
  103 + throw nofont_exception();
  104 +}
  105 +
  106 +xscreen::xscreen(xdisplay* d, int screen_num) {
  107 + this->screen_num=screen_num;
  108 + this->x_disp=d;
  109 +
  110 + if(screen_num!=-1) {
  111 + XPixmapFormatValues* pixmap_formats;
  112 + int count;
  113 +
  114 + screen=XScreenOfDisplay(d->display, screen_num);
  115 +
  116 + width=WidthOfScreen(screen);
  117 + height=HeightOfScreen(screen);
  118 +
  119 + default_cm=DefaultColormapOfScreen(screen);
  120 + black_pixel=XBlackPixelOfScreen(screen);
  121 + white_pixel=XWhitePixelOfScreen(screen);
  122 +
  123 + rootwin=new xwindow(this); // Ich kann nicht this nehmen,
  124 + // da das aktuelle Object dem
  125 + // Array zugewiesen wird und
  126 + // danach weg is.
  127 +
  128 + vis=DefaultVisual(d->display, 0);
  129 +
  130 + pixmap_formats=XListPixmapFormats(d->display, &count);
  131 +
  132 + depth=0;
  133 + for(int i=0, result=0; i<count; i++) {
  134 + if(pixmap_formats[i].depth > depth) {
  135 + // OK, das vi existiert jetzt nur fuer TrueColor, ich muss
  136 + // noch fuer alle anderen VisualTypes eins einbauen.
  137 + if(XMatchVisualInfo(d->display, d->default_screen,
  138 + pixmap_formats[i].depth, TrueColor, &vi)) {
  139 + depth=pixmap_formats[i].depth;
  140 + bytespp=pixmap_formats[i].bits_per_pixel/8;
  141 + scanline_pad=pixmap_formats[i].scanline_pad;
  142 + }
  143 + }
  144 + }
  145 +
  146 + gc=DefaultGC(d->display, d->defaultscreenid());
  147 + }
  148 + else {
  149 + screen=NULL;
  150 + rootwin=NULL;
  151 + }
  152 +}
  153 +
  154 +xscreen::xscreen(const xscreen& scr) {
  155 + x_disp=scr.x_disp;
  156 + screen_num=scr.screen_num;
  157 + screen=scr.screen;
  158 + rootwin=scr.rootwin;
  159 +
  160 + width=scr.width;
  161 + height=scr.height;
  162 + vis=scr.vis;
  163 +
  164 + memcpy(&vi, &scr.vi, sizeof(XVisualInfo));
  165 +
  166 + depth=scr.depth;
  167 + bytespp=scr.bytespp;
  168 + scanline_pad=scr.scanline_pad;
  169 +
  170 + memcpy(&gc, &scr.gc, sizeof(GC));
  171 +
  172 + default_cm=scr.default_cm;
  173 + black_pixel=scr.black_pixel;
  174 + white_pixel=scr.white_pixel;
  175 +}
  176 +
  177 +xscreen::~xscreen() {
  178 + delete rootwin;
  179 +
  180 + XFreeGC(x_disp->display, gc);
  181 + XFreeColormap(x_disp->display, default_cm);
  182 +}
  183 +
  184 +xscreen& xscreen::operator=(const xscreen& scr) {
  185 + x_disp=scr.x_disp;
  186 + screen_num=scr.screen_num;
  187 + screen=scr.screen;
  188 + rootwin=scr.rootwin;
  189 +
  190 + width=scr.width;
  191 + height=scr.height;
  192 + vis=scr.vis;
  193 +
  194 + memcpy(&vi, &scr.vi, sizeof(XVisualInfo));
  195 +
  196 + depth=scr.depth;
  197 + bytespp=scr.bytespp;
  198 + scanline_pad=scr.scanline_pad;
  199 +
  200 + memcpy(&gc, &scr.gc, sizeof(GC));
  201 +
  202 + default_cm=scr.default_cm;
  203 + black_pixel=scr.black_pixel;
  204 + white_pixel=scr.white_pixel;
  205 +
  206 + return *this;
  207 +}
  208 +
  209 +xwindow* xdisplay::getXwinById(Window id) {
  210 + int i;
  211 +
  212 + for(i=0; i<wincount; i++)
  213 + if(wins[i]->window == id)
  214 + return wins[i];
  215 +
  216 + return NULL;
  217 +}
  218 +
  219 +xwindow::xwindow(xscreen* xs) {
  220 + screen=xs;
  221 + window=XRootWindowOfScreen(xs->screen);
  222 +
  223 + screen->x_disp->wincount++;
  224 + xwindow** temp=new xwindow*[screen->x_disp->wincount];
  225 +
  226 + for(int i=0; i<screen->x_disp->wincount-1; i++)
  227 + temp[i]=screen->x_disp->wins[i];
  228 +
  229 + temp[screen->x_disp->wincount-1]=this;
  230 + delete[] screen->x_disp->wins;
  231 + screen->x_disp->wins=temp;
  232 +}
  233 +
  234 +xwindow::xwindow(xwindow* win, int x, int y,
  235 + unsigned int bwidth, unsigned int width,
  236 + unsigned int height) {
  237 + screen=win->screen;
  238 +
  239 + window=XCreateSimpleWindow(screen->x_disp->display, win->window,
  240 + x, y, width, height, bwidth,
  241 + screen->black_pixel, screen->white_pixel);
  242 +
  243 + screen->x_disp->wincount++;
  244 + xwindow** temp=new xwindow*[screen->x_disp->wincount];
  245 +
  246 + for(int i=0; i<screen->x_disp->wincount-1; i++)
  247 + temp[i]=screen->x_disp->wins[i];
  248 +
  249 + temp[screen->x_disp->wincount-1]=this;
  250 + delete[] screen->x_disp->wins;
  251 + screen->x_disp->wins=temp;
  252 +
  253 + XSelectInput(screen->x_disp->display, window,
  254 + ExposureMask|KeyPressMask|ButtonPressMask|StructureNotifyMask);
  255 +}
  256 +
  257 +xwindow::xwindow(const xwindow& xw) {
  258 + screen=xw.screen;
  259 +
  260 + window=xw.window;
  261 + back=xw.back;
  262 + swapinfo=xw.swapinfo;
  263 +}
  264 +
  265 +xwindow& xwindow::operator=(const xwindow& xw) {
  266 + screen=xw.screen;
  267 +
  268 + window=xw.window;
  269 + back=xw.back;
  270 + swapinfo=xw.swapinfo;
  271 +
  272 + return *this;
  273 +}
  274 +
  275 +// Dies sollte nochmal in mehrere kleinere Methoden zum einstellen der
  276 +// diversen Dinge fuer den WM aufgesplittet werden.
  277 +void xwindow::initWM(void) {
  278 + XSizeHints* size_hints; // Informationen fuer WM ueber
  279 + // minimale Groessen fuer App
  280 + XWMHints* wm_hints; // weiter Infos fuer WM z.B. Icon
  281 + // Input/Output initialisierung
  282 + XClassHint* class_hints; // noch mehr infos fuer WM
  283 +
  284 + if (!(size_hints = XAllocSizeHints())) {
  285 + fprintf(stderr, "failure allocating memory\n");
  286 + exit(1); //throw exception...
  287 + }
  288 + if (!(wm_hints = XAllocWMHints())) {
  289 + fprintf(stderr, "failure allocating memory\n");
  290 + exit(1); //throw exception...
  291 + }
  292 + if (!(class_hints = XAllocClassHint())) {
  293 + fprintf(stderr, "failure allocating memory\n");
  294 + exit(1); //throw exception...
  295 + }
  296 +
  297 + size_hints->flags = PPosition | PSize | PMinSize;
  298 + size_hints->min_width = 300;
  299 + size_hints->min_height = 200;
  300 +
  301 + wm_hints->initial_state = NormalState;
  302 + wm_hints->input = True;
  303 + // wm_hints->icon_pixmap = icon_pixmap;
  304 + wm_hints->flags = StateHint | IconPixmapHint | InputHint;
  305 +
  306 + class_hints->res_name = "jokus"; //screen->x_disp->argv[0];
  307 + class_hints->res_class = "Basicwin";
  308 +
  309 +// XSetWMProperties(screen->x_disp->display, window, NULL, NULL, /*&iconName*/
  310 +// screen->x_disp->argv, screen->x_disp->argc, size_hints,
  311 +// wm_hints, class_hints);
  312 + XStoreName(screen->x_disp->display, window, "jokus");
  313 +}
  1 +/**
  2 + * \file xclass.h
  3 + *
  4 + * \brief Drei Klassen f&uuml;r die zentralen XWindows Objekte.
  5 + *
  6 + * Verpackt die drei zentralen Elemente f&uuml;r ein XWindows Programm
  7 + * in drei Klassen.
  8 + * <ul type="circle">
  9 + * <li>\ref xdisplay f&uuml;r das display</li>
  10 + * <li>\ref xscreen f&uuml;r alle screens</li>
  11 + * <li>\ref xwindow f&uuml;r alle windows</li>
  12 + * </ul>
  13 + * Dabei ist die Struktur so das zu ein display aus 1-n screens bestehen
  14 + * In denen dann wiederum jeweils 1-n windows existieren. Es existiert
  15 + * mindestens das rootwindow.
  16 + * Alle in dieser Datei definierten Klassen arbeiten sehr eng zusammen,
  17 + * daher ist jede friend der aller anderen.
  18 + *
  19 + * \author Georg Steffers <georg@steffers.org>
  20 + *
  21 + * \date 04.12.2003
  22 + *
  23 + * \version ..2001 (Georg Steffers): erste implementation
  24 + * \version 2001-2003 (Georg Steffers): diverse Modifikationen
  25 + * \version 05.12.2003 (Georg Steffers): beginn der Dokumentation via doxygen
  26 + */
  27 +
  28 +/*
  29 + * Copyright (C)2003 Georg Steffers
  30 + *
  31 + * This program is free software; you can redistribute it and/or modify
  32 + * it under the terms of the GNU General Public License as published by
  33 + * the Free Software Foundation; either version 2 of the License, or
  34 + * (at your option) any later version.
  35 + *
  36 + * This program is distributed in the hope that it will be useful,
  37 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  38 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  39 + * GNU General Public License for more details.
  40 + *
  41 + * You should have received a copy of the GNU General Public License
  42 + * along with this program; if not, write to the Free Software
  43 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  44 + */
  45 +
  46 +#ifndef __xclass_h__
  47 +#define __xclass_h__
  48 +
  49 +#include <X11/Xlib.h>
  50 +#include <X11/Xutil.h>
  51 +#include <X11/Xos.h>
  52 +#include <X11/Xatom.h>
  53 +#include <X11/keysym.h>
  54 +#include <X11/extensions/Xdbe.h>
  55 +
  56 +class xscreen;
  57 +class xwindow;
  58 +
  59 +/**
  60 + * \brief Das Display ist die Verbindung zum X-Server
  61 + *
  62 + * Verbindung zum X-Server, entwerder &uuml;ber TCP/IP oder
  63 + * Unix Domain Sockets. Je nach Server und Hardware auf der dieser
  64 + * l&auml;ft kann dieser 1-n screens zur verf&uuml;gung stellen.
  65 + * Es existiert zumindest der \ref default_screen.
  66 + */
  67 +class xdisplay {
  68 + friend class xscreen; //!< Da ein xscreen sehr eng mit einem xdisplay
  69 + //! zusammenarbeitet
  70 + friend class xwindow; //!< Da ein xwindow sehr eng mit einem xdisplay
  71 + //! zusammenarbeitet
  72 +
  73 + private:
  74 + // Exceptionklassen
  75 + class noconnect_exception {}; //!< no connection to display
  76 + class nofont_exception {}; //!< no font-file to load
  77 +
  78 + Display* display; //!< \brief Der Descriptor f&uuml;r die eigentliche
  79 + //! Verbindung zum X-Server
  80 + char* display_name; //!< \brief Hardwarename des Displays
  81 + //!
  82 + //! Wenn display_name NULL ist, so wird f&uuml;r
  83 + //! den Hardwarenamen der Wert der in der
  84 + //! Environmentvariable \$DISPLAY steht genommen.
  85 +
  86 + int screen_anz; //<! Anzahl moeglicher screens dieses Displays
  87 + int default_screen; //<! default screen dieses Displays
  88 + xscreen** screens; //<! Liste aller screens dieses Displays
  89 +
  90 + int wincount; //<! Anzahle der existierenden Windows
  91 + xwindow** wins; //<! Referenz zu allen Windows
  92 +
  93 + XFontStruct* font_info; //<! Fontinformationen
  94 +
  95 + public:
  96 + xdisplay(char* name=NULL); //!< Defaultkonstruktor
  97 + xdisplay(const xdisplay&); //!< Copyconstruktor
  98 + ~xdisplay(); //!< Destruktor
  99 +
  100 + xdisplay& operator=(const xdisplay&); //!< Zuweisungsoperator
  101 +
  102 + // Queryfunktionen...
  103 + Display* getdisplay(void) { return display; }
  104 + XFontStruct* getfont(void) { return font_info; }
  105 + xwindow* getXwinById(Window id);
  106 + xscreen* defaultscreen(void);
  107 + int defaultscreenid(void) { return default_screen; }
  108 + void loadfont(char* name="9x15");
  109 +};
  110 +
  111 +class xscreen {
  112 + friend class xwindow;
  113 + friend class xdisplay;
  114 +
  115 + private:
  116 + xdisplay* x_disp;
  117 +
  118 + int screen_num;
  119 + Screen* screen;
  120 + xwindow* rootwin;
  121 +
  122 + unsigned int width;
  123 + unsigned int height;
  124 +
  125 + Visual* vis;
  126 + XVisualInfo vi;
  127 +
  128 + int depth;
  129 + int bytespp;
  130 + int scanline_pad;
  131 + GC gc;
  132 +
  133 + Colormap default_cm;
  134 + unsigned long black_pixel;
  135 + unsigned long white_pixel;
  136 +
  137 + public:
  138 + xscreen(xdisplay* disp=NULL, int screen_num=-1);
  139 + xscreen(const xscreen&);
  140 + ~xscreen();
  141 +
  142 + xscreen& operator=(const xscreen&);
  143 +
  144 + // queryfunktionen.....
  145 + Screen* getscreen(void) { return screen; }
  146 + int getscreennum(void) {return screen_num; }
  147 + xdisplay* getxdisp(void) { return x_disp; }
  148 + Visual* getvisual(void) { return vis; }
  149 + int getdepth(void) { return depth; }
  150 + int getbytespp(void) { return bytespp; }
  151 + int getscanlinepad(void) { return scanline_pad; }
  152 + GC getgc(void) { return gc; }
  153 + unsigned getwidth(void) { return width; }
  154 + unsigned getheight(void) { return height; }
  155 + xwindow* getrootwin(void) { return rootwin; }
  156 + Colormap getdefaultcm(void) { return default_cm; }
  157 + unsigned long blackpixel(void) { return black_pixel; }
  158 + unsigned long whitepixel(void) { return white_pixel; }
  159 + unsigned long getcolor(unsigned short, unsigned short,
  160 + unsigned short);
  161 +};
  162 +
  163 +class xwindow {
  164 + friend class xscreen;
  165 + friend class xdisplay;
  166 +
  167 + private:
  168 + xscreen* screen;
  169 +
  170 + Window window;
  171 + XdbeBackBuffer back;
  172 + XdbeSwapInfo swapinfo;
  173 +
  174 + public:
  175 + xwindow(xwindow*, int, int, unsigned int,
  176 + unsigned int, unsigned int);
  177 + xwindow(xscreen* screen);
  178 + xwindow(const xwindow&);
  179 + xwindow() {
  180 + screen=NULL;
  181 + }
  182 + ~xwindow() {
  183 + XDestroyWindow(screen->x_disp->display, window);
  184 + }
  185 +
  186 + xwindow& operator=(const xwindow&);
  187 +
  188 + xscreen* getxscr(void) { return screen; }
  189 + Window getwindow(void) { return window; }
  190 + void initWM(void);
  191 + void map(void) { XMapWindow(screen->x_disp->display, window); }
  192 +};
  193 +
  194 +#endif // __xclass_h__
Please register or login to post a comment