How to transform one of DirectWrite text objects while keep others no change - direct2d

I have several DirectWrite text objects on a same render target and I want to transform one of them at one time while keep others no change, In Direct2D, there are several type of transforms
Render target transform
Geometry transform
Brush transform
I can not use render target transform since it affects all the objects on it
I can not use geometry transform, since text is not a geometry, and there is no transform method for IDWriteTextLayout.
So the only choice for me is brush transform, but when I try to use the solid brush to draw a transformed rectangle, it still draw it in the original place(see code below), the sdk demo show an example of bitmap brush transform, so my question is: does transform works for other type of brush? like solid brush?
here is my code, first, calculate a translate matrix based on the time elapsed, then use this matrix to translate the brush and at last draw the rectangle. please take a look and tell me whether this is the case or if I can do it in some way else?
VOID CalculateTranslationMatrix(D2D1_MATRIX_3X2_F* matrix)
{
static float totalTime = 0.0f;
// Get start time
static DWORD startTime = timeGetTime();
// Get current time
DWORD currentTime = timeGetTime();
// Calculate time elapsed
float timeElapsed = (currentTime - startTime) * 0.001f;
// Accumulate total time elapsed
totalTime += timeElapsed;
// Build up the translation matrix
matrix->_11 = 1.0f;
matrix->_12 = 0.0f;
matrix->_21 = 0.0f;
matrix->_22 = 1.0f;
matrix->_31 = totalTime;
matrix->_32 = totalTime;
}
VOID DrawRectangle(HWND hwnd)
{
CreateD2DResource(hwnd) ;
g_pRenderTarget->BeginDraw() ;
// Clear background color to white
g_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));
D2D1_MATRIX_3X2_F matrix;
CalculateTranslationMatrix(&matrix);
g_pBlackBrush->SetTransform(&matrix);
// Draw Rectangle
g_pRenderTarget->DrawRectangle(
D2D1::RectF(10.f, 10.f, 50.f, 50.f),
g_pBlackBrush
);
HRESULT hr = g_pRenderTarget->EndDraw() ;
if (FAILED(hr))
{
MessageBox(NULL, "Draw failed!", "Error", 0) ;
return ;
}
}

You could use render target transform, and just apply and restore states, eg:
Before draw, call g_pRenderTarget->GetTransform to get copy of the current transform
Set your desired object transform
Draw your object
use g_pRenderTarget->SetTransform using the value you saved before the draw.

Related

GDI: Create Mountain Chart/Graph?

