Public Group

# Lost in the Matrix

This topic is 502 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Basically I wanted to become more familiar with matrix usage, starting 2D, so I put up a basic setup where I have an "interactive wheel" that spits out whatever angle its handle is set to (image below)

Now I have my basisVector y and x because I get the feeling those are needed, and I have a horizontal line floating on top of y.

My goal would be to rotate that line with a vector Matrix multiplication based on the angle I get from my interactive wheel, as you would do in 3d I guess (the whole point of this is to get me familiar with matrices usage after all, so it need to be done that way), the problem is that from here I don't know how to proceed to build my rotation matrix, where to place my elements, what multiply with what...I am kind of lost.

so this below is the code situation, and I need some help to get from where I am to where I want to be...

float angle = mHandle->getHandleAngle();
D2D1_POINT_2F basisX = { 1,0 };
D2D1_POINT_2F basisY = { 0,1 };

//draw line
mBrush->SetColor(D2D1::ColorF(0.87f, 0.3f, 0.36f, 1.f));
D2D1_POINT_2F lineP1 = D2D1::Point2F(mOriginX - 100, mOriginY - 150);
D2D1_POINT_2F lineP2 = D2D1::Point2F(mOriginX + 100, mOriginY - 150);
mRenderTarget->DrawLine(lineP1, lineP2, mBrush, 2.f);

//replace draw line above with a line rotated by a rotation matrix
mRenderTarget->DrawLine(D2D1::Point2F(),//Begin point
D2D1::Point2F(),//End point
mBrush, 2.f);

Edited by MarcusAseth

##### Share on other sites

Check out this article here https://msdn.microsoft.com/en-us/library/windows/desktop/ff684172(v=vs.85).aspx. The classic clock exercise will give you a good idea as to how rotations work and how to use them in Direct2D.

Basically you will need to use the D2D1::Matrix3x2F class (particularly the D2D1::Matrix3x2F::Rotation(angle, center) function) to create a rotation matrix and then apply it to both lineP1 and lineP2 before rendering them.

##### Share on other sites

Apologize samoan, for some reason I didn't saw your reply the first time trough, that' weird

I'll check that too, thanks!

##### Share on other sites

@ninnghazad:  that link really helped, thanks again I started reading the openGL link, didn't finished it because I wanted to test with code after reading about the rotation matrix, and it works. I'll go back finish reading since I need a better grasp on this, meanwhile, below the code and gif of the thing working

Ignore the fact I am re-calculating the shape point at every draw even though those won't change, I just needed to see it all together in a single page.

void Matrix2DClient::Update(float dt)
{
mHandle->update();
}

void Matrix2DClient::Draw()
{
mRenderTarget->Clear(D2D1::ColorF(0.34f, 0.36f, 0.4f, 1.0f));
makeGrid(100, 45.f);

mHandle->draw();

float angle = mHandle->getHandleAngle();//angle in degree

D2D1_POINT_2F basisX = { cos(rad(angle)), sin(rad(-angle)) }; //for angle == 0°,  (1,0)
{
float displayLenght = 100;
//draw basisX
mBrush->SetColor(D2D1::ColorF(0.86f, 0.1f, 0.2f, 1.f));
float basisXnewX = mOriginX + basisX.x * displayLenght; //draw axis at origin
float basisXnewY = mOriginY + basisX.y * displayLenght; //draw axis at origin
mRenderTarget->DrawLine(D2D1::Point2F(mOriginX, mOriginY),
D2D1::Point2F(basisXnewX, basisXnewY), mBrush, 2.f);
mRenderTarget->DrawTextW(L"x", 1, mTextFormat, D2D1::RectF(basisXnewX, basisXnewY, 1000, 1000), mBrush);

//draw basisY
mBrush->SetColor(D2D1::ColorF(0.1f, 0.86f, 0.2f, 1.f));
float basisYnewX = mOriginX + -basisY.x * displayLenght; //draw axis at origin
float basisYnewY = mOriginY + -basisY.y * displayLenght; //draw axis at origin
mRenderTarget->DrawLine(D2D1::Point2F(mOriginX, mOriginY),
D2D1::Point2F(basisYnewX, basisYnewY), mBrush, 2.f);
mRenderTarget->DrawTextW(L"y", 1, mTextFormat, D2D1::RectF(basisYnewX, basisYnewY, 1000, 1000), mBrush);
}

//star image points
const unsigned points = 5;
float r = 100.f;
D2D1_POINT_2F linePoint[points] = {
};
//offset
float offsetX = 200;
float offsetY = 20;
for (auto& p : linePoint)
{
p.x += offsetX;
p.y -= offsetY;
}

//rotation matrix|  3rd column is for translate the points to the origin (center of screen)
//columns-> |   1   | |   2   |  |   3   |
float R[3][3] = /*row1*/{ basisX.x, basisY.x, mOriginX ,

/*row2*/  basisX.y, basisY.y, mOriginY ,

/*row3*/	 0    ,     0   ,       1
};

//for every point, apply rotation matrix
for (size_t i = 0; i < points; i++)
{
D2D1_POINT_2F newPoint = D2D1::Point2F(
R[0][0] * linePoint[i].x + R[0][1] * linePoint[i].y + R[0][2] * 1,//X
R[1][0] * linePoint[i].x + R[1][1] * linePoint[i].y + R[1][2] * 1 //Y
);
linePoint[i] = newPoint;
}

//draw line
mBrush->SetColor(D2D1::ColorF(0.87f, 0.3f, 0.36f, 1.f));
for (size_t i = 0; i < points; i++)
{
if (i == points - 1) {//connect last point with first
mRenderTarget->DrawLine(linePoint[i], linePoint[0], mBrush, 2.f);
} else {
mRenderTarget->DrawLine(linePoint[i], linePoint[i + 1], mBrush, 2.f);
}

}

}

