00001 package org.hfbk.vis.visnode;
00002
00003 import java.io.BufferedReader;
00004 import java.io.IOException;
00005 import java.io.InputStreamReader;
00006 import java.net.URL;
00007 import java.util.ArrayList;
00008 import java.util.List;
00009
00010 import org.dronus.gl.Convexiser;
00011 import org.dronus.gl.GLFont;
00012 import org.dronus.gl.GLUtil;
00013 import org.dronus.graph.Node;
00014 import org.hfbk.vis.Prefs;
00015 import org.lwjgl.opengl.GL11;
00016 import org.lwjgl.util.vector.Vector3f;
00017
00031 public class VisObj extends VisNodeDraggable {
00032
00033 int dl;
00034
00035 Vector3f epicenter;
00036
00037 class Line extends ArrayList<Vector3f>{}
00038 class Face extends ArrayList<Vector3f>{}
00039 class Group {
00040 String name;
00041 List<Face> faces=new ArrayList<Face>();
00042 List<Line> lines=new ArrayList<Line>();
00043 }
00044
00045
00046 List<Vector3f> verticies=new ArrayList<Vector3f>();
00047 List<Group> groups=new ArrayList<Group>();
00048
00049 List<List<Vector3f>> triangles=new ArrayList<List<Vector3f>>();
00050
00051
00052 public VisObj(Node n, Vector3f position) {
00053 super(n, position);
00054
00055 try {
00056 load(new URL("file:"+n.text));
00057 } catch (IOException e) {
00058 e.printStackTrace();
00059 }
00060 }
00061
00062 public VisObj(String ressource, Vector3f pos){
00063 super(new Node(ressource), pos);
00064 try {
00065 URL r=ClassLoader.getSystemResource(ressource);
00066 load(r);
00067 } catch (IOException e) {
00068 e.printStackTrace();
00069 }
00070 }
00071
00087 void load(URL url) throws IOException{
00088 BufferedReader r=new BufferedReader(new InputStreamReader(url.openStream()));
00089
00090 Vector3f scale=new Vector3f(1,1,1);
00091
00092 Group currentGroup=new Group();
00093 currentGroup.name="default";
00094 groups.add(currentGroup);
00095
00096 String line;
00097 while ((line=r.readLine())!=null){
00098 String[] params=line.split(" +");
00099 if (params.length==0) continue;
00100
00101 String command=params[0];
00102
00103
00104 if (params[0].equals("v")){
00105 Vector3f vertex=new Vector3f(
00106 Float.parseFloat(params[1])*scale.x,
00107 Float.parseFloat(params[2])*scale.y,
00108 Float.parseFloat(params[3])*scale.z
00109 );
00110 verticies.add(vertex);
00111
00112 radius=Math.max(radius, vertex.length());
00113
00114 }
00115
00116 if (command.equals("center")){
00117 epicenter=new Vector3f(Float.parseFloat(params[1]),
00118 Float.parseFloat(params[2]),
00119 Float.parseFloat(params[3])
00120 );
00121
00122 }else if (command.equals("f")){
00123 Face f=new Face();
00124 for (int i=1; i<params.length; i++){
00125 String parts[]=params[i].split("/");
00126
00127
00128
00129 Vector3f v=verticies.get(Integer.parseInt(parts[0])-1);
00130 f.add(v);
00131 }
00132 currentGroup.faces.add(f);
00133 }else if (command.equals("l")){
00134 Line l=new Line();
00135 for (int i=1; i<params.length; i++){
00136 Vector3f v=verticies.get(Integer.parseInt(params[i])-1);
00137 l.add(v);
00138 }
00139 currentGroup.lines.add(l);
00140 }else if (command.equals("g") && params.length>1){
00141 currentGroup=new Group();
00142 currentGroup.name=params[1];
00143 groups.add(currentGroup);
00144 }else if (command.equals("scale")){
00145 scale=new Vector3f(Float.parseFloat(params[1]),
00146 Float.parseFloat(params[2]),
00147 Float.parseFloat(params[3])
00148 );
00149 }
00150 }
00151 r.close();
00152
00153 }
00154
00155 void drawNormals(){
00156 GL11.glLineWidth(2);
00157 for (Group g: groups)
00158 for (Face f: g.faces){
00159 if (f.size()<3) continue;
00160
00161 Vector3f normal=getNormal(f);
00162 normal.scale(10);
00163
00164 Vector3f mid=getCenter(f);
00165
00166 GL11.glBegin(GL11.GL_LINE_STRIP);
00167 GL11.glColor3f(0,0,1);
00168 GL11.glVertex3f(normal.x+mid.x, normal.y+mid.y,normal.z+mid.z);
00169 GL11.glColor3f(1,1,1);
00170 GL11.glVertex3f(mid.x,mid.y,mid.z);
00171 GL11.glColor3f(1,0,0);
00172 GL11.glVertex3f(-normal.x+mid.x, -normal.y+mid.y, -normal.z+mid.z);
00173 GL11.glEnd();
00174 }
00175
00176 GL11.glLineWidth(1);
00177 }
00178
00179 Vector3f getNormal(List<Vector3f> tri){
00180 Vector3f n0=tri.get(0), n1=tri.get(1), n2=tri.get(2);
00181 Vector3f d0=new Vector3f(), d2=new Vector3f();
00182 Vector3f.sub(n0,n1, d0);
00183 Vector3f.sub(n2,n1, d2);
00184 Vector3f normal=new Vector3f();
00185 Vector3f.cross(d0, d2, normal);
00186 normal.normalise();
00187 return normal;
00188 }
00189
00190 Vector3f getCenter(List<Vector3f> poly){
00191 Vector3f c=new Vector3f();
00192 for (Vector3f v: poly){
00193 Vector3f.add(c, v, c);
00194 }
00195 c.scale(1f/poly.size());
00196 return c;
00197 }
00198
00199 void drawFaces(){
00200
00201 for (Group g:groups){
00202 if (!g.name.equals("default")) groupColor(g.name.hashCode()&0xFF);
00203 for (Face f: g.faces){
00204
00205 List<List<Vector3f>> convexPolys;
00206 if (f.size()<4){
00207 convexPolys=new ArrayList<List<Vector3f>>();
00208 convexPolys.add(f);
00209 }else{
00210 Convexiser bfec=new Convexiser();
00211 convexPolys=bfec.convexise(f);
00212 }
00213
00214 for (List<Vector3f> t: convexPolys){
00215 GL11.glBegin(GL11.GL_POLYGON);
00216 for (Vector3f v: t)
00217 GL11.glVertex3f(v.x,v.y,v.z);
00218 GL11.glEnd();
00219
00220 triangles.add(t);
00221 }
00222 }
00223 }
00224 }
00225
00226 void groupColor(float g){
00227 if (g>0) {
00228 g=g*41;
00229 GL11.glColor3f((g/3)%1f, (g/5)%1f, (g/7)%1f);
00230 }
00231 }
00232
00233 void drawWireframe(){
00234 for (Group g: groups)
00235 for (Face f: g.faces){
00236 GL11.glBegin(GL11.GL_LINE_LOOP);
00237 for (Vector3f v: f)
00238 GL11.glVertex3f(v.x,v.y,v.z);
00239 GL11.glEnd();
00240 }
00241 }
00242
00243 void drawLines(){
00244 for (Group g: groups)
00245 for (Line l: g.lines){
00246 GL11.glBegin(GL11.GL_LINE_STRIP);
00247 for (Vector3f v: l)
00248 GL11.glVertex3f(v.x,v.y,v.z);
00249 GL11.glEnd();
00250 }
00251 }
00252
00256 void renderSelf() {
00257
00258
00259
00260 if (parent instanceof VisRoot){
00261 VisNode struct=parent.findNode(VisStructure.class);
00262 if (struct!=null){
00263 parent.remove(this);
00264 struct.add(this);
00265 }
00266 }
00267
00268 if (dl==0){
00269 dl=GL11.glGenLists(1);
00270 GL11.glNewList(dl, GL11.GL_COMPILE);
00271
00272 GL11.glDisable(GL11.GL_TEXTURE_2D);
00273
00274 GL11.glPolygonOffset(1,1);
00275 GL11.glColor4f(.5f,.5f,.5f,.3f);
00276 drawFaces();
00277 GL11.glPolygonOffset(0,0);
00278
00279 GL11.glColor3f(1,1,1);
00280 drawWireframe();
00281
00282 drawLines();
00283
00284 GL11.glEndList();
00285
00286 if (epicenter!=null)
00287 getRoot().epicenter=epicenter;
00288 }
00289
00290
00291 GL11.glCallList(dl);
00292
00293 if (isHoovered) {
00294 GL11.glColor3f(1,0,0);
00295 drawWireframe();
00296 }
00297
00298 if (Prefs.current.debug){
00299
00300 drawNormals();
00301 drawIndicies();
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 }
00312 }
00313
00314 void drawIndicies(){
00315 GLFont.getDefault().render();
00316 int index=0;
00317 for (Vector3f v: verticies){
00318 GL11.glPushMatrix();
00319 GL11.glTranslatef(v.x, v.y, v.z);
00320 GLUtil.billboardCylinder();
00321 GL11.glColor3f(1,1,1);
00322 GLFont.getDefault().print(""+index++);
00323 GL11.glPopMatrix();
00324 }
00325
00326 GL11.glDisable(GL11.GL_TEXTURE_2D);
00327 }
00328
00329
00333 boolean hitTriangle(Ray ray, List<Vector3f> polygon) {
00334
00335 final double EPSILON=0.000001;
00336
00337 Vector3f vert0=polygon.get(0);
00338 Vector3f vert1=polygon.get(1);
00339 Vector3f vert2=polygon.get(2);
00340
00341 Vector3f edge1=new Vector3f(), edge2=new Vector3f(), tvec=new Vector3f(), pvec=new Vector3f(), qvec=new Vector3f();
00342
00343 Vector3f.sub(vert1, vert0, edge1);
00344 Vector3f.sub(vert2, vert0, edge2);
00345
00346 Vector3f.cross(ray.dir, edge2, pvec);
00347
00348
00349 double det =Vector3f.dot(edge1,pvec);
00350
00351 if (det > -EPSILON && det < EPSILON)
00352 return false;
00353
00354 double inv_det = 1.0 / det;
00355
00356
00357 Vector3f.sub(ray.start, vert0, tvec);
00358
00359
00360 double u = Vector3f.dot(tvec, pvec) * inv_det;
00361 if (u < 0.0 || u > 1.0)
00362 return false;
00363
00364
00365
00366 Vector3f.cross(tvec,edge1,qvec);
00367 double v = Vector3f.dot(ray.dir, qvec) * inv_det;
00368 if (v < 0.0 || u + v > 1.0)
00369 return false;
00370
00371
00372
00373
00374 return true;
00375 }
00376
00383 boolean hit(Ray mouseray, Vector3f hit) {
00384 float distance;
00385
00386 if(handle==null) distance=GLUtil.getPosition().length();
00387 else distance=hitDepth;
00388 Vector3f projector=(Vector3f)new Vector3f(mouseray.dir).scale(distance);
00389 Vector3f.add(mouseray.start, projector, hit);
00390
00391
00392
00393 for (List<Vector3f> t:triangles)
00394 if (hitTriangle(mouseray, t))
00395 return true;
00396
00397 return false;
00398 }
00399 }