2016-04-17 5 views
7

मैं एंड्रॉइड के Canvas के साथ कुछ काम कर रहा हूं, विशेष रूप से यह निर्धारित करने की कोशिश कर रहा हूं कि इसके getClipBounds परिणाम निर्धारित किए गए हैं। मैं समझता हूं कि Canvas आंतरिक रूप से एक ट्रांसफॉर्म Matrix रखता है जिसे अपडेट किया गया है क्योंकि मैं translate, scale आदि पर कॉल करता हूं लेकिन Matrix के परिणामों को दोहराने की कोशिश कर रहा हूं।कैनवास कैसे इसकी क्लिप सीमा निर्धारित करता है?

@Override 
public void onDraw(Canvas canvas) { 
    Rect clipBounds; 
    RectF viewport; 

    canvas.save(); 
    canvas.concat(translationMatrix); 
    //viewportMatrix.preConcat(canvas.getMatrix()); 
    viewportMatrix.set(canvas.getMatrix()); 

    clipBounds = canvas.getClipBounds(); 
    viewport = GetViewport(); 

    Log.d("clipBounds", clipBounds.toString() + " (" + clipBounds.width() + ", " + clipBounds.height() + ")"); 
    Log.d("viewport", viewport.toString() + " (" + viewport.width() + ", " + viewport.height() + ")"); 

    //drawing is done here 

    canvas.restore(); 
} 

//viewport code modeled after http://stackoverflow.com/a/17142856/2245528 
private RectF GetViewport() { 
    RectF viewport = new RectF(); 

    viewportMatrix.mapRect(viewport, originalViewport); 

    return viewport; 
} 

private void Translate(float x, float y) { 
    translationMatrix.postTranslate(x, y); 

    invalidate(); 
} 

private void Scale(float scaleFactor, PointF focusPoint) { 
    if (focusPoint == null) { 
     translationMatrix.postScale(scaleFactor, scaleFactor); 
    } 
    //keep the focus point in focus if possible 
    else { 
     translationMatrix.postScale(scaleFactor, scaleFactor, focusPoint.x, focusPoint.y); 
    } 

    invalidate(); 
} 

private final Matrix translationMatrix = new Matrix(); 
private final RectF originalViewport = new RectF(); 
private final Matrix viewportMatrix = new Matrix(); 

originalViewport0, 0, canvas.getWidth(), canvas.getHeight() को तैयार है। Translate और Scale इशारा ईवेंट हैंडलर से बुलाए जाते हैं, जो सही तरीके से काम कर रहे हैं।

जो भाग मुझे भ्रमित करता है वह viewportMatrix है। इससे कोई फर्क करने के लिए मुझे क्या करना है कि क्या नहीं लगता है

viewportMatrix.set(canvas.getMatrix()); 

या

viewportMatrix.preConcat(canvas.getMatrix()); 

या शुरुआत साथ-पक्ष द्वारा पीछा किया पर

viewportMatrix.set(canvas.getMatrix()); 

को भी एक बार की कॉल Translate/Scale दो मैट्रिक्स को कॉल करता है। मैं भी पूरी तरह से Matrix में निर्मित Canvas की अनदेखी की है की कोशिश की और फिर से लिखने GetViewport रूप

//viewport code modeled after http://stackoverflow.com/a/17142856/2245528 
private RectF GetViewport() { 
    RectF viewport = new RectF(); 

    translationMatrix.mapRect(viewport, originalViewport); 

    return viewport; 
} 

मैं getClipBounds() मिलते हुए लगते हैं कभी नहीं कर सकते हैं और विसंगतियों काफी गंभीर हैं:

viewportMatrix.set(canvas.getMatrix) साथ:

clipBounds: रेक्ट (-97, -97 - 602, 452) (699, 549)
व्यूपोर्ट: RectF (९७.०४,१७८, ९७.०६,०३६, ७९७.०४,१७५, 647। 06,036) (700.0, 550,0)

साथ

:

clipBounds: रेक्ट (-97, -96 - 602, 453) (699, 549)
व्यूपोर्ट: RectF (2708.9663, 2722.2754, 3408.9663, 3272.2754) (700.0, 550,0)

