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
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;}
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) {
00126 Vector3f.cross(normal, base, axis);
00127 axis.normalise();
00128 return 180;
00129 }else if(dot<-.9f){
00130 return 0;
00131 }else {
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) {
00144 return 0;
00145 }else {
00146 return -90;
00147 }
00148 }
00149
00150
00152 final float TOLERANCE=3;
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
00201 if (!isDragged && wasDragged && candidate!=null ){
00202
00203
00204
00205
00206 Vector3f otherOrigin=candidate.getOwner().traverse(this, new Vector3f());
00207
00208
00209 Vector3f otherNormal=candidate.getOwner().traverse(this, candidate.normal);
00210 Vector3f.sub(otherNormal, otherOrigin, otherNormal);
00211
00212
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
00219
00220 retransform();
00221
00222
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
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
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 }