Edited by MarcusAseth

##### Share on other sites

I've took it a step further, added the third dimension using direct2D, feels like cheating

I was so focused on having it work trough trials and errors that the code became real ugly, so I'll refrain from pasting that

I guess now is only a matter of deleting the code and do it again, until I can do all the steps without any mistakes

Edited by MarcusAseth

##### Share on other sites

Experiments went too far, the cube took life and seems threatening, I'll call it the "slimy dancing cube of spite" and proceed to abort experiments. It looks fun and I thought was worth sharing

Also the bad random code for it in the spoiler, in case someone need a slimy dancing cube

image:

Spoiler

Matrix2DClient::Matrix2DClient(HINSTANCE instance, std::wstring caption, float clientWidth, float clientHeight)
:D2DApp(instance, caption, clientWidth, clientHeight), mOriginX{ 0 }, mOriginY{ 0 }
{
std::array<std::array<float, 3>, 9> tempCubePoint = {
-70.82,   -112.90,   -40.75,//0
-0.34 ,   -170.82,      0.2,//1
0.11,   -112.90,    81.71,//2
-70.59,    -54.97,    40.75,//3
0.34,      2.38,     -0.2,//4
0.11,    -55.54,   -81.71,//5
70.59,   -113.46,   -40.75,//6
70.82,    -55.54,    40.75, //7
1,1,1
};

cubePoint = tempCubePoint;
//cubes is an array of 250 cubes
for (auto& c : cubes) { c = tempCubePoint; }
}

void Matrix2DClient::Draw()
{
static D2D1_COLOR_F clearColor = D2D1::ColorF(0.34f, 0.39f, 0.4f, 1.0f);
mRenderTarget->Clear(clearColor);
makeGrid(100, 45.f);

static float constRotation;
constRotation += constRotation + 1.7 < 360 ? 1.7 : -constRotation;

float RX[3][3] = { 1     ,      0     ,     0     ,

};

0      ,             1     ,           0            ,

};

0        ,         0       ,  1
};

for (size_t c = 0; c < cubes.size(); c++)
{
std::array<std::array<float, 3>, 3> finalMatrix = mBasisVectors;
std::array<std::array<float, 3>, 3> intermediateMatrix1 = mBasisVectors;
std::array<std::array<float, 3>, 3> intermediateMatrix2 = mBasisVectors;

//rotate on axis X  (basisVectors x RotationX) = intermediateMatrix1
for (size_t i = 0; i < 3; i++)
{
for (size_t j = 0; j < 3; j++)
{
float sum = 0;
for (size_t k = 0; k < 3; k++)
{
sum += mBasisVectors[i][k] * RX[k][j];
}
intermediateMatrix1[i][j] = sum;
}
}

static float size = 0.02f;
static int sign = 1;
if (c == 0)
{
float increase = 0.0012f;
if (size + increase*sign > 0.02f || size + increase*sign < 0.01f) { sign *= -1; }
size += increase*sign;
}

intermediateMatrix1[0][0] = intermediateMatrix1[0][0] * size*(((c + 1))/2);
intermediateMatrix1[1][1] = intermediateMatrix1[1][1] * size*(((c + 1))/2);
intermediateMatrix1[2][2] = intermediateMatrix1[2][2] * size*(((c + 1))/2);

//rotate on axis Y (intermediateMatrix1 x RotationY) = intermediateMatrix2
for (size_t i = 0; i < 3; i++)
{
for (size_t j = 0; j < 3; j++)
{
float sum = 0;
for (size_t k = 0; k < 3; k++)
{
sum += intermediateMatrix1[i][k] * RY[k][j];
}
intermediateMatrix2[i][j] = sum;
}
}

//rotate on axis Z (intermediateMatrix2 x RotationZ) = finalMatrix
for (size_t i = 0; i < 3; i++)
{
for (size_t j = 0; j < 3; j++)
{
float sum = 0;
for (size_t k = 0; k < 3; k++)
{
sum += intermediateMatrix2[i][k] * RZ[k][j];
}
finalMatrix[i][j] = sum;
}
}
//for every point, apply the rotation finalMatrix

for (size_t i = 0; i < cubePoint.size(); i++)
{
cubes[c][i][0] = cubePoint[i][0] * finalMatrix[0][0] + cubePoint[i][1] * finalMatrix[0][1] + cubePoint[i][2] * finalMatrix[0][2];//X
cubes[c][i][1] = cubePoint[i][0] * finalMatrix[1][0] + cubePoint[i][1] * finalMatrix[1][1] + cubePoint[i][2] * finalMatrix[1][2];//Y
cubes[c][i][2] = cubePoint[i][0] * finalMatrix[2][0] + cubePoint[i][1] * finalMatrix[2][1] + cubePoint[i][2] * finalMatrix[2][2];//Z
cubes[c][8][0] = abs(size*(c / 2)); //color
cubes[c][8][1] = abs(size*(c / 2)); //color
cubes[c][8][2] = abs(size*(c / 2)); //color
}
}

