Costs of SolidBrush Object? - direct2d

Is it (memory/performance-wise) better to a) create SolidBrushes for all colors needed or b) create one SolidBrush and change the color with the SetColor method:
m_pSolidColorBrush->SetColor(
D2D1::ColorF(
0.0f,
intensity,
1.0f - intensity
));
?
I haven't found any documentation or useful code samples..

Performance test result: SetColor() is much faster and works fine.

Related

Slant/Skew a Texture - Monogame

I am trying to Slant/Skew a texture to create some shadows for my game.
I have read over this helpful answer that shows this can be done by passing a matrix to spriteBatch.Begin().
Because my linear algebra skills are not very developed, I am having some troubles meeting my desired results. I am hoping to skew my shadow so it looks similar to the following. Where the shadow is slanted by an angle, but the bottom of the shadow lines up with the (feet in this case) bottom of the sprite.
I originally tied the skew matrix provided in the solution above:
Matrix skew = Matrix.Identity;
skew.M12 = (float)Math.Tan(MathHelper.ToRadians(36.87f));
But this ends up rotation the shadow against the world's origin. I see the solution also notes this, and provides the follow to rotate again the sprite.
Matrix myMatrix = Matrix.CreateTranslation(-100, -100, 0)
* Matrix.CreateScale(2f, 0.5f, 1f)
* Matrix.CreateTranslation(100, 100, 0);
Though I'm not sure where to apply this myMatrix Matrix. I have tried applying it to both the shadow sprite, the castingShadow sprite, and also multiplying them together and applying to the shadow with no luck.
I have also tried using other methods like Matrix.CreateRotationX(MathHelper.ToRadians(0.87f)) with no luck.
There is actually a Matrix.CreateShadow() method too, but it requires a Plane, which I have no semblance of in my game.
Can anyone can help me figure out the required Matrix for this slanting, or point me in the direction of some resources?
Thanks!
Okay, so I found a transform to use to get the desired slant.
Thanks to #David Gouveia and #AndreRussell from this post
Matrix matrix = Matrix.CreateRotationX(MathHelper.ToRadians(60)) *
Matrix.CreateRotationY(MathHelper.ToRadians(30)) *
Matrix.CreateScale(1,1,0);
EDIT:
So the above solution solved how I wanted to slant my texture, but had some weird positioning side effects. To address this, I ended up with a transform like the following:
Matrix slant = Matrix.CreateTranslation(-loc.X + angleX, -loc.Y, 0f) *
Matrix.CreateRotationX(MathHelper.ToRadians(angleX)) *
Matrix.CreateRotationY(MathHelper.ToRadians(30)) *
Matrix.CreateScale(1.4f, 1f, 0) *
Matrix.CreateTranslation(loc.X + angleX, loc.Y, 0f);
Where angleX was set based on the "sun" X position and loc vector is where I want the object and object's shadow to appear.

How can I convert world coordinates to screen coordinates using C++ and DirectX11?

I am working on collisions for a simple 2d game and I am trying to make sure that the sprites cannot leave the edges of the screen, and I understand how this is done, but I can't seem to get the correct coordinates to perform the calculations.
In the image, the black rectangle is my sprite whos world position is around (2.2, 0.0, 0.0) however the screen width is around ~1200. I know that I will have to deal with some sort of matrix calculation but I'm not sure which matrix I will need to use.
I have tried the following from another post on SO, but it doesn't seem to give me correct results
How can I convert my world coordinate (2.2, 0.0, 0.0) to a screen-space coordinate in pixels, so I can compare that against the width of the screen? If anyone can point me in the right direction it would be much appreciated.
Edit
This implementation is slightly incorrect.
I am currently checking if the center position of the rectangle is outside the bounds of the screen.
Given the following image where the world position is (-2.2, 0.0, 0.0), when this is projected into screen space coordinates, I get an X value of -76 when it is clearly on the screen, so it should be above 0. It seems there is some slight offset the more I move the rectangle around, however, at the center of the screen, the X value is correct at ~630, which is half the screen width.
Here is the code I am using to get the screen space coordinates for the center of the rectangle.
float centerX = boundingBox.m_center.x;
XMVECTOR centerVector = XMVectorSet(centerX, 0.0f, 0.0f, 0.0f);
XMVECTOR centerProjection = XMVector3Project(centerVector, 0.0f, 0.0f, screenSize.Width, screenSize.Height, 0.0f, 1.0f, projection, view, worldMatrix);
float centerScreenSpace = XMVectorGetX(centerProjection);
Does anyone have any ideas why this might be?
There seems to be a 150-200 pixel offset