translationMatrix.mapRect साथ:

clipBounds: रेक्ट (-96, -96 - 603, 453) (699, 549)
व्यूपोर्ट: RectF (९६.७३,२१३, ९६.८५,७९४, 796.7321, 646.8579) (700.0, 550,0)

एक एक के साथ

viewportMatrix.preConcat(canvas.getMatrix()) को -shot कॉल साइड-बाई-साइड Translate/Scale कॉल के बाद:

clipBounds: रेक्ट (-96, -97 - 603, 452) (699, 549)
व्यूपोर्ट: RectF (९६.५७,७३८, 97.78168, 796.5774, 647.7817) (700.0, 550।0)

viewportMatrix.set(canvas.getMatrix()) करने के लिए एक एक शॉट कॉल साइड-बाई-साइड Translate/ Scale कॉल के बाद साथ

:

clipBounds: रेक्ट (-96, -96 - 603, 453) (699 , 549)
व्यूपोर्ट: RectF (९६.४०,०५१, ९६.८८,१५३, 796.4005, ६४६.८८,१५३) (700.0, 550,0)

मैं भी the Canvas source जांच नहीं कर सकता, सभी Matrix कोड के रूप में निजी नेट में गायब हो जाती है ive कॉल जिसका कोड नहीं दिखाया गया है।

मेरे GetViewport इतने बड़े पैमाने पर क्यों कॉल कर रहे हैं, और getClipBounds के साथ दृश्यों के पीछे क्या चल रहा है?

उत्तर

1

मैं this answer on GameDev SE के माध्यम से पढ़ते हैं, जो स्क्रीन और दुनिया के बीच स्वैप करने के लिए सिस्टम समन्वय मैट्रिक्स उलट उपयोग करता है:

स्क्रीन से दुनिया अंतरिक्ष में जाने के लिए बस Vector2.Transform का उपयोग करें। ऑब्जेक्ट पिकिंग के लिए दुनिया में माउस का स्थान प्राप्त करने के लिए इसका उपयोग आमतौर पर किया जाता है।

Vector2.Transform(mouseLocation, Matrix.Invert(Camera.TransformMatrix)); 

दुनिया से स्क्रीन स्पेस जाने के लिए बस विपरीत करें।

private RectF GetViewport() { 
    RectF viewport = new RectF(); 
    Matrix viewportMatrix = new Matrix(); 

    translationMatrix.invert(viewportMatrix); 

    viewportMatrix.mapRect(viewport, originalViewport); 

    return viewport; 
} 

यह व्यूपोर्ट सही ढंग से getClipBounds द्वारा लौटाए गए परिणामों से मेल खाता है:

Vector2.Transform(mouseLocation, Camera.TransformMatrix); 

इस दृष्टिकोण से प्रेरित होकर, मैं इस तरह परिवर्तन मैट्रिक्स inverting की कोशिश की।

This matrix tutorial बताते हैं कि मैं क्या transform कॉल के परिणामों से देखा था, लेकिन मेरे मैट्रिक्स के लिए लागू नहीं किया था:

एक कंप्यूटर प्रोग्राम में कैमरा सब पर और वास्तविकता में स्थानांतरित नहीं होता है, दुनिया सिर्फ दिशा और अभिविन्यास में चल रही है कि आप कैमरे को वास्तविकता में कैसे ले जाना चाहते हैं।

आदेश में यह सही ढंग से समझने के लिए, हम दो अलग बातें करने के मामले में सोचना चाहिए:

  1. कैमरा परिवर्तन मैट्रिक्स: परिवर्तन है कि दुनिया अंतरिक्ष में सही स्थिति और अभिविन्यास में कैमरा स्थानों (यह वह परिवर्तन है जिसे आप कैमरे के 3 डी मॉडल पर लागू करेंगे यदि आप दृश्य में इसका प्रतिनिधित्व करना चाहते हैं)।
  2. व्यू मैट्रिक्स: यह मैट्रिक्स विश्व-स्थान से देखने-स्थान पर शिखर को बदल देगा। यह मैट्रिक्स ऊपर वर्णित कैमरे के रूपांतरण मैट्रिक्स के विपरीत है।
संबंधित मुद्दे