Qt 5.5 drawing a pointer - rotation

Is there a built in method for drawing an arrow/pointer at the end of a line in Qt?
I know I can draw it myself, but curious to know if there is already a way of doing this, I've search online and couldn't find anything.
I want to be able to rotate the line and the arrow rotates with it.
Below is the image I'm working on:
I would like to draw the arrow at the end of the dashed line, it should rotate with the dash line pointing around from the bottom left.
[edit] In the end I used a polygon and rotated that:
Code to add polygon needle:
Polygon clsMyClass::plygnGetNeedle(QPoint* pptOrigin
,int intRadius
,float fltAngle) {
const int cintNeedleHalfWidth = 4;
QPolygon plyNeedle;
int intX = pptOrigin->x(), intY = pptOrigin->y();
plyNeedle << QPoint(intX - cintNeedleHalfWidth, intY)
<< QPoint(intX, intY + cintNeedleHalfWidth)
<< QPoint(intX + intRadius - cintNeedleHalfWidth, intY)
<< QPoint(intX, intY- cintNeedleHalfWidth);
return QTransform().translate(intX, intY)
.rotate(fltAngle)
.translate(-intX, -intY)
.map(plyNeedle);
}

I don't recall something like this in Qt. As for the position and angle of the arrow - you can easily find those out if you use something like QPainterPath's angleAtPercent() and pointAtPercent() functions.

Related

How to invert the sprite position in GameMaker Studio 2 code?

I put this code for my sprite to reverse the position according to its direction but it reverses the position and it looks skinny. How to fix this?
key_left = keyboard_check(ord("A"))
key_right = keyboard_check(ord("D"))
key_jump = keyboard_check(vk_space)
var move = key_right - key_left
hspd = move * spd;
vspd = vspd + grv;
if (hspd != 0) {
image_xscale = sign(hspd)
}
The code's correct. You must have resized the sprite in the room editor, delete the instance and put it in again and don't resize it, it should work.
Also if you need it a little bigger you can (If 1.5 doesn't satisfy you, feel free to use a bigger number).
image_xscale = sign(hspd) * 1.5;
The code seem to be correct, have you tried setting the origin point at the center? By default the origin point is on the top-left, and once it's set at the center of your sprite, it won't change positions when turning around.
You can set the origin point at the sprite window.

OpenVR Teleportation Problem (Forward direction calculation)

So I am trying to implement teleportation in my VR application (not in Unity). I am able to get the pose matrices for each controller from
if (auto error = vr::VRInput()->GetPoseActionDataForNextFrame(hand[eHand].pose_handle, vr::TrackingUniverseStanding, &poseData, sizeof(poseData), vr::k_ulInvalidInputValueHandle) != vr::VRInputError_None
|| !poseData.bActive || !poseData.pose.bPoseIsValid)
{
std::cerr << "pose invalid " << error << std::endl;
}
else
{
hand[eHand].pose = ConvertSteamVRMatrixToMatrix4(poseData.pose.mDeviceToAbsoluteTracking);
}
I then use glm::decompose() to get the position and orientation (orientation must be conjugated). Then I try to get the forward direction from it by multiplying the orientation matrix by vec4(0,0,1,0) but the resultant vector is incorrect. Is there a flaw in my logic?
So it turns out I had a few issues with my methodology. Firstly, OpenVR defines the forward direction of the controllers as vec4(0,0,-1,0), and secondly, it is defined with respect to the HMD camera. In order to move around the scene, I use a second camera matrix for translation and rotation. Thus had to take this into account.
My final calculation is as follows
auto forward = glm::normalize(glm::inverse(nonHMDViewMat) *
vr.GetControllerPose(Right) * glm::vec4(0,0,-1,0));
Where vr.GetControllerPose(Right) returns the matrix in hand[eHand].pose for the right hand.

Rotation between 2 points facing away when standing at back while facing towards while standing infront (pics)

With this little piece of code I've made it possible to rotate the 'monster' towards the avatar but if the avatar is behind the 'monster', the 'monster' is facing away from the avatar. (Pic's below)
Note: the white numbers are the value of m_RotationAngle
DOUBLE2 mousePos = GAME_ENGINE->GetMousePosition();
double xDiff = m_ActPtr->GetPosition().x - mousePos.x;
double yDiff = m_ActPtr->GetPosition().y - mousePos.y;
m_RotationAngle = atan(yDiff, xDiff);
m_ActPtr->SetAngle(m_RotationAngle);
I've tried to fix it with:
if (diff.x < 0)
{
m_RotationAngle = -atan(diff.y / diff.x);
//also tried following but gave and error:
//m_RotationAngle = tan(diff.y / diff.x);
}
else
{
m_RotationAngle = atan(diff.y / diff.x);
}
But this gave the following output:
You are probably looking for atan2(yDiff, xDiff); which computes the arc tangent of yDiff/xDiff using the signs of arguments to determine the correct quadrant, instead of atan (which also require only one parameter).
Be aware that the result is in the range [-π ; +π] radians, not degrees.

Visual C++: Good way to draw and animated fill path to screen?