//draw cube
for (size_t c = 0; c < cubes.size(); c++)
{
float strokeSize = 2.f;
mRenderTarget->DrawLine(D2D1::Point2F(mOriginX + cubes[c][0][0], mOriginY + cubes[c][0][1]), D2D1::Point2F(mOriginX + cubes[c][1][0], mOriginY + cubes[c][1][1]), mBrush, strokeSize);
mRenderTarget->DrawLine(D2D1::Point2F(mOriginX + cubes[c][1][0], mOriginY + cubes[c][1][1]), D2D1::Point2F(mOriginX + cubes[c][6][0], mOriginY + cubes[c][6][1]), mBrush, strokeSize);
mRenderTarget->DrawLine(D2D1::Point2F(mOriginX + cubes[c][6][0], mOriginY + cubes[c][6][1]), D2D1::Point2F(mOriginX + cubes[c][5][0], mOriginY + cubes[c][5][1]), mBrush, strokeSize);
mRenderTarget->DrawLine(D2D1::Point2F(mOriginX + cubes[c][5][0], mOriginY + cubes[c][5][1]), D2D1::Point2F(mOriginX + cubes[c][0][0], mOriginY + cubes[c][0][1]), mBrush, strokeSize);
mRenderTarget->DrawLine(D2D1::Point2F(mOriginX + cubes[c][1][0], mOriginY + cubes[c][1][1]), D2D1::Point2F(mOriginX + cubes[c][2][0], mOriginY + cubes[c][2][1]), mBrush, strokeSize);
mRenderTarget->DrawLine(D2D1::Point2F(mOriginX + cubes[c][6][0], mOriginY + cubes[c][6][1]), D2D1::Point2F(mOriginX + cubes[c][7][0], mOriginY + cubes[c][7][1]), mBrush, strokeSize);
mRenderTarget->DrawLine(D2D1::Point2F(mOriginX + cubes[c][5][0], mOriginY + cubes[c][5][1]), D2D1::Point2F(mOriginX + cubes[c][4][0], mOriginY + cubes[c][4][1]), mBrush, strokeSize);
mRenderTarget->DrawLine(D2D1::Point2F(mOriginX + cubes[c][0][0], mOriginY + cubes[c][0][1]), D2D1::Point2F(mOriginX + cubes[c][3][0], mOriginY + cubes[c][3][1]), mBrush, strokeSize);
mRenderTarget->DrawLine(D2D1::Point2F(mOriginX + cubes[c][3][0], mOriginY + cubes[c][3][1]), D2D1::Point2F(mOriginX + cubes[c][2][0], mOriginY + cubes[c][2][1]), mBrush, strokeSize);
mRenderTarget->DrawLine(D2D1::Point2F(mOriginX + cubes[c][2][0], mOriginY + cubes[c][2][1]), D2D1::Point2F(mOriginX + cubes[c][7][0], mOriginY + cubes[c][7][1]), mBrush, strokeSize);
mRenderTarget->DrawLine(D2D1::Point2F(mOriginX + cubes[c][7][0], mOriginY + cubes[c][7][1]), D2D1::Point2F(mOriginX + cubes[c][4][0], mOriginY + cubes[c][4][1]), mBrush, strokeSize);
mRenderTarget->DrawLine(D2D1::Point2F(mOriginX + cubes[c][4][0], mOriginY + cubes[c][4][1]), D2D1::Point2F(mOriginX + cubes[c][3][0], mOriginY + cubes[c][3][1]), mBrush, strokeSize);
}
}

Edited by MarcusAseth

##### Share on other sites

that's pretty cool

1. 1
2. 2
Rutin
16
3. 3
4. 4
5. 5

• 26
• 11
• 9
• 9
• 11
• ### Forum Statistics

• Total Topics
633702
• Total Posts
3013450
×