In Processing, getting constant stroke width independent of scale

What value fed to strokeWidth() will give a stroke width of one pixel regardless of the current scale() setting?
I think strokeWeight(0) should work. Here is an example:
void setup() {
size(100,100);
noFill();
scale(10);
// 1st square, stroke will be 10 pixels
translate(3,3);
strokeWeight(1);
beginShape();
vertex(-1.0, -1.0);
vertex(-1.0, 1.0);
vertex( 1.0, 1.0);
vertex( 1.0, -1.0);
endShape(CLOSE);
// 2nd square, stroke will be 1 pixel
translate(3,3);
strokeWeight(0);
beginShape();
vertex(-1.0, -1.0);
vertex(-1.0, 1.0);
vertex( 1.0, 1.0);
vertex( 1.0, -1.0);
endShape(CLOSE);
}
Kevin did offer a couple of good approaches.
Your question doesn't make it clear what level of comfort you have with the language. My assumption (and I could be wrong) is that the layers approach isn't clear as you might have not used PGraphics before.
However, this option Kevin provided is simple and straight forward:
multiplying the coordinates manually
Notice most drawing functions take not only the coordinates, but also dimensions ?
Don't use scale(), but keep track of a multiplier floating point variable that you use for the shape dimensions. Manually scale the dimensions of each shape:
void draw(){
//map mouseX to a scale between 10% and 300%
float scale = map(constrain(mouseX,0,width),0,width,0.1,3.0);
background(255);
//scale the shape dimensions, without using scale()
ellipse(50,50, 30 * scale, 30 * scale);
}
You can run this as a demo bellow:
function setup(){
createCanvas(100,100);
}
function draw(){
//map mouseX to a scale between 10% and 300%
var scale = map(constrain(mouseX,0,width),0,width,0.1,3.0);
background(200);
//scale the shape dimensions, without using scale()
ellipse(50,50, 30 * scale, 30 * scale);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.7/p5.min.js"></script>
Another answer is in the question itself: what value would you feed to strokeWidth() ? If scale() is making the stroke bigger, but you want to keep it's appearance the same, that means you need to use a smaller stroke weight as scale increases: the thickness is inversely proportional to the scale:
void draw(){
//map mouseX to a scale between 10% and 300%
float scale = map(constrain(mouseX,0,width),0,width,0.1,3.0);
background(255);
translate(50,50);
scale(scale);
strokeWeight(1/scale);
//scaled shape, same appearing stroke, just smaller in value as scale increases
ellipse(0,0, 30, 30);
}
You can run this bellow:
function setup(){
createCanvas(100,100);
}
function draw(){
//map mouseX to a scale between 10% and 300%
var scaleValue = map(constrain(mouseX,0,width),0,width,0.1,3.0);
background(240);
translate(50,50);
scale(scaleValue);
strokeWeight(1/scaleValue);
//scale the shape dimensions, without using scale()
ellipse(0,0, 30, 30);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.7/p5.min.js"></script>
Kevin was patient, not only to answer your question, but also your comments, being generous with his time. You need to be patient to carefully read and understand the answers provided. Try it on your own then come back with specific questions on clarifications if that's the case. It's the best way to learn.
Simply asking "how do I do this ?" without showing what you're tried and what your thinking behind the problem is, expecting a snippet to copy/paste will not get your very far and this is not what stackoverflow is about.
You'll have way more to gain by learning, using the available documentation and especially thinking about the problem on your own first. You might not crack the problem at the first go (I know I certainly don't), but reasoning about it and viewing it from different angles will get your gears going.
Always be patient, it will serve you well on the long run, regardless of the situation.
Update Perhaps you mean by
What value fed to strokeWidth() will give a stroke width of one pixel regardless of the current scale() setting?
is how can you draw without anti-aliasing ?
If so, you can disable smoothing via a line: calling noSmooth(); once in setup(). Try it with the example code above.
None.
The whole point of scale() is that it, well, scales everything.
You might want to draw things in layers: draw one scaled layer, and one unscaled layer that contains the single-pixel-width lines. Then combine those layers.
That won't work if you need your layers to be mixed, such as an unscaled line on top of a scaled shape, on top of another scaled line. In that case you'll just have to unscale before drawing your lines, then scale again to draw your shapes.

glDrawPixels() with 0.375 translation

I've noticed some strange behaviour with glDrawPixels() when using a 0.375 translation. This is my GL initialization:
width = 640; height = 480;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity( );
glOrtho(0, width, height, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity( );
glTranslatef(0.375, 0.375, 0.0);
Now I want to draw a 640x30 pixel buffer to the very last 30 rows of my GL window. Hence, I do the following:
glRasterPos2i(0, 480);
glDrawPixels(640, 30, GL_RGBA, GL_UNSIGNED_BYTE, pixelbuffer);
Unfortunately, nothing gets drawn using this code. glGetError() also returns 0. The interesting thing is that as soon as I remove the call to glTranslatef(0.375, 0.375, 0.0) everything works fine!
So could somebody explain to me why this 0.375 translation on both axes confuses glDrawPixels()? Is this somehow rounded to 1.0 internally making my call to glDrawPixels() suddenly want to draw beyond the context's boundaries and thus it gets clipped by OpenGL? This is the only explanation I can think of but I don't understand why OpenGL should round a 0.375 translation to 1.0... it should be rounded down to 0.0 instead, shouldn't it?
The point (0,480) actually straddles one of your clipping planes given your projection matrix. Your sub-pixel shift hack pushes the point beyond the breaking point and the raster position is clipped. In GL, glRasterPos (...) will invalidate all following raster operations as long as the initial position is clipped (which in this case, it is).
You could try glRasterPos2i (0, 479). This is altogether more meaningful given the dimensions of your window anyway. You could also drop the whole charade and use glWindowPos2i (...) instead of relying on your projection and modelview matrices to position the raster coordinate in window-space.
I can't answer your question on why glTranslatef stops glDrawPixels from working, but I can tell you that isn't the way to select where to draw. Check the man page for glDrawPixels for a bit more info. It will tell you about glRasterPos and glWindowPos

The transform property in CGPathAddEllipseInRect

I am using CGPathAddEllipseInRect to draw a circle and then using that in CAKeyframeAnimation. My issue is that the animation always starts in the same spot. I thought that I could do the following with a CGAffineTransform to make it start in a different point:
CGAffineTransform temp = CGAffineTransformMakeRotation(M_PI / 2);
CGPathAddEllipseInRect(animationPath , &temp, rect);
I do not know what this is doing. When it runs, I don't even see this portion of the animation. It is doing something offscreen. Any help understanding this would be great.
The rotation happens around the origin (0,0) by default, but you want to rotate around the center of the circle, so you have to do additional transformations:
float midX = CGRectGetMidX(rect);
float midY = CGRectGetMidY(rect);
CGAffineTransform t =
CGAffineTransformConcat(
CGAffineTransformConcat(
CGAffineTransformMakeTranslation(-midX, -midY),
CGAffineTransformMakeRotation(angle)),
CGAffineTransformMakeTranslation(midX, midY));
CGPathAddEllipseInRect(animationPath, &t, rect);
Essentially, this chains three transformations: First, the circle is moved to the origin (0,0), then the rotation is applied and afterwards it is moved back to its original position. I've made a little visualization to illustrate the effect:
I chose a square instead of a circle and 45° instead of 90° to make the rotation easier to see, but the principle is the same.

Resources