I want to use Visual C++ to animate fill paths to screen. I have done it with C# before, but now switch to C++ for better perfomance and want do more complex works in the future.
Here is the concept in C#:
In a Canvas I have a number of Path. These paths are closed geometries combine of LineTo and QuadraticBezierTo functions.
Firstly, I fill Silver color for all path.
Then for each path, I fill Green color from one end to other end (up/down/left/right direction) (imagine a progress bar increase its value from min to max). I do it by set the Fill brush of the path to a LinearGradientBrush with two color Green and Silver with same offset, then increase the offset from 0 to 1 by Timer.
When a path is fully green, continue with next path.
When all path is fill with Green, come back first step.
I want to do same thing in Visual C++. I need to know an effective way to:
Create and store paths in a collection to reuse. Because the path is quite lot of point, recreate them repeatly take lots of CPU usage.
Draw all paths to a window.
Do animation fill like step 2, 3, 4 in above concept.
So, what I need is:
A suitable way to create and store closed paths. Note: paths are combine of points connect by functions same with C# LineTo and QuadraticBezierTo function.
Draw and animated fill the paths to screen.
Can you please suggest one way to do above step? (outline what I have to read, then I can study about it myself). I know basic of Visual C++, Win32 GUI and a little about draw context (HDC) and GDI, but only start to learn Graphic/Drawing.
Sorry about my English! If anythings I explain dont clear, please let me know.
how many is quite lot of point ? what is the target framerate? for low enough counts you can use GDI for this otherwise you need HW acceleration like OpenGL,DirectX.
I assume 2D so You need:
store your path as list of segments
for example like this:
struct path_segment
{
int p0[2],p1[2],p2[2]; // points
int type; // line/bezier
float length; // length in pixels or whatever
};
const int MAX=1024; // max number of segments
path_segment path[MAX]; // list of segments can use any template like List<path_segment> path; instead
int paths=0; // actual number of segments;
float length=0.0; // while path length in pixels or whatever
write functions to load and render path[]
The render is just for visual check if you load is OK ... for now atlest
rewrite the render so
it take float t=<0,1> as input parameter which will render path below t with one color and the rest with other. something like this:
int i;
float l=0.0,q,l0=t*length; // separation length;
for (i=0;i<paths;i++)
{
q=l+path[i].length;
if (q>=l0)
{
// split/render path[i] to < 0,l-l0> with color1
// split/render path[i] to <l-l0,q-l0> with color2
// if you need split parameter in <0,1> then =(l-l0)/path[i].length;
i++; break;
}
else
{
//render path[i] with color1
}
l=q;
}
for (;i<paths;i++)
{
//render path[i] with color2
}
use backbuffer for speedup
so render whole path with color1 to some bitmap. On each animation step just render the newly added color1 stuff. And on each redraw just copy the bitmap to screen instead of rendering the same geometry over and over. Of coarse if you have zoom/pan/resize capabilities you need to redraw the bitmap fully on each of those changes ...

Zoom toward mouse (eg. Google maps)

I've written a home-brew view_port class for a 2D strategy game. The panning (with arrow keys) and zooming (with mouse wheel) work fine, but I'd like the view to also home towards wherever the cursor is placed, as in Google Maps or Supreme Commander
I'll spare you the specifics of how the zoom is implemented and even what language I'm using: this is all irrelevant. What's important is the zoom function, which modifies the rectangle structure (x,y,w,h) that represents the view. So far the code looks like this:
void zoom(float delta, float mouse_x, float mouse_y)
{
zoom += delta;
view.w = window.w/zoom;
view.h = window.h/zoom;
// view.x = ???
// view.y = ???
}
Before somebody suggests it, the following will not work:
view.x = mouse_x - view.w/2;
view.y = mouse_y - view.h/2;
This picture illustrates why, as I attempt to zoom towards the smiley face:
As you can see when the object underneath the mouse is placed in the centre of the screen it stops being under the mouse, so we stop zooming towards it!
If you've got a head for maths (you'll need one) any help on this would be most appreciated!
I managed to figure out the solution, thanks to a lot of head-scratching a lot of little picture: I'll post the algorithm here in case anybody else needs it.
Vect2f mouse_true(mouse_position.x/zoom + view.x, mouse_position.y/zoom + view.y);
Vect2f mouse_relative(window_size.x/mouse_pos.x, window_size.y/mouse_pos.y);
view.x = mouse_true.x - view.w/mouse_relative.x;
view.y = mouse_true.y - view.h/mouse_relative.y;
This ensures that objects placed under the mouse stay under the mouse. You can check out the code over on github, and I also made a showcase demo for youtube.
In my concept there is a camera and a screen.
The camera is the moving part. The screen is the scalable part.
I made an example script including a live demo.
The problem is reduced to only one dimension in order to keep it simple.
https://www.khanacademy.org/cs/cam-positioning/4772921545326592
var a = (mouse.x + camera.x) / zoom;
// now increase the zoom e.g.: like that:
zoom = zoom + 1;
var newPosition = a * zoom - mouse.x;
camera.setX(newPosition);
screen.setWidth(originalWidth * zoom);
For a 2D example you can simply add the same code for the height and y positions.

Resources