2009-11-30 12 views
12

मैं 3 डी में पथ निकालने की कोशिश कर रहा हूं। अभी तक कुछ भी फैंसी नहीं है, बस कुछ बिंदुओं का पालन करें और 'टयूबिंग' के लिए नियमित बहुभुज का उपयोग करें। मैं अब प्रोटोटाइप के लिए प्रोसेसिंग का उपयोग कर रहा हूं, लेकिन बाद में कोड को ओपनजीएल में बदल दूंगा।3 डी में पथ कैसे निकालना है?

मेरी समस्या दाएं कोणों पर 'जोड़ों' को घुमा रही है। मुझे लगता है कि मुझे कोई अजीब विचार है कि कोण कैसे प्राप्त करें, सुनिश्चित नहीं है।

मैं साइमन Greenwold (प्रसंस्करण> फ़ाइल> उदाहरण> 3 डी> फ़ॉर्म> कोने) .Here मेरा प्रयास अब तक से एक नमूना से शुरू कर दिया है:

अद्यतन> रिफैक्टर्ड/सरलीकृत कोड

Here is the main sketch code: 
int pointsNum = 10; 
Extrusion star; 

int zoom = 0; 

void setup() { 
    size(500, 500, P3D); 

    PVector[] points = new PVector[pointsNum+1]; 
    for(int i = 0 ; i <= pointsNum ; i++){ 
    float angle = TWO_PI/pointsNum * i; 
    if(i % 2 == 0) 
     points[i] = new PVector(cos(angle) * 100,sin(angle) * 100,0); 
    else 
     points[i] = new PVector(cos(angle) * 50,sin(angle) * 50,0); 
    } 

    star = new Extrusion(10,10,points,3); 
} 

void draw() { 
    background(0); 
    lights(); 
    translate(width/2, height/2,zoom); 
    rotateY(map(mouseX, 0, width, 0, PI)); 
    rotateX(map(mouseY, 0, height, 0, PI)); 
    rotateZ(-HALF_PI); 
    noStroke(); 
    fill(255, 255, 255); 
    translate(0, -40, 0); 
    star.draw(); 
} 

void keyPressed(){ 
    if(key == 'a') zoom += 5; 
    if(key == 's') zoom -= 5; 
} 

और यहां एक्सट्रूज़न क्लास है:

आयात प्रसंस्करण.कोर.पीमैट्रिक्स 3 डी;

class Extrusion{ 

    float topRadius,bottomRadius,tall,sides; 
    int pointsNum; 
    PVector[] points; 

    Extrusion(){} 

    Extrusion(float topRadius, float bottomRadius, PVector[] points, int sides) { 
    this.topRadius = topRadius; 
    this.bottomRadius = bottomRadius; 
    this.points = points; 
    this.pointsNum = points.length; 
    this.sides = sides; 
    } 

    void draw() { 
    if(pointsNum >= 2){ 
     float angle = 0; 
     float angleIncrement = TWO_PI/sides; 

     //begin draw segments between caps 
     angle = 0; 
     for(int i = 1; i < pointsNum ; ++i){ 
     beginShape(QUAD_STRIP); 
     for(int j = 0; j < sides + 1; j++){ 
      vertex(points[i-1].x + cos(angle) * topRadius, points[i-1].y, points[i-1].z + sin(angle) * topRadius); 
      vertex(points[i].x + cos(angle) * bottomRadius, points[i].y, points[i].z + sin(angle) * bottomRadius); 

      angle += angleIncrement; 
      } 
     endShape(); 
     } 
     //begin draw segments between caps 
    }else println("Not enough points: " + pointsNum); 
    } 
} 

अद्यतन

यहाँ कैसे मेरी स्केच लग रहा है की तरह है:

processing extrude http://doc.gold.ac.uk/~ma802gp/extrude.gif

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

यहाँ कुछ नमूने हैं:

star painting http://doc.gold.ac.uk/~ma802gp/star_painting.jpg

star paper sculpture http://doc.gold.ac.uk/~ma802gp/star_paper_sculpture.jpg

triangles http://doc.gold.ac.uk/~ma802gp/triangles_pencil.jpg

खराब गुणवत्ता के बारे में खेद है।

जैसा कि आप त्रिकोण छवि में देख सकते हैं, जो extrusions के साथ हासिल किया जाएगा।

अद्यतन

यहाँ ड्रॉ विधि में drhirsch की मदद का उपयोग करने के लिए अपने प्रयास है:

void draw() { 
    if(pointsNum >= 2){ 
     float angle = 0; 
     float angleIncrement = TWO_PI/sides; 

     //begin draw segments between caps 
     angle = 0; 
     for(int i = 1; i < pointsNum ; ++i){ 
     beginShape(QUAD_STRIP); 
     for(int j = 0; j < sides + 1; j++){ 

      PVector s = new PVector(0,0,1); 
      PVector cn = new PVector(); 
      points[i].normalize(cn); 
      PVector r = s.cross(cn); 
      float a = acos(s.dot(cn)); 
      PMatrix3D rot = new PMatrix3D(1,0,0,0, 
             0,1,0,0, 
             0,0,1,0, 
             0,0,0,1); 
      rot.rotate(a,r.x,r.y,r.z); 
      PVector rotVec = new PVector(); 
      rot.mult(points[i],rotVec); 
      rotVec.add(new PVector(cos(angle) * topRadius,0,sin(angle) * topRadius)); 

      vertex(points[i-1].x + cos(angle) * topRadius, points[i-1].y, points[i-1].z + sin(angle) * topRadius); 
      vertex(rotVec.x,rotVec.y,rotVec.y); 

      //vertex(points[i-1].x + cos(angle) * topRadius, points[i-1].y, points[i-1].z + sin(angle) * topRadius); 
      //vertex(points[i].x + cos(angle) * bottomRadius, points[i].y, points[i].z + sin(angle) * bottomRadius); 

      angle += angleIncrement; 
      } 
     endShape(); 
     } 
     //begin draw segments between caps 
    }else println("Not enough points: " + pointsNum); 
    } 

मैं तो अब वर्ग कि CShape के नाम से जाना बाहर निकालना कहा जाता है के लिए इस्तेमाल किया कोड पुनर्संशोधित गया है, कोड कम है और उम्मीद है कि, और मैं PVector ऑब्जेक्ट्स के वेक्टर के बजाय PVector ऑब्जेक्ट्स की एक सरणी का उपयोग करता हूं जो भ्रमित हो सकता है।

void draw() { 
    if(pointsNum >= 2){ 
     float angle = 0; 
     float angleIncrement = TWO_PI/sides; 

     //begin draw segments between caps 
     angle = 0; 
     for(int i = 1; i < pointsNum ; ++i){ 
     beginShape(QUAD_STRIP); 
     float angleBetweenNextAndPrevious = 0.0; 
     if(i < pointsNum - 1) angleBetweenNextAndPrevious = PVector.angleBetween(points[i],points[i+1]); 
     PVector s = new PVector(0,0,1); 
     PVector s2 = new PVector(0,0,1); 
     PVector cn = new PVector(); 
     PVector cn2 = new PVector(); 
     points[i-1].normalize(cn); 
     points[i].normalize(cn2); 
     PVector r = s.cross(cn); 
     PVector r2 = s.cross(cn2); 
     PMatrix3D rot = new PMatrix3D(1,0,0,0, 
             0,1,0,0, 
             0,0,1,0, 
             0,0,0,1); 
     PMatrix3D rot2 = new PMatrix3D(1,0,0,0, 
             0,1,0,0, 
             0,0,1,0, 
             0,0,0,1); 

     rot.rotate(angleBetweenNextAndPrevious,r.x,r.y,r.z); 
     rot2.rotate(angleBetweenNextAndPrevious,r2.x,r2.y,r2.z); 
     PVector rotVec = new PVector(); 
     PVector rotVec2 = new PVector(); 

     for(int j = 0; j < sides + 1; j++){ 
      // I am still not sure about this. Should the shape be in the xy plane 
      // if the extrusion is mainly along the z axis? If the shape is now in 
      // the xz plane, you need to use (0,1,0) as normal vector of the shape 
      // (this would be s and s2 above, don't use the short names I have 
      // used, sorry) 
      PVector shape = new PVector(cos(angle) * topRadius,0,sin(angle) * topRadius); 

      rot.mult(shape, rotVec); 
      rot2.mult(shape,rotVec2); 

      rotVec.add(points[i-1]); 
      rotVec2.add(points[i]); 

      vertex(rotVec.x,rotVec.y,rotVec.z); 
      vertex(rotVec2.x,rotVec2.y,rotVec2.z); 
      //vertex(points[i-1].x + cos(angle) * topRadius, points[i-1].y, points[i-1].z + sin(angle) * topRadius); 
      //vertex(points[i].x + cos(angle) * bottomRadius, points[i].y, points[i].z + sin(angle) * bottomRadius); 

      angle += angleIncrement; 
      } 
     endShape(); 
     } 
     //begin draw segments between caps 
    }else println("Not enough points: " + pointsNum); 
    } 
} 
:

