View Full Version : Mask acting very weird, works if drawn in one direciton, but not the other.
lordofduct
06-19-2008, 06:16 AM
First, please try running this code:
var spr1:Sprite = new Sprite();
var gr:Graphics = spr1.graphics;
gr.beginFill(0x000000);
gr.drawRect(0,0, 300,300);
gr.moveTo(300,100);
gr.lineTo(100,300);
gr.lineTo(300,300);
gr.lineTo(300,100);
gr.endFill();
/* gr.drawRect(0,0, 300,300);
gr.moveTo(0,100);
gr.lineTo(100,300);
gr.lineTo(0,300);
gr.lineTo(0,100);
gr.endFill(); */
var spr2:Sprite = new Sprite();
gr = spr2.graphics;
gr.beginFill(0xFF0000);
gr.drawRect(0,0,300,300);
gr.endFill();
addChild(spr2);
addChild(spr1);
spr2.mask = spr1;
if you run it as is, you should get a red square with a sliver chopped off on the right. But if you comment the first draw, and uncomment the second draw it doesn't work although the resulting mask still would have a sliver cut off.
here are the two masks, left is the first one, right is the second:
http://img.photobucket.com/albums/v333/lordofduct/maskBug.jpg
Now of course I could just draw the mask with out drawing the rect first and splicing and instead just do lineTo for the whole thing, and it works fine. BUT the situation I need to use this for doesn't know the cross points. I'm basically drawing a rect and then splicing off some of the square to fit properly (to avoid a lot of math that is costly).
Does anyone know what is going on?
lordofduct
06-19-2008, 06:31 AM
For a basic explanation of why I'm doing it this way...
http://img.photobucket.com/albums/v333/lordofduct/weirdRect.jpg
For some rect marked by the black box, I take some positiong marked by the red X. From there depending the conditions I solve a vector to one of the four corners, then I rotate that vector 90 degrees to find an adjacent line who's angle is at which the rect is cut.
Then I cut the first vector in half, and add it to the initial point (the red x) to find a point on the rect through which the previous vector passes.
Then I draw 3 masks, one which is the entire rect on the right side of the line, another which is on the left hand side, and a 3rd which is the smaller of those two mirrored over the line.
If anyone knows an easy way to do this... please, tell me!
pj-co
06-19-2008, 06:41 AM
im not totally following what you are trying to accomplish, i tried your code and it seems to me to work nicely withouth drawRect() in the masks.
Can you explain more what your expected and actual results look like? especially expected
lordofduct
06-19-2008, 09:48 AM
That's the thing, I need drawRect in there... note, if you run that code with out setting the masks or adding spr2 you'll get those two black shapes. THOSE should be your masks.
by performing drawRect first, and then the following lines with a fill, the triangle basically clips the rect leaving a rect with a chunk taken out. If I do this with the sliver on the right side, the mask functions properly, but if I draw this with the chunk on the left, the mask acts like a full rectangle.
basically... this code produces what is in the left of the lower image (black is mask shape, red is the result):
var spr1:Sprite = new Sprite();
var gr:Graphics = spr1.graphics;
gr.beginFill(0x000000);
gr.drawRect(0,0, 300,300);
gr.moveTo(300,100);
gr.lineTo(100,300);
gr.lineTo(300,300);
gr.lineTo(300,100);
gr.endFill();
var spr2:Sprite = new Sprite();
gr = spr2.graphics;
gr.beginFill(0xFF0000);
gr.drawRect(0,0,300,300);
gr.endFill();
addChild(spr2);
addChild(spr1);
spr2.mask = spr1;
but this creates what is on the right (black is the mask shape created, red is the result):
var spr1:Sprite = new Sprite();
var gr:Graphics = spr1.graphics;
gr.beginFill(0x000000);
gr.drawRect(0,0, 300,300);
gr.moveTo(0,100);
gr.lineTo(100,300);
gr.lineTo(0,300);
gr.lineTo(0,100);
gr.endFill();
var spr2:Sprite = new Sprite();
gr = spr2.graphics;
gr.beginFill(0xFF0000);
gr.drawRect(0,0,300,300);
gr.endFill();
addChild(spr2);
addChild(spr1);
spr2.mask = spr1;
image:
http://img.photobucket.com/albums/v333/lordofduct/MessBoard/rectSideBySide.jpg
Mazoonist
06-19-2008, 01:53 PM
I believe at the end of the code you just need to reverse the masking:
spr1.mask = spr2;
Edit: Sorry, I didn't really have time to really study it much... so it that's not the solution I apologize
lordofduct
06-19-2008, 02:04 PM
No that's not the solution.
I should tell you all, the code I supplied is just a demo of the much larger project this is getting implimented in.
I'm just wondering why... my problem is I have to find out "where" on this rectangle the line is crossing, and then see which corners are exposed, and which order to draw those points in. Not very easy, but if this isn't gonna work I guess I'll have to do it that way. Just is a lot more math then I want my program to have to do.
as you can see though, there is already a lot going on:
internal function solve( rect:Rectangle, p:Vector2, cx:String, cy:String ):void
{
v1.i = rect[cx] - p.i;
v1.j = rect[cy] - p.j;
v1.multiply(0.5);
//v2
v2 = Vector2.normal(v1);
if (!v2.i) return;
var arr:Array = lineIntersectsRect( rect, Vector2.add(p, v1), v2 );
if ( cy == "top" && arr[0].j > arr[1].j)
{
var tmpT:Vector2 = arr[1];
arr[1] = arr[0];
arr[0] = tmpT;
} else if ( cy == "bottom" && arr[0].j < arr[1].j )
{
var tmpB:Vector2 = arr[1];
arr[1] = arr[0];
arr[0] = tmpB;
}
var a:Number = Math.atan2(arr[0].j - p.j, arr[0].i - p.i );
a *= 180 / Math.PI;
_pageFlip.page.rotation = ( cx == "left" ) ? a - 180 : a;
var bool:Boolean = ( ( cx == "right" && arr[0].i < rect.right && arr[1].i < rect.right ) || ( cx == "left" && arr[0].i > rect.left && arr[1].i > rect.left ) );
if ( bool )
{
v4.setValues(rect[cx], 0);
v4.j = (cy == "top") ? rect.bottom : rect.top;
v4.subtract(p);
v4.subtract(v1);
v4.reflect( v2 );
v4.negate();
v4.add(p);
v4.add(v1);
arr.push(v4);
}
arr.push(p);
var gr:Graphics = _pageFlip.pageMask.graphics;
gr.clear();
gr.lineStyle(0);
gr.beginFill(0x000000);
gr.moveTo(p.i, p.j);
for (var j:int = 0; j < arr.length; j++)
{
gr.lineTo(arr[j].i, arr[j].j);
}
gr.endFill();
gr = _pageFlip.underMask.graphics;
gr.clear();
gr.beginFill(0x00FF00);
gr.drawRect(rect.x, rect.y, rect.width, rect.height);
var tx:Number = (cy == "top") ? rect.bottom : rect.top;
gr.moveTo(arr[0].i, arr[0].j);
gr.lineTo(rect[cx], rect[cy]);
gr.lineTo(rect[cx], tx);
gr.lineTo(arr[1].i, arr[1].j);
gr.lineTo(arr[0].i, arr[0].j);
gr.endFill();
a = v1.angle() * 180 / Math.PI;
_pageFlip.glare.rotation = ( ( cx == "left" && cy == "bottom" ) || ( cx == "right" && cy == "top" ) ) ? a - 180 : a;
_pageFlip.glare.x = arr[0].i;
_pageFlip.glare.y = arr[0].j;
var alph:Number = v1.length / _pageFlip.pageWidth;
alph -= 1;
alph = Math.abs(alph);
_pageFlip.glare.alpha = alph;
}
/**
*
*/
internal function lineIntersectsRect( rect:Rectangle, p:Vector2, v:Vector2):Array
{
v.normalize();
var xi:Number = (v.i >= 0) ? rect.right - p.i : rect.left - p.i;
var yi:Number = (v.j >= 0) ? rect.bottom - p.j : rect.top - p.j;
var xr:Number = xi / v.i;
var yr:Number = yi / v.j;
var rv1:Vector2 = (xr > yr) ? Vector2.multiply(v, yr).add(p) : Vector2.multiply(v, xr).add(p);
v.negate();
xi = (v.i < 0) ? rect.left - p.i : rect.right - p.i;
yi = (v.j < 0) ? rect.top - p.j : rect.bottom - p.j;
xr = xi / v.i;
yr = yi / v.j;
var rv2:Vector2 = (xr > yr) ? Vector2.multiply(v, yr).add(p) : Vector2.multiply(v, xr).add(p);
return [rv1, rv2];
}
from this project:
http://www.lordofduct.com/FlashTest/pageFlip/PageFlip.html
(loads slow, stupidly big image needs to be loaded)
pj-co
06-19-2008, 06:39 PM
Ok, i think I get it. So lord, do you use that kind of knockout method for drawing a lot? or is this something new for this project because of the need to mask the page in a certain way?
Anyways, it seems like you found something odd about the drawing api when trying to use that knockout method. I wonder if direction is important here, though, it looked like you were going in the same direction. I would say the work around seems to be to draw the full pentagon without the rect, I dont think the overhead would be all that bad. but idunno. either way good luck and let us know how it turns out.
lordofduct
06-20-2008, 01:12 AM
Figured it out, I just have to draw the clipping area in the opposite direction that the original rect was drawn.
thusly this works for the lower left corner:
var spr1:Sprite = new Sprite();
var gr:Graphics = spr1.graphics;
gr.beginFill(0x000000);
gr.drawRect(0,0, 300,300);
gr.moveTo(0,100);
gr.lineTo(0,300);
gr.lineTo(100,300);
gr.lineTo(0,100);
gr.endFill();
var spr2:Sprite = new Sprite();
gr = spr2.graphics;
gr.beginFill(0xFF0000);
gr.drawRect(0,0,300,300);
gr.endFill();
addChild(spr2);
addChild(spr1);
spr2.mask = spr1;
|
vBulletin® v3.8.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.