opengl ओपन गेल में ऑब्जेक्ट ऑब्जेक्ट को कैसे मॉनिटर करना चाहिए?



graphics geometry (1)

मैं इस 4 डी खिलौनों के समान एक खेल का मैदान लिखने की कोशिश करना चाहता हूं, इसलिए मैंने ओपनगेल सीखना शुरू कर दिया।
मेरी वर्तमान समझ से, लोग ज्यादातर-स्थिर ऑब्जेक्ट्स के लिए वीबीओ और वर्दी परिवर्तन मैट्रिक्स का उपयोग करते हैं
(जैसे क्यूब्स, कंकाल एनीमेशन आदि, जो आमतौर पर परिवर्तनों को शामिल करता है)

मैंने यह भी सुना है कि मॉडल के बीच morphing दोनों मॉडलों को कैशिंग के लिए VBOs का उपयोग करता है, क्योंकि उनमें से दोनों अच्छी तरह से परिभाषित होंगे और बहुत ज्यादा मध्यवर्ती नहीं होंगे।

लेकिन ऊपर उल्लिखित 4 डी खिलौने में ऑब्जेक्ट्स मोर्फ़िंग और क्लीप्स बहुत हैं।
और यह संभावना है कि बीच में कोई परिभाषित मॉडल नहीं है, और कई बदलाव हैं।
(यह अब एक साधारण वर्ग हो सकता है, और बाद में आधे में काट ली गई एक स्पिकि गेंद)
इस मामले में, क्या एक उपयुक्त समाधान अद्यतन-शीर्ष- VBO-per-frame या Vertex Arrays (जो मैंने एक और प्रश्न में देखा है)?