upated drhirsch द्वारा आकर्षित

void draw() { 
    if(pointsNum >= 2){ 
     float angle = 0; 
     float angleIncrement = TWO_PI/sides; 

     //begin draw segments between caps 
     angle = 0; 
     for(int i = 1; i < pointsNum ; ++i){ 
     beginShape(QUAD_STRIP); 
     float angleBetweenNextAndPrevious = 0.0; 
     if(i < pointsNum - 1) angleBetweenNextAndPrevious = PVector.angleBetween(points[i],points[i+1]); 

     for(int j = 0; j < sides + 1; j++){ 

      PVector s = new PVector(0,0,1); 
      PVector s2 = new PVector(0,0,1); 
      PVector cn = new PVector(); 
      PVector cn2 = new PVector(); 
      points[i-1].normalize(cn); 
      points[i].normalize(cn); 
      PVector r = s.cross(cn); 
      PVector r2 = s.cross(cn2); 
      PMatrix3D rot = new PMatrix3D(1,0,0,0, 
             0,1,0,0, 
             0,0,1,0, 
             0,0,0,1); 
      PMatrix3D rot2 = new PMatrix3D(1,0,0,0, 
             0,1,0,0, 
             0,0,1,0, 
             0,0,0,1); 

      rot.rotate(angleBetweenNextAndPrevious,r.x,r.y,r.z); 
      rot2.rotate(angleBetweenNextAndPrevious,r2.x,r2.y,r2.z); 

      PVector rotVec = new PVector(); 
      rot.mult(points[i-1],rotVec); 
      rotVec.add(new PVector(cos(angle) * topRadius,0,sin(angle) * topRadius)); 
      PVector rotVec2 = new PVector(); 
      rot2.mult(points[i],rotVec2); 
      rotVec2.add(new PVector(cos(angle) * topRadius,0,sin(angle) * topRadius)); 

      vertex(rotVec.x,rotVec.y,rotVec.z); 
      vertex(rotVec2.x,rotVec2.y,rotVec2.z); 
      //vertex(points[i-1].x + cos(angle) * topRadius, points[i-1].y, points[i-1].z + sin(angle) * topRadius); 
      //vertex(points[i].x + cos(angle) * bottomRadius, points[i].y, points[i].z + sin(angle) * bottomRadius); 

      angle += angleIncrement; 
      } 
     endShape(); 
     } 
     //begin draw segments between caps 
    }else println("Not enough points: " + pointsNum); 
    } 
} 

fix_test http://doc.gold.ac.uk/~ma802gp/extrude2.gif

संपादित यह काम करना चाहिए:

यहाँ कुछ Escher-esque परिणामों के साथ मेरी अभी तक एक और प्रयास है

description http://doc.gold.ac.uk/~ma802gp/description.gif

नीले पथ, मेरे कोड में अंक [] PVector सरणी के बराबर है अगर pointsNum = 6. लाल मार्ग है:

अद्यतन

यहाँ मेरी समस्या का एक सरल उदाहरण है जो मैं हल करने के लिए संघर्ष कर रहा हूं, हरा पथ वह है जो मैं प्राप्त करना चाहता हूं।

अद्यतन

कुछ मामूली कोने मुझे लगता है कि के आदेश में समस्याओं का। यहां 6 अंक और नहीं (अगर/अन्य% 2) स्टार स्थिति का उपयोग करके कुछ प्रिंट स्क्रीन हैं। क्योंकि अपने आकार xy में फ्लैट है

points1 http://doc.gold.ac.uk/~ma802gp/points1.gif

alt text http://doc.gold.ac.uk/~ma802gp/points2.gif

+0

कोणों की गणना करने का एकमात्र कारण मानक उत्पन्न करेगा। ज़ेड-अक्ष के साथ अनुवाद द्वारा एक्सट्रूज़न क्यों नहीं करते? और आप पक्षों पर एक QUAD_STRIP का उपयोग कर सकते हैं। – hirschhornsalz

+0

या क्या आप इस पथ के स्पर्शरेखा पर झुकाव से मेल खाने के लिए स्वत: घूर्णन वाले पथ के साथ एक एक्सट्रूज़न करना चाहते हैं? – hirschhornsalz

+0