I can use Polyline() GDI function to plot values to create a graph but now I want the lower part of it filled in to create a mountain type chart. Is there something built-in to help create that? (I don't need gradient, but that would be a nice touch).
TIA!!
For this diagram type you need to draw a filled shape. The Polygon function can be used to draw an irregularly shaped filled object:
The polygon is outlined by using the current pen and filled by using the current brush [...].
The polygon points need to be constructed from the data points (left to right). To turn this into a closed shape, the bottom right and bottom left points of the diagram area need to be appended. The Polygon function then closes the shape automatically by drawing a line from the last vertex to the first.
The following implementation renders a single data set into a given device context's area:
/// \brief Renders a diagram into a DC
///
/// \param dc Device context to render into
/// \param area Diagram area in client coordinates
/// \param pen_col Diagram outline color
/// \param fill_col Diagram fill color
/// \param data Data points to render in data coordinate space
/// \param y_min Y-axis minimum in data coordinate space
/// \param y_max Y-axis maximum in data coordiante space
void render_diagram(HDC dc, RECT area,
COLORREF pen_col, COLORREF fill_col,
std::vector<int> const& data, int y_min, int y_max) {
// Make sure we have data
if (data.size() < 2) { return; }
// Make sure the diagram area isn't empty
if (::IsRectEmpty(&area)) { return; }
// Make sure the y-scale is sane
if (y_max <= y_min) { return; }
std::vector<POINT> polygon{};
// Reserve enough room for the data points plus bottom/right
// and bottom/left to close the shape
polygon.reserve(data.size() + 2);
auto const area_width{ area.right - area.left };
auto const area_height{ area.bottom - area.top };
// Translate coordinates from data space to diagram space
// In lieu of a `zip` view in C++ we're using a raw loop here
// (we need the index to scale the x coordinate, so we cannot
// use a range-based `for` loop)
for (int index{}; index < static_cast<int>(data.size()); ++index) {
// Scale x value
auto const x = ::MulDiv(index, area_width - 1, static_cast<int>(data.size()) - 1) + area.left;
// Flip y value so that the origin is in the bottom/left
auto const y_flipped = y_max - (data[index] - y_min);
// Scale y value
auto const y = ::MulDiv(y_flipped, area_height - 1, y_max - y_min);
polygon.emplace_back(POINT{ x, y });
}
// Semi-close the shape
polygon.emplace_back(POINT{ area.right - 1, area.bottom - 1 });
polygon.emplace_back(POINT{ area.left, area.bottom - 1 });
// Prepare the DC for rendering
auto const prev_pen{ ::SelectObject(dc, ::GetStockObject(DC_PEN)) };
auto const prev_brush{ ::SelectObject(dc, ::GetStockObject(DC_BRUSH)) };
::SetDCPenColor(dc, pen_col);
::SetDCBrushColor(dc, fill_col);
// Render the graph
::Polygon(dc, polygon.data(), static_cast<int>(polygon.size()));
// Restore DC (stock objects do not need to be destroyed)
::SelectObject(dc, prev_brush);
::SelectObject(dc, prev_pen);
}
Most of this function deals with translating and scaling data values into the target (client) coordinate space. The actual rendering is fairly compact in comparison, and starts from the comment reading // Prepare the DC for rendering.
To test this you can start from a standard Windows Desktop application, and dump the following into the WM_PAINT handler:
case WM_PAINT:
{
RECT rc{};
::GetClientRect(hWnd, &rc);
// Leave a 10px border around the diagram area
::InflateRect(&rc, -10, -10);
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
auto pen_col = RGB(0x00, 0x91, 0x7C);
auto fill_col = RGB(0xCC, 0xE9, 0xE4);
render_diagram(hdc, rc, pen_col, fill_col, g_dataset1, 0, 100);
pen_col = RGB(0x02, 0x59, 0x55);
fill_col = RGB(0xCC, 0xDD, 0xDD);
render_diagram(hdc, rc, pen_col, fill_col, g_dataset2, 0, 100);
EndPaint(hWnd, &ps);
}
break;
g_dataset1/g_dataset2 are containers holding random values that serve as test input. It is important to understand, that the final diagram is rendered back to front, meaning that data sets with smaller values need to be rendered after data sets with higher values; the lower portion gets repeatedly overdrawn.
This produces output that looks something like this:
Note that on a HiDpi display device GDI rendering gets auto-scaled. This produces the following:
Looking closely you'll observe that the lines are wider than 1 device pixel. If you'd rather have a more crisp look, you can disable DPI virtualization by declaring the application as DPI aware. Things don't change for a standard DPI display; on a HiDpi display the rendering now looks like this:

How do I blur/unblur the picture according to the mouseY position - going down - blur, going up - unblur

It's like the blur is in never ending loop.
This is what I've wrote so far, it's currently always blurring it up again and again, and I can't make it un-blur.
void draw() {
filter(BLUR, blurRate/60);
nextY = mouseY-blurRate;
blurRate= nextY-mouseY;
}
It will help to split the problem into smaller subproblems.
(Kevin Workman's article is a great start)
The code you shared looks like you're trying to do two things at once:
map the mouse Y position to a blur value
apply the blur value to the blur filter
Let's start with mapping the value.
If you know what the minimum / maximum blur value you need you can make your life easier using Processing's map() function. It takes a value(mouseY in your case) and maps it from one range (mouseY's min/max range: 0 to height) to another range (blur's min/max value, let's say 0 to 6)
The mapping range above (from 0, height to 0, 6) is trivial because can simply divide height / 6 and get the mapped value, but map() is pretty useful and worth getting the hang of.
Here's a minimal mapping example:
void setup(){
}
void draw(){
float blurValue = map(mouseY, 0, height, 0, 6);
background(0);
text("blurValue: " + blurValue, 5, height / 2);
}
The second part is applying the blur filter.
The catch here is avoiding this situation:
currently always blurring it up again and again,
This happens because you apply the blur filter in draw() multiple times per second to the content, so each pass blurs further.
It sounds like what you want is to apply the blur filter to the initial state of your image or graphics. The code you posted doesn't show what is it that you're trying to blur.
If using graphics rendered in processing, one option is to simply clear everything (using background()) and redrawing the graphics before applying the filter. With the filter applied in draw and nothing cleared/redrawn the effect is reapplied to the same (pre blurred) content continously.
Let's take this basic example:
void setup(){
}
void draw(){
line(mouseX, mouseY, pmouseX, pmouseY);
}
Notice that even draw we render a single tiny line, because the graphics aren't cleared (using background()) each tiny line accumulates to form a larger path.
Intuitively, adding blur will accumulate the effect:
void setup(){
}
void draw(){
line(mouseX, mouseY, pmouseX, pmouseY);
filter(BLUR, 0.6);
}
Another option, if you'd rather be more efficient and re-render the same graphics in draw(), you can get an image copy of what's been rendered so far which you could render continuously.
Let's say you're drawing something in setup().
You can easily call get()(with no arguments) to get a "snapshot" of what's been drawn so far a PImage.
Once you have that you can simply render it again and again in draw() as it was drawn in setup() using image().
Once image() is called you can then call filter() with be applied to the global Processing graphics, meaning only what's rendered (while the snapshot PImage will remain intact).
Here's an example illustrating the above:
PImage snapshot;
void setup(){
// draw something
background(0);
noFill();
strokeWeight(3);
for(int i = 0 ; i < 100; i++){
stroke(random(32, 128));
float size = random(3, 27);
ellipse(random(width), random(height), size, size);
}
// take a snapshot of the current graphics
snapshot = get();
}
void draw(){
float blurValue = map(mouseY, 0, height, 0, 6);
// render the image snapshot
image(snapshot, 0, 0);
// blur it
filter(BLUR, blurValue);
// display blur value (should be unblurred)
text("blurValue: " + blurValue, 5, height / 2);
}
Your question doesn't specify, but if you are using PImage, then you need to apply blur to a copy of the image to avoid re-applying blur to an already blurred image. Here's a PImage tweaked version of the above:
PImage snapshot;
void setup(){
// draw something
background(0);
noFill();
strokeWeight(3);
for(int i = 0 ; i < 100; i++){
stroke(random(32, 128));
float size = random(3, 27);
ellipse(random(width), random(height), size, size);
}
// take a snapshot of the current graphics
snapshot = get();
}
void draw(){
float blurValue = map(mouseY, 0, height, 0, 6);
// clone the original image via get()
PImage blurredImage = snapshot.get();
// blur the cloned image
blurredImage.filter(BLUR, blurValue);
// display the blurred image
image(blurredImage, 0, 0);
// display blur value (should be unblurred)
text("blurValue: " + blurValue, 5, height / 2);
}

Storing motion vectors from calculated optical flow in a practical way which enables reconstruction of subsequent frames from initial keyframes

I am trying to store the motion detected from optical flow for frames in a video sequence and then use these stored motion vectors in order to predict the already known frames using just the first frame as a reference. I am currently using two processing sketches - the first sketch draws a motion vector for every pixel grid (each of width and height 10 pixels). This is done for every frame in the video sequence. The vector is only drawn in a grid if there is sufficient motion detected. The second sketch aims to reconstruct the video frames crudely from just the initial frame of the video sequence combined with information about the motion vectors got from the first sketch.
My approach so far is as follows: I am able to determine the size, position and direction of each motion vector drawn in the first sketch from four variables. By creating four arrays (two for the motion vector's x and y coordinate and another two for its length in the x and y direction), every time a motion vector is drawn I can append each of the four variables to the arrays mentioned above. This is done for each pixel grid throughout an entire frame where the vector is drawn and for each frame in the sequence - via for loops. Once the arrays are full, I can then save them to a text file as a list of strings. I then load these strings from the text file into the second sketch, along with the first frame of the video sequence. I load the strings into variables within a while loop in the draw function and convert them back into floats. I increment a variable by one each time the draw function is called - this moves on to the next frame (I used a specific number as a separator in my text-files which appears at the end of every frame - the loop searches for this number and then increments the variable by one, thus breaking the while loop and the draw function is called again for the subsequent frame). For each frame, I can draw 10 by 10 pixel boxes and move then by the parameters got from the text files in the first sketch. My problem is simply this: How do I draw the motion of a particular frame without letting what I've have blitted to the screen in the previous frame affect what will be drawn for the next frame. My only way of getting my 10 by 10 pixel box is by using the get() function which gets pixels that are already drawn to the screen.
Apologies for the length and complexity of my question. Any tips would be very much appreciated! I will add the code for the second sketch. I can also add the first sketch if required, but it's rather long and a lot of it is not my own. Here is the second sketch:
import processing.video.*;
Movie video;
PImage [] naturalMovie = new PImage [0];
String xlengths [];
String ylengths [];
String xpositions [];
String ypositions [];
int a = 0;
int c = 0;
int d = 0;
int p;
int gs = 10;
void setup(){
size(640, 480, JAVA2D);
xlengths = loadStrings("xlengths.txt");
ylengths = loadStrings("ylengths.txt");
xpositions = loadStrings("xpositions.txt");
ypositions = loadStrings("ypositions.txt");
video = new Movie(this, "sample1.mov");
video.play();
rectMode(CENTER);
}
void movieEvent(Movie m) {
m.read();
PImage f = createImage(m.width, m.height, ARGB);
f.set(0, 0, m);
f.resize(width, height);
naturalMovie = (PImage []) append(naturalMovie, f);
println("naturalMovie length: " + naturalMovie.length);
p = naturalMovie.length - 1;
}
void draw() {
if(naturalMovie.length >= p && p > 0){
if (c == 0){
image(naturalMovie[0], 0, 0);
}
d = c;
while (c == d && c < xlengths.length){
float u, v, x0, y0;
u = float(xlengths[a]);
v = float(ylengths[a]);
x0 = float(xpositions[a]);
y0 = float(ypositions[a]);
if (u != 1.0E-19){
//stroke(255,255,255);
//line(x0,y0,x0+u,y0+v);
PImage box;
box = get(int(x0-gs/2), int(y0 - gs/2), gs, gs);
image(box, x0-gs/2 +u, y0 - gs/2 +v, gs, gs);
if (a < xlengths.length - 1){
a += 1;
}
}
else if (u == 1.0E-19){
if (a < xlengths.length - 1){
c += 1;
a += 1;
}
}
}
}
}
Word to the wise: most people aren't going to read that wall of text. Try to "dumb down" your posts so they get to the details right away, without any extra information. You'll also be better off if you post an MCVE instead of only giving us half your code. Note that this does not mean posting your entire project. Instead, start over with a blank sketch and only create the most basic code required to show the problem. Don't include any of your movie logic, and hardcode as much as possible. We should be able to copy and paste your code onto our own machines to run it and see the problem.
All of that being said, I think I understand what you're asking.
How do I draw the motion of a particular frame without letting what I've have blitted to the screen in the previous frame affect what will be drawn for the next frame. My only way of getting my 10 by 10 pixel box is by using the get() function which gets pixels that are already drawn to the screen.
Separate your program into a view and a model. Right now you're using the screen (the view) to store all of your information, which is going to cause you headaches. Instead, store the state of your program into a set of variables (the model). For you, this might just be a bunch of PVector instances.
Let's say I have an ArrayList<PVector> that holds the current position of all of my vectors:
ArrayList<PVector> currentPositions = new ArrayList<PVector>();
void setup() {
size(500, 500);
for (int i = 0; i < 100; i++) {
currentPositions.add(new PVector(random(width), random(height)));
}
}
void draw(){
background(0);
for(PVector vector : currentPositions){
ellipse(vector.x, vector.y, 10, 10);
}
}
Notice that I'm just hardcoding their positions to be random. This is what your MCVE should do as well. And then in the draw() function, I'm simply drawing each vector. This is like drawing a single frame for you.
Now that we have that, we can create a nextFrame() function that moves the vectors based on the ArrayList (our model) and not what's drawn on the screen!
void nextFrame(){
for(PVector vector : currentPositions){
vector.x += random(-2, 2);
vector.y += random(-2, 2);
}
}
Again, I'm just hardcoding a random movement, but you would be reading these from your file. Then we just call the nextFrame() function as the last line in the draw() function:
If you're still having trouble, I highly recommend posting an MCVE similar to mine and posting a new question. Good luck.

How to add (not blend) non-looped animation clip to looped animation with Mecanim?

I have a GameObject with Animator and looped animation clip.
This animation changes X coordinate from 0 to 10 and back.
I need to add another animation to the first one that increases GameObject's scale and changes its color to red simultaneously.
After scale and color change GameObject keeps these parameters and continues to move according to the first animation clip.
The only way I managed to work it around is writing a custom script with couroutine:
IEnumerator Animate()
{
float scaleDelta = 0.2f;
float colorDelta = 0.02f;
for (int i = 0; i < 50; i++)
{
spriteRenderer.color = new Color(
spriteRenderer.color.r,
spriteRenderer.color.g - colorDelta,
spriteRenderer.color.b - colorDelta);
transform.localScale = new Vector3(
transform.localScale.x + scaleDelta,
transform.localScale.y + scaleDelta,
transform.localScale.z);
yield return new WaitForSeconds(0.02f);
}
}
This works for linear interpolation, but requires to write additional code and write even more code for non-linear transformations.
How can I achieve the same result with Mecanim?
Sample project link: https://drive.google.com/file/d/0B8QGeF3SuAgTU0JWNGd2RnpUU00/view?usp=sharing

Processing Bullets interaction

Hi How do I make bullets to collide with the objects in Processing ?
Bullets are fired and being translated and rotated
but whenever i try to use function dist() it always gives me 0 as the position of the vector
How do i get the correct vector position if i want the bullet to collide with objects using distance and make the the other object disappear ?
Here's the code
void move(){
passed = passed + time;
if (passed > bulletLife) {
alive = false;
}
forward.x = sin(theta);
forward.y = -cos(theta);
float speed = 15.0f;
velocity = PVector.mult(forward, speed);
side.add(forward);
void display(){
pushMatrix();
translate(side.x, side.y);
rotate(theta);
stroke(255);
ellipse(side.x, side.y, 30, 30);
popMatrix();
Thanks
You're getting 0 from dist() because translate() moves the coordinate system! I think, more than your question, you need to reconsider your code overall. You translate to side.x, side.y (which will then be 0,0 until you call popMatrix()) but then you draw the ellipse at side.x, side.y which is offset from its actual position.
In other words: if the position is 100,200, you're actually drawing the object at 200,400!
If you skip the translate() part, you can use this to draw your object:
void display() {
stroke(255);
ellipse(side.x, side.y, 30,30);
}
And this to check collision:
if (dist(side.x, side.y, bullet.x, bullet.y) == 0) {
collision = true;
}
else {
collision = false;
}
You can also see my collision-detection functions for Processing, which have lots of examples that might help.

Resources