शुरुआत के लिए मैं हाइडप्लेन द्वारा कटौती के बजाय 4D -> 3D प्रक्षेपण का उपयोग करूँगा इसका नतीजा एक समान नहीं है, लेकिन आपको अपने लक्ष्य के करीब ले जाएगा (ताकि आप बाद में यह कटौती करने के लिए अपग्रेड कर सकें)। तो इसी तरह 3D -> 2D ग्राफिक्स में उपयोग किए जाने वाले 3D -> 2D रूपांतरणों में आपको 2 विकल्प मिलते हैं, जो एक परिप्रेक्ष्य प्रक्षेपण का उपयोग कर रहा है और दूसरा केवल प्रतिपादन करते समय चौथे आयाम समन्वय की अनदेखी कर रहा है। मैं बाद का उपयोग करूँगा क्योंकि यह सरल है

  1. संरचनाओं

    इसे उतना आसान बनाने के लिए कि मैं ब्र रेंडरिंग के बजाय तार फ्रेम का उपयोग कर सकूँ। तो आपको 4 डी मेष (तार फ्रेम) को संभालना होगा। मैं 2 तालिकाओं का उपयोग करेगा:

    double pnt[];   // 4D point list (x,y,z,u)
    int  lin[];     // lines point indexes (i0,i1)
    

    पहले एक आपके जाल के सभी शीर्षबिंदु और तार फ्रेम के प्रतिनिधित्व में लाइनों से जुड़ी अंकों की दूसरी पकड़ इंडेक्स जोड़े रखता है।

  2. रूपांतरण

    अगर मैं केवल चौथे निर्देशांक की अनदेखी करूँगा तो हम वांछित कार्यक्षमता नहीं प्राप्त करेंगे। तो 4 डी आयाम काम करने के लिए हमें रेंडर करने से पहले 4 डी में हमारे जाल को 4 डी परिणत करने की ज़रूरत है। तो समरूप परिणत मैट्रिक्स का उपयोग करें और कॉल और rep कॉल करें। 4 डी में यह 4x4 रोटेशन भाग rot साथ 5x5 ऑथोनोर्मल मैट्रिक्स होना चाहिए।

    इसे अब तक आसान बनाने के लिए चिकनी घूर्णन से बचने के लिए (जैसा कि 4 डी में उतना आसान नहीं है) और इसके बजाय रैंडम रोटेशन 4x4 मैट्रिक्स की गणना करें। तो बस सभी कोशिकाओं को बेतरतीब ढंग से सेट करें <-1,+1> । प्रत्येक पंक्ति को आधार वेक्टर के रूप में संभाल लें। उन्हें ऑर्थनॉर्मल बनाने के लिए सिर्फ उन्हें यूनिट बनाते हैं और क्रॉस उत्पाद का फायदा उठाते हैं। अधिक जानकारी के लिए देखें:

    • कैसे अजगर में एक बेतरतीब ढंग से उन्मुख, उच्च आयाम चक्र उत्पन्न करने के लिए?
  3. प्रस्तुत करना

    बस अपने रूपांतरण मैट्रिक्स द्वारा प्वाइंट टेबल को परिवर्तित करें

    (x',y',z',u',W) = rep * (x,y,z,u,1)
    

    तो (x ,y , z`) लें और रेंडर करें ...

यहां 4D हाइपर क्यूब का सरल ओपनजीएल / सी ++ उदाहरण:

//---------------------------------------------------------------------------
//--- Mesh 4D: ver 0.000 ----------------------------------------------------
//---------------------------------------------------------------------------
#ifndef _mesh4D_h
#define _mesh4D_h
//---------------------------------------------------------------------------
#include <math.h>
#include "nd_math.h"
#include "list.h"
//---------------------------------------------------------------------------
const double pi   =    M_PI;
const double pi2  =2.0*M_PI;
const double pipol=0.5*M_PI;
const double deg=M_PI/180.0;
const double rad=180.0/M_PI;
//---------------------------------------------------------------------------
class mesh4D
    {
public:
    matrix<5> rep;  // 4D uniform 5x5 transform matrix

    List<double> pnt;   // 4D point list (x,y,z,u)
    List<int>    lin;   // lines point indexes (i0,i1)

    mesh4D()    {}
    mesh4D(mesh4D& a)   { *this=a; }
    ~mesh4D()   {}
    mesh4D* operator = (const mesh4D *a) { *this=*a; return this; }
    //mesh4D* operator = (const mesh4D &a) { ...copy... return this; }

    void set_randomrep();               // random oriented uniform 4D transform matrix with origin (0,0,0,0)
    void set_hypercube(double a);

    void draw();
    };
//---------------------------------------------------------------------------
void mesh4D::set_randomrep()
    {
    int i,j;
    matrix<4> rot;
    rep.unit();
    rot.rnd();
    rot.orthonormal();
    for (i=0;i<4;i++)
     for (j=0;j<4;j++)
      rep[i][j]=rot[i][j];
    }     
void mesh4D::set_hypercube(double a)
    {
    rep.unit(); // reset orientation
    pnt.num=0;  // clear point list
    lin.num=0;  // clear line list

    pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(-a);
    pnt.add(+a); pnt.add(-a); pnt.add(-a); pnt.add(-a);
    pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(-a);
    pnt.add(+a); pnt.add(+a); pnt.add(-a); pnt.add(-a);
    pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(-a);
    pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(-a);
    pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(-a);
    pnt.add(+a); pnt.add(+a); pnt.add(+a); pnt.add(-a);

    pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(+a);
    pnt.add(+a); pnt.add(-a); pnt.add(-a); pnt.add(+a);
    pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(+a);
    pnt.add(+a); pnt.add(+a); pnt.add(-a); pnt.add(+a);
    pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(+a);
    pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(+a);
    pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(+a);
    pnt.add(+a); pnt.add(+a); pnt.add(+a); pnt.add(+a);

    // A0
    lin.add( 0+0); lin.add( 0+1);
    lin.add( 0+1); lin.add( 0+3);
    lin.add( 0+3); lin.add( 0+2);
    lin.add( 0+2); lin.add( 0+0);
    // A1
    lin.add( 4+0); lin.add( 4+1);
    lin.add( 4+1); lin.add( 4+3);
    lin.add( 4+3); lin.add( 4+2);
    lin.add( 4+2); lin.add( 4+0);
    // A=A0+A1
    lin.add( 0+0); lin.add( 4+0);
    lin.add( 0+1); lin.add( 4+1);
    lin.add( 0+2); lin.add( 4+2);
    lin.add( 0+3); lin.add( 4+3);

    // B0
    lin.add( 8+0); lin.add( 8+1);
    lin.add( 8+1); lin.add( 8+3);
    lin.add( 8+3); lin.add( 8+2);
    lin.add( 8+2); lin.add( 8+0);
    // B1
    lin.add(12+0); lin.add(12+1);
    lin.add(12+1); lin.add(12+3);
    lin.add(12+3); lin.add(12+2);
    lin.add(12+2); lin.add(12+0);
    // B=B0+B1
    lin.add( 8+0); lin.add(12+0);
    lin.add( 8+1); lin.add(12+1);
    lin.add( 8+2); lin.add(12+2);
    lin.add( 8+3); lin.add(12+3);

    // hyper cube = A+B
    lin.add( 0+0); lin.add( 8+0);
    lin.add( 0+1); lin.add( 8+1);
    lin.add( 0+2); lin.add( 8+2);
    lin.add( 0+3); lin.add( 8+3);
    lin.add( 0+4); lin.add( 8+4);
    lin.add( 0+5); lin.add( 8+5);
    lin.add( 0+6); lin.add( 8+6);
    lin.add( 0+7); lin.add( 8+7);
    }
//---------------------------------------------------------------------------
void mesh4D::draw()
    {
    int i,j;
    double _zero=1e-3;
    vector<5> a,b;
    glBegin(GL_LINES);
    for (i=0;i<lin.num;)
        {
        // extrac first point
        j=lin[i]*4; i++;
        a.a[0]=pnt[j]; j++;
        a.a[1]=pnt[j]; j++;
        a.a[2]=pnt[j]; j++;
        a.a[3]=pnt[j]; j++;
        a.a[4]=1.0; // W=1
        // extrac second point
        j=lin[i]*4; i++;
        b.a[0]=pnt[j]; j++;
        b.a[1]=pnt[j]; j++;
        b.a[2]=pnt[j]; j++;
        b.a[3]=pnt[j]; j++;
        b.a[4]=1.0; // W=1
        // transform
        a=rep*a;
        b=rep*b;
        // render
        glVertex3dv(a.a);   // use just x,y,z
        glVertex3dv(b.a);   // use just x,y,z
        }
    glEnd();
    }
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------

मैं अपने गतिशील list.h टेम्पलेट का इस्तेमाल किया तो:


List<double> xxx; double xxx[];
xxx.add(5); सूची के अंत तक 5 जोड़ता है
xxx[7] एक्सेस सरणी तत्व (सुरक्षित)
xxx.dat[7] एक्सेस सरणी तत्व (असुरक्षित लेकिन तेजी से सीधी पहुंच)
xxx.num सरणी का वास्तविक इस्तेमाल किया आकार है
xxx.reset() सरणी साफ करता है और xxx.num=0 सेट करता है
xxx.allocate(100) 100 आइटमों के लिए स्थान preallocate

nd_math.h मेरी N-Dimensional computations के लिए nd_math.h है। आपको केवल 4 डी, 5 डी वेक्टर और 4x4 , रैखिक बीजगणित से 5x5 मैट्रिक्स गणित की आवश्यकता है।

दोनों लिब्स आकार में थोड़े बड़े हैं और कानूनी मुद्दों से मुझे यहां उनके कोड को साझा करने में रोक लगती है।

उपयोग सरल है:

// globals and init
mesh4D mesh
double animx=-50.0,danimx=0.0;
double animy=  0.0,danimy=2.0;
mesh.set_hypercube(0.5);

// render
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D( -2.0, 2.0, -2.0, 2.0 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotated(animx,1.0,0.0,0.0);
glRotated(animy,0.0,1.0,0.0);
mesh.draw();
glFlush();
SwapBuffers(hdc);

// some timer
animx+=danimx; if (animx>=360.0) animx-=360.0;
animy+=danimy; if (animy>=360.0) animy-=360.0;
call_render_here();

// on key press or mouse wheel or what ever
mesh.set_randomrep();

और यहां कुछ rep घुमाने के लिए पूर्वावलोकन ...

इसलिए इस तरह से आप किसी भी तार फ्रेम जाल प्रस्तुत कर सकते हैं (यहां तक ​​कि BR रेंडरिंग इस तरीके से काम करना चाहिए)।

यदि आप कटौती में अपग्रेड करना चाहते हैं , तो आपको प्रत्येक वायर-फ़्रेम लाइन को लेना चाहिए और इसके अंतरालन को हाइपरप्लेन काटने के साथ करना चाहिए अगर हम हाइपरप्लेन चुनते हैं जो बिंदु के माध्यम से चला जाता है

O(0,0,0,u_cut)

और सामान्य है

N(0,0,0,1)

तब कार्य बहुत आसान होगा। वहाँ 3 विकल्प हैं एंडपॉइंट A,B साथ बढ़त रेखा पर विचार करें:

  1. कोई चौराह नहीं

    ((A.u > u_cut)&&(B.u > u_cut)) || ((A.u < u_cut)&&(B.u < u_cut))
    

    बस ऐसे किनारे पर ध्यान न दें

  2. 1 चौराहे

    ((A.u >= u_cut)&&(B.u <= u_cut)) || ((A.u <= u_cut)&&(B.u >= u_cut))
    

    इसलिए रेखीय प्रक्षेप के माध्यम से प्रतिच्छेदन की गणना करें

    x = A.x + (B.x-A.x)*(u_cut-A.u)/(B.u-A.u)
    y = A.y + (B.y-A.y)*(u_cut-A.u)/(B.u-A.u)
    z = A.z + (B.z-A.z)*(u_cut-A.u)/(B.u-A.u)
    

    और इस तरह के बिंदु को याद रखो और इसके किनारे के किनारे के लिए भी।

  3. पूरी तरह से अंदर

    (A.u == u_cut)&&(B.u == u_cut)
    

    बस दोनों किनारों को याद करते हैं और इस किनारे को भी प्रस्तुत करते हैं

इस प्रकार सभी किनारों को संसाधित करने के बाद आपको याद किए गए चौराहों के बिंदुओं का विश्लेषण करने और किनारों के बीच कनेक्टिविटी जानकारी के आधार पर उनसे नए किनारों को बनाने की आवश्यकता है। मैं अभी तक ऐसा नहीं किया है इसलिए मैं इस के साथ मदद नहीं कर सकता। मैं एक ही पड़ोसी को साझा करने वाले यादों को कनेक्ट करने का प्रयास करूँगा, लेकिन यह सुनिश्चित नहीं होगा कि यह 4 डी में पर्याप्त है या नहीं।

अधिक जानकारी के लिए संबंधित क्यूए को देखने पर देखें I

  • ओपनजीएल में 4 डी ऑब्जेक्ट्स को विज़ुअलाइज़ करना
  • 4 डी से 3 डी परिप्रेक्ष्य प्रक्षेपण
  • 4 डी घूर्णन

परिप्रेक्ष्य के साथ [संपादन 1] कोड

//---------------------------------------------------------------------------
//--- Mesh 4D: ver 0.001 ----------------------------------------------------
//---------------------------------------------------------------------------
#ifndef _mesh4D_h
#define _mesh4D_h
//---------------------------------------------------------------------------
#include <math.h>
#include "nd_math.h"
#include "list.h"
//---------------------------------------------------------------------------
const double pi   =    M_PI;
const double pi2  =2.0*M_PI;
const double pipol=0.5*M_PI;
const double deg=M_PI/180.0;
const double rad=180.0/M_PI;
//---------------------------------------------------------------------------
class mesh4D
    {
public:
    matrix<5> rep;  // 4D uniform 5x5 transform matrix

    List<double> pnt;   // 4D point list (x,y,z,u)
    List<int>    lin;   // lines point indexes (i0,i1)

    mesh4D()    {}
    mesh4D(mesh4D& a)   { *this=a; }
    ~mesh4D()   {}
    mesh4D* operator = (const mesh4D *a) { *this=*a; return this; }
    //mesh4D* operator = (const mesh4D &a) { ...copy... return this; }

    void set_randomrep();               // random oriented uniform 4D transform matrix with origin (0,0,0,0)
    void set_hypercube(double a);

    void draw();
    };
//---------------------------------------------------------------------------
void mesh4D::set_randomrep()
    {
    int i,j;
    matrix<4> rot;
    rot.rnd();
    rot.orthonormal();
    for (i=0;i<4;i++)
     for (j=0;j<4;j++)
      rep[i][j]=rot[i][j];
    }
//---------------------------------------------------------------------------
void mesh4D::set_hypercube(double a)
    {
    rep.unit();     // reset orientation
    rep[0][4]=0.0;  // set position
    rep[1][4]=0.0;
    rep[2][4]=0.0;
    rep[3][4]=3.0*a;
    pnt.num=0;  // clear point list
    lin.num=0;  // clear line list

    pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(-a);
    pnt.add(+a); pnt.add(-a); pnt.add(-a); pnt.add(-a);
    pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(-a);
    pnt.add(+a); pnt.add(+a); pnt.add(-a); pnt.add(-a);
    pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(-a);
    pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(-a);
    pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(-a);
    pnt.add(+a); pnt.add(+a); pnt.add(+a); pnt.add(-a);

    pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(+a);
    pnt.add(+a); pnt.add(-a); pnt.add(-a); pnt.add(+a);
    pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(+a);
    pnt.add(+a); pnt.add(+a); pnt.add(-a); pnt.add(+a);
    pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(+a);
    pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(+a);
    pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(+a);
    pnt.add(+a); pnt.add(+a); pnt.add(+a); pnt.add(+a);

    // A0
    lin.add( 0+0); lin.add( 0+1);
    lin.add( 0+1); lin.add( 0+3);
    lin.add( 0+3); lin.add( 0+2);
    lin.add( 0+2); lin.add( 0+0);
    // A1
    lin.add( 4+0); lin.add( 4+1);
    lin.add( 4+1); lin.add( 4+3);
    lin.add( 4+3); lin.add( 4+2);
    lin.add( 4+2); lin.add( 4+0);
    // A=A0+A1
    lin.add( 0+0); lin.add( 4+0);
    lin.add( 0+1); lin.add( 4+1);
    lin.add( 0+2); lin.add( 4+2);
    lin.add( 0+3); lin.add( 4+3);

    // B0
    lin.add( 8+0); lin.add( 8+1);
    lin.add( 8+1); lin.add( 8+3);
    lin.add( 8+3); lin.add( 8+2);
    lin.add( 8+2); lin.add( 8+0);
    // B1
    lin.add(12+0); lin.add(12+1);
    lin.add(12+1); lin.add(12+3);
    lin.add(12+3); lin.add(12+2);
    lin.add(12+2); lin.add(12+0);
    // B=B0+B1
    lin.add( 8+0); lin.add(12+0);
    lin.add( 8+1); lin.add(12+1);
    lin.add( 8+2); lin.add(12+2);
    lin.add( 8+3); lin.add(12+3);

    // hyper cube = A+B
    lin.add( 0+0); lin.add( 8+0);
    lin.add( 0+1); lin.add( 8+1);
    lin.add( 0+2); lin.add( 8+2);
    lin.add( 0+3); lin.add( 8+3);
    lin.add( 0+4); lin.add( 8+4);
    lin.add( 0+5); lin.add( 8+5);
    lin.add( 0+6); lin.add( 8+6);
    lin.add( 0+7); lin.add( 8+7);
    }
//---------------------------------------------------------------------------
void mesh4D::draw()
    {
    int i,j;
    const double _zero=1e-3;
    double focal_length=1.0;

    vector<5> a,b;
    glBegin(GL_LINES);
    for (i=0;i<lin.num;)
        {
        // extrac first point
        j=lin[i]*4; i++;
        a.a[0]=pnt[j]; j++;
        a.a[1]=pnt[j]; j++;
        a.a[2]=pnt[j]; j++;
        a.a[3]=pnt[j]; j++;
        a.a[4]=1.0; // W=1
        // extrac second point
        j=lin[i]*4; i++;
        b.a[0]=pnt[j]; j++;
        b.a[1]=pnt[j]; j++;
        b.a[2]=pnt[j]; j++;
        b.a[3]=pnt[j]; j++;
        b.a[4]=1.0; // W=1
        // transform
        a=rep*a;
        b=rep*b;
        // perspective: camera projection plane u=0, focus at (0,0,0,-focal_length)
        if (a[3]>=0.0) a*=divide(focal_length,a[3]+focal_length); else a.zero();
        if (b[3]>=0.0) b*=divide(focal_length,b[3]+focal_length); else b.zero();
        // render
        glVertex3dv(a.a);   // use just x,y,z
        glVertex3dv(b.a);   // use just x,y,z
        }
    glEnd();
    }
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------

और पूर्वावलोकन:

[संपादन 2] ठोस मेष और क्रॉस-सेक्शन

इसलिए मैंने वास्तुकला को थोड़ा बदल दिया। मैं 4D 5x5 homogenuous ट्रांसफ़ॉर्म मैट्रिक्स ( reper4D ) को अलग फ़ाइल और 4 डी सिग्नेक्स (4 अंक 4 साइड टेट्राहेड्रों) द्वारा जोड़ा गया रंग और जाल परिभाषा को स्थानांतरित कर दिया। कट केवल सिल्लक्ज़ और कटेक्शन हाइपरप्लेन के चौराहे (जैसा ऊपर वर्णित है) का अभिकलन है, जिसके परिणामस्वरूप 3 अंक (त्रिकोण), 4 अंक (टेट्राहेड्रॉन) या 0 अंक होते हैं। जो आसानी से गाया जा सकता है (किनारों के बीच कनेक्शन का विश्लेषण करने की कोई ज़रूरत नहीं है) Btw। मुझे लगता है कि यह कैसे मिगकुरे काम करता है यहां अद्यतन कोड:

//---------------------------------------------------------------------------
//--- Mesh 4D: ver 1.000 ----------------------------------------------------
//---------------------------------------------------------------------------
#ifndef _mesh4D_h
#define _mesh4D_h
//---------------------------------------------------------------------------
#include "list.h"
#include "reper4D.h"
//---------------------------------------------------------------------------
class mesh4D
    {
public:
    reper4D rep;        // 4D uniform 5x5 transform matrix

    List<double> pnt;   // 4D point list (x,y,z,w)
    List<int>    lin;   // 4D wireframe (i0,i1)
    List<int>    fac;   // 4D simplexes (i0,i1,i2,i3)
    List<DWORD>  col;   // simplex colors (RGB)

    mesh4D()    {}
    mesh4D(mesh4D& a)   { *this=a; }
    ~mesh4D()   {}
    mesh4D* operator = (const mesh4D *a) { *this=*a; return this; }
    //mesh4D* operator = (const mesh4D &a) { ...copy... return this; }

    void set_hypercube(double a);
    void draw_cut(double w_cut);                                        // render cross section by w=w_cut hyperplane
    void draw          (double focal_length=-1.0,double w_near=-1.0);   // render mesh      (focal_length<0) -> no perspective, else perspective view in W+ direction
    void draw_wireframe(double focal_length=-1.0,double w_near=-1.0);   // render wireframe (focal_length<0) -> no perspective, else perspective view in W+ direction
    };
//---------------------------------------------------------------------------
void mesh4D::set_hypercube(double a)
    {
    const double tab_pnt[]=
        {
        -a, -a, -a, -a,
        +a, -a, -a, -a,
        -a, +a, -a, -a,
        +a, +a, -a, -a,
        -a, -a, +a, -a,
        +a, -a, +a, -a,
        -a, +a, +a, -a,
        +a, +a, +a, -a,
        -a, -a, -a, +a,
        +a, -a, -a, +a,
        -a, +a, -a, +a,
        +a, +a, -a, +a,
        -a, -a, +a, +a,
        +a, -a, +a, +a,
        -a, +a, +a, +a,
        +a, +a, +a, +a,
        };
    const int tab_lin[]=
        {
        // A0
         0+0,  0+1,
         0+1,  0+3,
         0+3,  0+2,
         0+2,  0+0,
        // A1
         4+0,  4+1,
         4+1,  4+3,
         4+3,  4+2,
         4+2,  4+0,
        // A=A0+A1
         0+0,  4+0,
         0+1,  4+1,
         0+2,  4+2,
         0+3,  4+3,
        // B0
         8+0,  8+1,
         8+1,  8+3,
         8+3,  8+2,
         8+2,  8+0,
        // B1
        12+0, 12+1,
        12+1, 12+3,
        12+3, 12+2,
        12+2, 12+0,
        // B=B0+B1
         8+0, 12+0,
         8+1, 12+1,
         8+2, 12+2,
         8+3, 12+3,
        // hyper cube = A+B
         0+0,  8+0,
         0+1,  8+1,
         0+2,  8+2,
         0+3,  8+3,
         0+4,  8+4,
         0+5,  8+5,
         0+6,  8+6,
         0+7,  8+7,
        };
    // 5x simplex per cube
    #define _cube(a0,a1,a2,a3,a4,a5,a6,a7) a1,a2,a4,a7, a0,a1,a2,a4, a2,a4,a6,a7, a1,a2,a3,a7, a1,a4,a5,a7
    // 4D hypercube = 8 cubes
    const int tab_fac[]=
        {
        _cube( 0, 1, 2, 3, 4, 5, 6, 7),
        _cube( 0, 1, 2, 3, 8, 9,10,11),
        _cube( 4, 5, 6, 7,12,13,14,15),
        _cube( 8, 9,10,11,12,13,14,15),
        _cube( 0, 1, 4, 5, 8, 9,12,13),
        _cube( 0, 2, 4, 6, 8,10,12,14),
        _cube( 1, 3, 5, 7, 9,11,13,15),
        _cube( 2, 3, 6, 7,10,11,14,15),
        };
    #undef _cube
    const DWORD tab_col[]=
        {
        //  BBGGRR,    BBGGRR,    BBGGRR,    BBGGRR,    BBGGRR,
        0x00FF0000,0x00FF0000,0x00FF0000,0x00FF0000,0x00FF0000,
        0x0000FF00,0x0000FF00,0x0000FF00,0x0000FF00,0x0000FF00,
        0x000000FF,0x000000FF,0x000000FF,0x000000FF,0x000000FF,
        0x0000FFFF,0x0000FFFF,0x0000FFFF,0x0000FFFF,0x0000FFFF,
        0x00FF00FF,0x00FF00FF,0x00FF00FF,0x00FF00FF,0x00FF00FF,
        0x00FFFF00,0x00FFFF00,0x00FFFF00,0x00FFFF00,0x00FFFF00,
        0x00FFFFFF,0x00FFFFFF,0x00FFFFFF,0x00FFFFFF,0x00FFFFFF,
        0x004080FF,0x004080FF,0x004080FF,0x004080FF,0x004080FF,
        };

    int i,n;
    vector<4> p;
    rep.reset();
    pnt.num=0; for (i=0,n=sizeof(tab_pnt)/sizeof(tab_pnt[0]);i<n;i++) pnt.add(tab_pnt[i]);
    lin.num=0; for (i=0,n=sizeof(tab_lin)/sizeof(tab_lin[0]);i<n;i++) lin.add(tab_lin[i]);
    fac.num=0; for (i=0,n=sizeof(tab_fac)/sizeof(tab_fac[0]);i<n;i++) fac.add(tab_fac[i]);
    col.num=0; for (i=0,n=sizeof(tab_col)/sizeof(tab_col[0]);i<n;i++) col.add(tab_col[i]);
    }
//---------------------------------------------------------------------------
void mesh4D::draw_cut(double w_cut)
    {
    const double _zero=1e-6;
    const int edge2[]={0,1,0,2,0,3,1,2,2,3,3,1,-1}; // simplex wireframe i0,i1
    const int edge3[]={0,1,2,3,0,1,3,1,2,3,2,0,-1}; // simplex triangles i0,i1,i2
    int e,i,j,k,k0,k1,k2,inside[4];
    DWORD rgb;
    vector<4> p[4],q[4];
    vector<3> xyz[4],nor,a,b;
    for (i=0;i<fac.num;)
        {
        rgb=col[i>>2];
        // extrac points (x,y,z,w)
        for (k=0;k<4;k++)
            {
            j=fac[i]*4; i++;
            p[k].a[0]=pnt[j]; j++;
            p[k].a[1]=pnt[j]; j++;
            p[k].a[2]=pnt[j]; j++;
            p[k].a[3]=pnt[j]; j++;
            // transform
            rep.l2g(p[k],p[k]);
            inside[k]=1;
            }
        // process edge2 and compute cross section cut intersection points
        for (e=0,k=0;edge2[e]>=0;)
            {
            k0=edge2[e]; e++;
            k1=edge2[e]; e++;
            // fully inside
            if (fabs(p[k0][3]-w_cut)+fabs(p[k1][3]-w_cut)<=_zero)
                {
                if ((k<4)&&(inside[k0])){ q[k]=p[k0]; k++; inside[k0]=0; }
                if ((k<4)&&(inside[k1])){ q[k]=p[k1]; k++; inside[k1]=0; }
                continue;
                }
            // no intersection
            if (((p[k0][3]> w_cut)&&(p[k1][3]> w_cut))||((p[k0][3]< w_cut)&&(p[k1][3]< w_cut))) continue;
            // 1 intersection
            if (k<4)
                {
                q[k]=p[k1]-p[k0];
                q[k]*=divide(w_cut-p[k0][3],p[k1][3]-p[k0][3]);
                q[k]+=p[k0];
                q[k][3]=w_cut;
                k++;
                continue;
                }
            }
        // 4D -> 3D vector
        for (k0=0;k0<k;k0++) for (k1=0;k1<3;k1++) xyz[k0][k1]=q[k0][k1];
        // render triangle
        if (k==3)
            {
            // normal
            a=xyz[1]-xyz[0];
            b=xyz[2]-xyz[1];
            nor.cross(a,b);
            nor.unit();
            // render
            glBegin(GL_TRIANGLES);
            glNormal3dv(nor.a);
            glColor4ubv((BYTE*)(&rgb));
            glVertex3dv(xyz[0].a);
            glVertex3dv(xyz[1].a);
            glVertex3dv(xyz[2].a);
            glEnd();
            }
        // render simplex
        if (k==4)
         for (e=0;edge3[e]>=0;)
            {
            k0=edge3[e]; e++;
            k1=edge3[e]; e++;
            k2=edge3[e]; e++;
            // normal
            a=xyz[k1]-xyz[k0];
            b=xyz[k2]-xyz[k1];
            nor.cross(a,b);
            nor.unit();
            // render
            glBegin(GL_TRIANGLES);
            glNormal3dv(nor.a);
            glColor4ubv((BYTE*)(&rgb));
            glVertex3dv(xyz[k0].a);
            glVertex3dv(xyz[k1].a);
            glVertex3dv(xyz[k2].a);
            glEnd();
            }
        }
    }
//---------------------------------------------------------------------------
void mesh4D::draw(double focal_length,double w_near)
    {
    const int edge3[]={0,1,2,3,0,1,3,1,2,3,2,0,-1}; // simplex triangles i0,i1,i2
    int i,j,k,k0,k1,k2;
    DWORD rgb;
    vector<4> p;
    vector<3> xyz[4],nor,a,b;

    // 4D simplexes
    glColor3f(0.3,0.3,0.3);
    for (i=0;i<fac.num;)
        {
        rgb=col[i>>2];
        // extrac points (x,y,z,w)
        for (k=0;k<4;k++)
            {
            j=fac[i]*4; i++;
            p[0]=pnt[j]; j++;
            p[1]=pnt[j]; j++;
            p[2]=pnt[j]; j++;
            p[3]=pnt[j]; j++;
            // transform
            rep.l2g(p,p);
            // perspective projection
            if (focal_length>0.0)
                {
                p[3]-=w_near;
                if (p[3]>=0.0) p*=divide(focal_length,p[3]+focal_length); else p.zero();
                }
            // 4D -> 3D vector
            xyz[k].ld(p[0],p[1],p[2]);
            }
        // render simplex
        for (k=0;edge3[k]>=0;)
            {
            k0=edge3[k]; k++;
            k1=edge3[k]; k++;
            k2=edge3[k]; k++;
            // normal
            a=xyz[k1]-xyz[k0];
            b=xyz[k2]-xyz[k1];
            nor.cross(a,b);
            nor.unit();
            // render
//          glBegin(GL_LINE_LOOP);
            glBegin(GL_TRIANGLES);
            glNormal3dv(nor.a);
            glColor4ubv((BYTE*)(&rgb));
            glVertex3dv(xyz[k0].a);
            glVertex3dv(xyz[k1].a);
            glVertex3dv(xyz[k2].a);
            glEnd();
            }
        }
    }
//---------------------------------------------------------------------------
void mesh4D::draw_wireframe(double focal_length,double w_near)
    {
    int i,j,k;
    vector<4> p[4];
    // 4D wireframe
    glColor3f(1.0,1.0,1.0);
    glBegin(GL_LINES);
    for (i=0;i<lin.num;)
        {
        // extrac points (x,y,z,w)
        for (k=0;k<2;k++)
            {
            j=lin[i]*4; i++;
            p[k].a[0]=pnt[j]; j++;
            p[k].a[1]=pnt[j]; j++;
            p[k].a[2]=pnt[j]; j++;
            p[k].a[3]=pnt[j]; j++;
            // transform
            rep.l2g(p[k],p[k]);
            // perspective projection
            if (focal_length>0.0)
                {
                p[k][3]-=w_near;
                if (p[k][3]>=0.0) p[k]*=divide(focal_length,p[k][3]+focal_length); else p[k].zero();
                }
            // render
            glVertex3dv(p[k].a);    // use just x,y,z
            }
        }
    glEnd();
    }
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------

और क्रॉस सेक्शन के लिए पूर्वावलोकन प्रस्तुत करता है:

सबसे खराब हिस्सा हाइपरक्यूब को सरलता के रूप में परिभाषित करना था ...





4d