@drhirsch QUAD_STRIP पर टिप के लिए धन्यवाद, मैं इसका उपयोग करूंगा। मैं पथ के स्पर्शरेखा पर झुकाव से मेल खाने के लिए स्वचालित रोटेशन वाले पथ के साथ एक एक्सट्रूज़न चाहता हूं। मुझे लगता है कि मैंने 2 डी में काम किया, 3 डी पर जाने पर समस्याएं थीं।दूसरे बिंदु के लिए झुकाव प्राप्त करने के लिए मैं तीसरे बिंदु और 1 बिंदु के बीच अंतर के एटान 2 का उपयोग करता हूं और 90 डिग्री (लंबवत) जोड़ता हूं। सुनिश्चित नहीं है कि इसे 3 डी में कैसे लागू करें। –

उत्तर

3

अपने आकार मानते हुए, अपने उदाहरण एस में एक सामान्य वेक्टर एस होगा (0,0,1) है। आप रोटेशन अक्ष वेक्टर आर प्राप्त करने के लिए वर्तमान पथ वेक्टर वी (सामान्यीकृत) और एस के बीच क्रॉस उत्पाद का उपयोग कर सकते हैं। आपको आर के आसपास अपना आकार घुमाए जाने की आवश्यकता है। घूर्णन के कोण को एस और वी के बीच डॉट उत्पाद से प्राप्त किया जा सकता है। तो:

R = S x V 
a = arc cos(S . V) 

अब आप सेटअप आर और एक के साथ एक rotation matrix और आकार यह द्वारा घुमा सकते हैं।

आप ग्लैरोटेट (...) का उपयोग स्टैक पर वर्तमान मैट्रिक्स को घुमाने के लिए कर सकते हैं, लेकिन यह glBegin() और glEnd() के बीच नहीं किया जा सकता है। तो आपको अपने आप या पुस्तकालय के साथ मैट्रिक्स गुणा करना है।

संपादित करें: पुस्तकालय आप उपयोग कर रहे पर एक छोटी नज़र के बाद, आप सेटअप रोटेशन मैट्रिक्स करने में सक्षम

PVector s = new PVector(0,0,1); // is already normalized (meaning is has length 1) 
PVector cn; 
current.normalize(cn); 
PVector r = s.cross(cn); 
float a = acos(s.dot(cn)); 
PMatrix rot = new PMatrix(1, 0, 0, 0, 
          0, 1, 0, 0, 
          0, 0, 1, 0, 
          0, 0, 0, 1); 
rot.rotate(a, r.x, r.y, r.z); 

साथ होना चाहिए और अब सड़ांध के साथ अपने आकार के प्रत्येक तत्व गुणा और अपने वर्तमान करके इसे अनुवाद पथ वेक्टर:

PVector rotVec; 
rot.mult((PVector)shape[i], rotVec); 
rotVec.add(current); 
+0

का उपयोग करता है मैं आपकी मदद का उपयोग करने की कोशिश कर रहा हूं, और अब तक मैंने यह कोशिश की है: PVector s = new PVector (0,0,1); s.normalize(); // आकार सामान्य वेक्टर PVector r = s .cross (वर्तमान); फ्लोट ए = एकोस (एस डॉट (वर्तमान)); क्या मुझे अधिकार मिला? एस और वी के बीच डॉट उत्पाद के आर्क कोसाइन के बराबर है? –

+0

हां, आपको यह बिल्कुल सही मिला। क्रॉस उत्पाद हमेशा दोनों वैक्टरों के लिए लंबवत होता है। एक विशेष मामला है यदि दोनों वैक्टरों की एक ही दिशा है (संभवतः आपके पथ की शुरुआत में), लेकिन इसे संभालना आसान है। – hirschhornsalz

+0

मैंने आपके स्पष्टीकरण का उपयोग करने के अपने प्रयास के साथ कोड जोड़ा है। अभी भी कुछ चीजें जिनके साथ मैं खो गया हूं। मैं समझने की कोशिश कर रहा हूं कि 'अपने आकार के प्रत्येक तत्व को सड़ांध से गुणा करें'। प्रत्येक सेलेमेंट, प्रत्येक वेक्टर, या प्रत्येक वेक्टर के प्रत्येक घटक का मतलब है? घूर्णन को जोड़ना यह आखिरी बिट है जो मुझे सिरदर्द देता है। अनुवाद केवल घुमावदार शिखर प्राप्त करना चाहिए और उसमें एक अनुवाद वेक्टर जोड़ना चाहिए। सभी धैर्य drhirsch के लिए धन्यवाद! –