VisClient/org/hfbk/vis/visnode/VisDucts.java

Go to the documentation of this file.
00001 package org.hfbk.vis.visnode;
00002 
00003 import java.awt.event.MouseEvent;
00004 import java.nio.FloatBuffer;
00005 import java.util.ArrayList;
00006 import java.util.List;
00007 
00008 import org.dronus.gl.Buffers;
00009 import org.dronus.gl.GLUtil;
00010 import org.dronus.graph.Node;
00011 import org.hfbk.vis.visnode.VisDucts.VisDuct.Port;
00012 import org.lwjgl.opengl.GL11;
00013 import org.lwjgl.util.vector.Matrix4f;
00014 import org.lwjgl.util.vector.Vector3f;
00015 
00027 public class VisDucts extends VisNode {
00028 
00029         //javascript: client.root.add(new VisDucts());
00030         
00031         public VisDucts(Node dummy, Vector3f pos) {
00032                 super(null, pos);
00033                 
00034                 for (int i=0; i< 9; i++)
00035                         add(new VisDuct(1));
00036                 
00037                 for (int i=2; i<30; i++)  
00038                         add(new VisDuct(i)); 
00039                         
00040                 
00041         }
00042 
00043 
00052         static class VisDuct extends VisObj{
00053                 static int index=0;
00054                 
00055                 VisDuct diz=this;
00056 
00058                 Matrix4f orientation=new Matrix4f();
00059                 
00060                 VisDuct getThis(){return this;} //needed to get the owning duct of a Port 
00061                 
00064                 class Port{
00065                         float w,h;
00066                         
00067                         Vector3f center;
00069                         Vector3f normal;
00071                         Vector3f base;
00073                         List<Vector3f> polygon=new ArrayList<Vector3f>();
00074                 
00078                         Port(List<Vector3f> polygon){
00079                                 this.polygon=polygon;
00080                                 center=getCenter(polygon);
00081                                 normal=getNormal(polygon);
00082                                 
00083                                 Vector3f n0=polygon.get(0),n1=polygon.get(1),n2=polygon.get(2);
00084                                 
00085                                 base=new Vector3f();
00086                                 Vector3f baseh=new Vector3f();
00087                                 
00088                                 w=Vector3f.sub(n0,n1, base ).length();
00089                                 h=Vector3f.sub(n2,n1, baseh).length();
00090                                 
00091                                 if (h>w) base=baseh; 
00092                                 
00093                         }
00094                         
00096                         VisDuct getOwner(){return getThis();}
00097                         
00098                         void render(){
00099                                 GL11.glLineWidth(3);
00100                                 GL11.glBegin(GL11.GL_LINE_LOOP);                        
00101                                 for (Vector3f v : polygon)
00102                                         GL11.glVertex3f(v.x,v.y,v.z);                                   
00103                                 GL11.glEnd();
00104                                 GL11.glLineWidth(1);
00105                         }
00106                         
00108                         boolean isDualAspect(Port other){
00109                                 return tolerate(w, other.h) && tolerate(h, other.w);
00110                         }       
00112                         boolean isCompatible(Port other){
00113                                 return ((tolerate(w, other.w) && tolerate(h, other.h)) ||
00114                                                 isDualAspect(other)
00115                                 );
00116                         }
00117                         
00122                         float matchPlaneRotation(Vector3f other, Vector3f axis){
00123                                 float dot=Vector3f.dot(normal, other);
00124                                 
00125                                 if (dot>.9f) { //same orientation
00126                                         Vector3f.cross(normal, base, axis);
00127                                         axis.normalise();
00128                                         return 180;                                     
00129                                 }else if(dot<-.9f){ //already opposite
00130                                         return 0;
00131                                 }else { // perpendicular
00132                                         Vector3f.cross(normal, other, axis);
00133                                         axis.normalise();
00134                                         return -90;                             
00135                                 }
00136                         }
00137                         
00140                         float matchAspect(Vector3f other, Vector3f axis){
00141                                 axis.set(normal);
00142                                 float dot=Vector3f.dot(base, other);
00143                                 if (dot>.9f || dot<-.9f) { //same orientation                                   
00144                                         return 0;
00145                                 }else { // perpendicular                                        
00146                                         return -90;
00147                                 }
00148                         } 
00149                         
00150                         
00152                         final float TOLERANCE=3; //cm
00153                         boolean tolerate(float a, float b){
00154                                 return Math.abs(a-b)<TOLERANCE;
00155                         }
00156                 }
00158                 List<Port> ports=new ArrayList<Port>();
00159                 
00161                 Port candidate, candidateOwn;
00162                 
00164                 int type;
00165                 
00167                 VisDuct(int type){
00168                         super(new Node("misc/duct/"+type+".obj"), new Vector3f(index++*50,0,0));
00169                         this.type=type;
00170                         buildPorts();   
00171                         
00172                         radius*=2;
00173                 }
00174                 
00177                 void buildPorts(){
00178                         for(Group g: groups)                             
00179                                 if (g.name.matches("dock.*")) 
00180                                         ports.add(new Port(g.faces.get(0)));
00181                 }
00182                 
00184                 boolean wasDragged;
00187                 void renderSelf() {
00188                         super.renderSelf();
00189                         for (Port p: ports) {
00190                                 if (p==candidateOwn){
00191                                         if (!p.isCompatible(candidate)) GL11.glColor3f(1,0,0);
00192                                         else {
00193                                                 GL11.glColor3f(0,1,0);
00194                                         }
00195                                 }else
00196                                         GL11.glColor3f(1,1,1);
00197                                 p.render();     
00198                         }
00199                         
00200                         //if (!isDragged && wasDragged && candidate!=null && candidateOwn.isCompatible(candidate)){ 
00201                         if (!isDragged && wasDragged && candidate!=null ){  
00202                                 // this duct was dropped, and a candidate port 
00203                                 // is lit! so we join them. 
00204                                 
00205                                 //origin of other duct piece to resolve absolute port positions
00206                                 Vector3f otherOrigin=candidate.getOwner().traverse(this, new Vector3f());
00207                                 
00208                                 //traverse others port normal to our local transform
00209                                 Vector3f otherNormal=candidate.getOwner().traverse(this, candidate.normal);
00210                                 Vector3f.sub(otherNormal, otherOrigin, otherNormal);
00211                                 
00212                                 //compute rotation needed to get the ports into opposition
00213                                 Vector3f alignAxis=new Vector3f();
00214                                 float alignAngle=candidateOwn.matchPlaneRotation(otherNormal, alignAxis);
00215                                 
00216                                 if (alignAngle!=0) orientation.rotate(alignAngle/180*(float)Math.PI, alignAxis);
00217                         
00218                                 //apply transformations inbetween to allow 
00219                                 //further computations in new oriented local space.
00220                                 retransform();
00221                                 
00222                                 //now traverse the ports position to our space and get them both aligned.
00223                                 Vector3f should=candidate.getOwner().traverse(parent, candidate.center);
00224                                 Vector3f is    =                     traverse(parent, candidateOwn.center);
00225                                 Vector3f.sub(position, is, position);
00226                                 Vector3f.add(position, should, position);
00227                                 
00228                         }
00229                         
00230                         candidate=candidateOwn=null;                    
00231                         wasDragged=isDragged;
00232                         
00233                 }
00234                 
00236                 void transform() {
00237                         super.transform();
00238                         
00239                         FloatBuffer b=Buffers.matrixBuffer();
00240                         orientation.store(b); b.flip();
00241                         GL11.glMultMatrix(b);
00242                 }
00243                 
00247                 void retransform(){
00248                         GL11.glPopMatrix();
00249                         GL11.glPushMatrix();
00250                         transform();
00251                         GLUtil.getTransform(currentTransform);                  
00252                 }
00253                 
00255                 void spin(Port port){
00256                         Vector3f should=traverse(parent, port.center);                                  
00257                         orientation.rotate((float)Math.PI/2, port.normal);
00258                         retransform();                  
00259                         Vector3f is=traverse(parent, port.center);                                      
00260                         Vector3f.sub(position, is, position);
00261                         Vector3f.add(position, should, position);
00262                 }
00263         
00266                 void handleEvent(VisMouseEvent evt) {
00267                         super.handleEvent(evt);
00268                         if (evt.getID()==MouseEvent.MOUSE_CLICKED){
00269                                 Vector3f hit=evt.hit;
00270                                 
00271                                 //find nearest port to the 3d hit position
00272                                 Port nearest=null;
00273                                 float min=Float.MAX_VALUE;
00274                                 for (Port p: ports){
00275                                         float d=Vector3f.sub(hit, p.center, null).length();
00276                                         if (d<min){
00277                                                 min=d; 
00278                                                 nearest=p;
00279                                         }
00280                                 }
00281                                                                 
00282                                 //spin nearest.
00283                                 if (nearest!=null) 
00284                                         spin(nearest);
00285                         }
00286                 }
00287         } 
00288         
00289         
00292         void renderSelf() {
00293         
00294                 final float SNAP=20;
00295                 for (VisNode n1: children)
00296                         if (n1 instanceof VisDuct && ((VisDuct)n1).isDragged)
00297                                 for(VisNode n2: children)
00298                                         if (n2 instanceof VisDuct && n2!=n1){
00299                                                 VisDuct d1=(VisDuct)n1, d2=(VisDuct)n2;
00300                                                 for (Port p1: d1.ports)
00301                                                         for (Port p2:d2.ports)
00302                                                                 if (Vector3f.sub(d1.traverse(d2, p1.center),p2.center,null).length()<SNAP){
00303                                                                         d1.candidate=p2; d1.candidateOwn=p1;
00304                                                                         d2.candidate=p1; d2.candidateOwn=p2;
00305                                                                         return;
00306                                                                 }                                                                                                                                                                       
00307                                         }               
00308         }
00309 
00310 }

Generated on Tue Apr 7 17:57:21 2009 for visclient by  doxygen 1.5.1