From 4fdd846f89d0f81aec2b948d246f0383111662ab Mon Sep 17 00:00:00 2001
From: slevy <slevy>
Date: Sat, 30 Jun 2001 18:04:58 +0000
Subject: [PATCH] Add parent-to-camera (objparent()) support: objects with
 parent GV_ID_CAMERA have "o2w" transforms that are really interpreted
 relative to camera space. Also start adding per-object clip support; this
 requires change to subcameras, supplying projection parameters subc_lrbt()
 rather than a (clip-dependent) projection matrix.

---
 src/Gview.H  | 20 ++++++++---
 src/Gview.cc | 93 +++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 82 insertions(+), 31 deletions(-)

diff --git a/src/Gview.H b/src/Gview.H
index 19ec915..71fec46 100644
--- a/src/Gview.H
+++ b/src/Gview.H
@@ -17,7 +17,7 @@ typedef struct _Fl_Gview Fl_Gview;
 int Gview_add_drawer( Fl_Gview *gview,
 			void (*func)( Fl_Gview *, void *obj, void *arg ),
 			void *obj, void *arg, int id );
-void Gview_get_o2w( Fl_Gview *gview, Matrix *pos, int drawer );
+void Gview_get_o2w( Fl_Gview *gview, Matrix *pos, int drawer );	/* returns parent */
 void Gview_set_o2w( Fl_Gview *gview, CONST Matrix *pos, int drawer );
 int Gview_inpick( Fl_Gview *gview );	/* for plain-C drawers */
 void Gview_setpick( Fl_Gview *gview, void (*pickcb)(Fl_Gview *, int hits, int ents, GLuint *buf) );
