2010-05-21 18 views
7

मैं मार्चिंग क्यूब्स के साथ isosurfaces, प्रस्तुत करना (या शायद अग्रसर वर्गों के रूप में इस 2 डी) है और मैं सेट अंतर, चौराहे और संघ की तरह सेट संचालन करना चाहते हैं। मुझे लगा कि यह लागू करने के लिए, बस दो अलग अलग अंतर्निहित सतहों से दो शीर्ष scalars के बीच चुनने के द्वारा आसान था, लेकिन यह नहीं है।CSG संचालन

मेरी प्रारंभिक परीक्षण के लिए, मैं सेट आपरेशन अंतर दो क्षेत्रों मंडलियों के साथ की कोशिश की, और। i.e ए - बी एक सर्कल चल रहा है और दूसरा स्थिर है। यहाँ दृष्टिकोण मैंने कोशिश की जब शिखर scalars उठा और जब अंदर या बाहर के रूप में कोने कोने में वर्गीकृत है। कोड सी ++ में लिखा गया है। ओपनजीएल का उपयोग प्रतिपादन के लिए किया जाता है, लेकिन यह महत्वपूर्ण नहीं है। किसी भी सीएसजी संचालन के बिना सामान्य प्रतिपादन अपेक्षित परिणाम देता है।



 void march(const vec2& cmin, //min x and y for the grid cell 
        const vec2& cmax, //max x and y for the grid cell 
        std::vector<vec2>& tri, 
        float iso, 
        float (*cmp1)(const vec2&), //distance from stationary circle 
        float (*cmp2)(const vec2&) //distance from moving circle 
) 
{ 
    unsigned int squareindex = 0; 
    float scalar[4]; 
    vec2 verts[8]; 
    /* initial setup of the grid cell */ 
    verts[0] = vec2(cmax.x, cmax.y); 
    verts[2] = vec2(cmin.x, cmax.y); 
    verts[4] = vec2(cmin.x, cmin.y); 
    verts[6] = vec2(cmax.x, cmin.y); 

    float s1,s2; 
    /********************************** 
    ********For-loop of interest****** 
    *******Set difference between **** 
    *******two implicit surfaces****** 
    **********************************/ 
    for(int i=0,j=0; i<4; ++i, j+=2){ 
    s1 = cmp1(verts[j]); 
    s2 = cmp2(verts[j]); 
    if((s1 < iso)){ //if inside circle1 
     if((s2 < iso)){ //if inside circle2 
     scalar[i] = s2; //then set the scalar to the moving circle 
     } else { 
     scalar[i] = s1; //only inside circle1 
     squareindex |= (1<<i); //mark as inside 
     } 
    } 
    else { 
     scalar[i] = s1; //inside neither circle 
    } 
    } 

    if(squareindex == 0) 
    return; 
    /* Usual interpolation between edge points to compute 
    the new intersection points */ 
    verts[1] = mix(iso, verts[0], verts[2], scalar[0], scalar[1]); 
    verts[3] = mix(iso, verts[2], verts[4], scalar[1], scalar[2]); 
    verts[5] = mix(iso, verts[4], verts[6], scalar[2], scalar[3]); 
    verts[7] = mix(iso, verts[6], verts[0], scalar[3], scalar[0]); 

    for(int i=0; i<10; ++i){ //10 = maxmimum 3 triangles, + one end token 
    int index = triTable[squareindex][i]; //look up our indices for triangulation 
    if(index == -1) 
     break; 
    tri.push_back(verts[index]); 
    } 
} 

यह मैं देता अजीब jaggies: here http://www.mechcore.net/images/gfx/csgbug2.png
यह CSG आपरेशन की तरह लग रहा प्रक्षेप बिना किया जाता है। यह सिर्फ पूरे त्रिकोण को "त्याग" करता है। मैं किसी अन्य तरीके से अंतर्वेशन, या शीर्ष अदिश मूल्यों गठबंधन करने के लिए की जरूरत है? मुझे इसके साथ कुछ मदद चाहिए। एक पूर्ण testcase डाउनलोड किया जा सकता HERE

संपादित करें: असल में, मार्चिंग वर्गों ठीक काम करता है की मेरी कार्यान्वयन। यह मेरी अदिश क्षेत्र जो टूट गया है है, और मुझे आश्चर्य है कि सही तरीका कैसे दिखाई देते हैं। अधिमानतः मैं तीन सेट के संचालन मैं ऊपर चर्चा की, हमेशा की तरह पुरातन (सर्कल, आयत/स्क्वायर, विमान)

संपादित 2 के लिए लागू करने के लिए एक सामान्य दृष्टिकोण के लिए देख रहा हूँ: यहाँ लागू करने के बाद कुछ नए चित्र हैं उत्तर देने के श्वेतपत्र:

1.Difference
2.Intersection
3.Union

संपादित करें 3: मैं भी 3 डी में इस लागू किया, उचित छायांकन/प्रकाश व्यवस्था के साथ:

1.Difference between a greater sphere and a smaller sphere
2.Difference between a greater sphere and a smaller sphere in the center, clipped by two planes on both sides, and then union with a sphere in the center.
3.Union between two cylinders.

उत्तर

3

इस तरह आप अदिश क्षेत्र मिश्रण नहीं है। आपके स्केलर एक बात कहते हैं, लेकिन आपके झंडे चाहे आप अंदर हैं या नहीं कहें। सबसे पहले खेतों विलय, तो प्रस्तुत करना के रूप में यदि आप एक ही परिसर वस्तु कर रहे थे:

for(int i=0,j=0; i<4; ++i, j+=2){ 
    s1 = cmp1(verts[j]); 
    s2 = cmp2(verts[j]); 
    s = max(s1, iso-s2); // This is the secret sauce 
    if(s < iso) { // inside circle1, but not inside circle2 
    squareindex |= (1<<i); 
    } 
    scalar[i] = s; 
} 

इस लेख उपयोगी हो सकता है: Combining CSG modeling with soft blending using Lipschitz-based implicit surfaces

+0

हम्म, अजीब। यह वास्तव में काम करता है, लेकिन किनारे अजीब तरह मिलता है। मैं जांच कर रहा हूं कि यह एक सटीक समस्या है या नहीं। हालांकि यह सामान्य सर्कल के लिए दिखाई नहीं देता है। यहां एक 100x100 ग्रिड का एक स्क्रीनशॉट है: http://www.mechcore.net/images/gfx/csgbug3.png –

+0

ठीक है, यह एक सटीक मुद्दा है। बड़ी सर्कल बहुत अच्छी काम करती है, लेकिन ग्रिड टेस्सेलेशन में वृद्धि नहीं होती है (मैं फ्लोट्स का उपयोग कर रहा हूं)। महान जवाब और महान पेपर। श्रीमान के लिए मेरा गहरा धन्यवाद –

+0

आपका स्वागत है! आपकी परियोजना के साथ शुभकामनाएं, अंतर्निहित सतह मजेदार हैं! –

संबंधित मुद्दे