@@ -103,11 +103,13 @@ class Fl_Gview : public Fl_Gl_Window {
   int usesubcam() const { return use_subc_; };
   void Tc2subc( Matrix *newT ) { Tc2subc_ = *newT; }
   const Matrix *Tc2subc() const { return &Tc2subc_; }
-  void Tsubcproj( Matrix *newT ) { Tsubcproj_ = *newT; }
-  const Matrix *Tsubcproj() const { return &Tsubcproj_; }
+  void subc_lrbt( float lrbt[4] );
+  const float *subc_lrbt() const { return subclrbt_; }
 
   const Matrix *To2w( int drawerno ) const;	/* returns &Tidentity if invalid */
   int To2w( int drawerno, const Matrix * );	/* returns zero if invalid */
+  int objparent( int drawerno ) const;		/* parent object id (0=world, -1=camera) */
+  void objparent( int drawerno, int id );		
 
   int perspective() { return persp_; }
   void perspective(int persp);
@@ -188,6 +190,9 @@ class Fl_Gview : public Fl_Gl_Window {
   static void idlepick( void *me );
 
  protected:
+
+  void glprojection( float nearclip, float farclip, const Matrix *postproj );
+
   Point qc2w_;
   Matrix Tc2w_, Tw2c_; 
 
@@ -196,7 +201,8 @@ class Fl_Gview : public Fl_Gl_Window {
   float focallen_, halfyfov_, near_, far_;
   float aspect_, stereosep_;
 
-  Matrix Tc2subc_, Tsubcproj_;
+  Matrix Tc2subc_;
+  float subclrbt_[4];  // subcam frustum tan(left),tan(right),tan(bot),tan(top)
   int use_subc_;
 
   int target_;
@@ -236,6 +242,9 @@ class Fl_Gview : public Fl_Gl_Window {
     Matrix To2w;
     char *name;
     int id;
+    int parent;			/* 0=world, GV_ID_CAMERA=attach-to-camera */
+    int objclip;		/* object has custom clip planes? */
+    float objnear, objfar;
   };
   int ndrawers_, maxdrawers_;
   struct drawer *drawers_;
@@ -275,7 +284,8 @@ class Fl_Gview : public Fl_Gl_Window {
     hasfocus_ = 0;
     use_subc_ = 0;
     Tc2subc_ = Tidentity;
-    Tsubcproj_ = Tidentity;
+    subclrbt_[0] = subclrbt_[2] = -1;
+    subclrbt_[1] = subclrbt_[3] = 1;
     nav( GV_ORBIT );
     reset( GV_ID_CAMERA );
   }
diff --git a/src/Gview.cc b/src/Gview.cc
index befa32d..602246f 100644
--- a/src/Gview.cc
+++ b/src/Gview.cc
@@ -152,12 +152,13 @@ int Fl_Gview::add_drawer( void (*func)( Fl_Gview *, void *obj, void *arg ),
   dp->To2w = Tidentity;
   dp->name = name;
   dp->id = id;
+  dp->parent = 0;
   notify();
   redraw();
   return id;
 }
 
-int Fl_Gview::withid( int id ) const {
+int Fl_Gview::withid( int id ) const {	// Which drawer[] slot is id in?
   for(int dno = 0; dno < ndrawers_; dno++)
     if(drawers_[dno].id == id)
 	return dno;
@@ -184,10 +185,54 @@ int Fl_Gview::To2w( int id, const Matrix *newT ) {
   return 1;
 }
 
+void Fl_Gview::objparent( int id, int parent ) {
+  int drawerno = withid( id );
+  if(drawerno >= 0)
+    drawers_[drawerno].parent = parent;
+}
+
+int Fl_Gview::objparent( int id ) const {
+  int drawerno = withid( id );
+  return (drawerno >= 0) ? drawers_[drawerno].parent : 0;
+}
+
+void Fl_Gview::subc_lrbt( float subclrbt[4] ) {
+  for(int k = 0; k < 4; k++)
+    subclrbt_[k] = subclrbt[k];
+}
+
 #define VIEW_CLEAR  0x1
 #define	VIEW_RED    0x2
 #define	VIEW_CYAN   0x4
 
+void Fl_Gview::glprojection( float nearclip, float farclip, const Matrix *postproj )
+{
+    glMatrixMode( GL_PROJECTION );
+    glLoadIdentity();
+    if(inpick()) {
+	GLint vp[4] = {0, 0, w(), h()};
+	gluPickMatrix( pickx_, picky_, pickwidth_, pickheight_, vp );
+    }
+    if(use_subc_) {
+	glFrustum( nearclip * subclrbt_[0], nearclip * subclrbt_[1],
+		   nearclip * subclrbt_[2], nearclip * subclrbt_[3],
+		   nearclip, farclip );
+
+    } else if(persp_) {
+	float nthf = nearclip * halfyfov_ / focallen_;
+	glFrustum( -nthf * aspect_, nthf * aspect_,
+		   -nthf, nthf,
+		   nearclip, farclip );
+    } else {
+	glOrtho( -aspect_*halfyfov_, aspect_*halfyfov_,
+		 -halfyfov_, halfyfov_,
+		  nearclip, farclip );
+    }
+    if(postproj)
+	glMultMatrixf( postproj->m );
+    glMatrixMode( GL_MODELVIEW );
+}
+
 void Fl_Gview::draw_scene( int how, const Matrix *postproj ) {
   /* draw scene */
 
@@ -211,27 +256,7 @@ void Fl_Gview::draw_scene( int how, const Matrix *postproj ) {
   glDisable( GL_COLOR_MATERIAL );
 
   if(how || postproj) {
-    glMatrixMode( GL_PROJECTION );
-    glLoadIdentity();
-    if(inpick()) {
-	GLint vp[4] = {0, 0, w(), h()};
-	gluPickMatrix( pickx_, picky_, pickwidth_, pickheight_, vp );
-    }
-    if(use_subc_) {
-	glMultMatrixf( Tsubcproj_.m );
-
-    } else if(persp_) {
-	float nthf = near_ * halfyfov_ / focallen_;
-	glFrustum( -nthf * aspect_, nthf * aspect_,
-		   -nthf, nthf,
-		   near_, far_ );
-    } else {
-	glOrtho( -aspect_*halfyfov_, aspect_*halfyfov_,
-		 -halfyfov_, halfyfov_,
-		  near_, far_ );
-    }
-    if(postproj)
-	glMultMatrixf( postproj->m );
+    glprojection( near_, far_, postproj );
 
     glMatrixMode( GL_MODELVIEW );
     if(use_subc_) {
@@ -242,15 +267,31 @@ void Fl_Gview::draw_scene( int how, const Matrix *postproj ) {
     }
   }
 
+  int curclip = 0;
+
   for(int i = 0; i < ndrawers_; i++) {
-    if(drawers_[i].func != NULL) {
+    struct drawer *dp = &drawers_[i];
+    if(dp->func != NULL) {
+	int wantclip = dp->objclip;
+	if(wantclip)
+	    glprojection( dp->objnear, dp->objfar, postproj );
+	else if(curclip)
+	    glprojection( near_, far_, postproj );
+	curclip = wantclip;
+
 	glPushMatrix();
-	glMultMatrixf( drawers_[i].To2w.m );
+	if(dp->parent == GV_ID_CAMERA) {
+	    if(use_subc_)
+		glLoadMatrixf( Tc2subc()->m );
+	    else
+		glLoadIdentity();
+	}
+	glMultMatrixf( dp->To2w.m );
 	if(inpick_) {
-	    glLoadName( drawers_[i].id );
+	    glLoadName( dp->id );
 	    glPushName(0);
 	}
-	(*drawers_[i].func)(this, drawers_[i].obj, drawers_[i].arg);
+	(*dp->func)(this, dp->obj, dp->arg);
 	if(inpick_)
 	     glPopName();
 	glPopMatrix();
-- 
GitLab