I am reading through the 8th edition of the OpenGL Programming Guide by Shreiner Sellers Kessenich and Licea-Kane, and I keep seeing this "vmath" library being used for vector and matrices work.
I did a google search for vmath.h, but wasn't able to find anything. I did a search on stackoverflow and found one question where it has been used but nothing more.
My question is where or how can I install it or download it. I assumed it was something which came along with freeglut or whatever other opengl stuff I installed with "apt-get install", but apparently not since g++ can't find vmath.h.
Any ideas on how to get it installed?
#Blastfurnace provides the correct address to download. But I still have something to say.
Please use glm instead of vmath.h: http://glm.g-truc.net/0.9.5/index.html
I used vmath.h and found tons of bugs. Some definitions of operator causes recursive function call and stack overflows. Also the conversion between radius and degree is inverted.
line 11:
template <typename T>
inline T radians(T angleInRadians)
{
return angleInRadians * static_cast<T>(180.0/M_PI);
}
line 631:
static inline mat4 perspective(float fovy /* in degrees */, float aspect, float n, float f)
{
float top = n * tan(radians(0.5f*fovy)); // bottom = -top
float right = top * aspect; // left = -right
return frustum(-right, right, -top, top, n, f);
}
Obviously the tangent function accepts a radian input, but the function 'radian' converts the radian to degree instead.
line 137:
inline vecN& operator/=(const vecN& that)
{
assign(*this * that);
return *this;
}
It should be a division instead of a multiplication: assign(*this / that).
line 153:
inline vecN& operator/(const T& that)
{
assign(*this / that);
}
See? Recursive call of operator '/'. At least in Xcode this causes a stack overflow.
These bugs annoy me a lot, while glm library provides almost the same functions but much more stable code. I STRONGLY RECOMMEND you using glm instead of the current buggy vmath.h. Maybe when all these bugs are fixed, a simple vmath.h would be a better choice, while you need to give up at the moment.
The web site for the book can be found at The OpenGL Programming Guide. That page has a link to a .zip file with most of the code from the book. The vmath.h file is in the include directory.
Related
I have been writing TensorFlow custom op and hence am dealing with some matrix operations using Eigen library. I am trying to understand how Eigen library executes the operations. I have the below code:
void __attribute__((optimize("O0"))) quantizeDequantize(const GPUDevice& d, TTypes<float>::ConstMatrix inputs,
float delta, float offset, float minVal, float maxVal,
TTypes<float>::Matrix outputs, int channel)
{
float invScale = 1.0f / ((float)delta);
const auto clampedTensor = inputs.chip<1>(channel).cwiseMax(min).cwiseMin(max);
const auto tensor = (clampedTensor * invScale).round() + offset;
const auto tensor_2 = (tensor - offset) * scale;
outputs.chip<1>(channel).device(d) = clampedTensor; // line taking the most time
}
If I disable the below line, the code is almost 7 times faster when running on a large model when compared to having the line in (I understand output wont be correct).
outputs.chip<1>(channel).device(d) = clampedTensor;
But, if I have following code, the execution time is pretty much close to what I see with all the code in.
void __attribute__((optimize("O0"))) quantizeDequantize(const GPUDevice& d, TTypes<float>::ConstMatrix inputs,
float delta, float offset, float minVal, float maxVal,
TTypes<float>::Matrix outputs, int channel)
{
outputs.chip<1>(channel).device(d) = inputs.chip<1>(channel);
}
The above two experiments are leading me to infer the following,
Eigen backend would not run any operations if we are not using the intermediate results to generate the output. Is it correct?
If above is True, how does Eigen library know the graph. Does it figure these details out at compile time similar to how GCC optimizes the code?
Does adding attribute((optimize("O0"))) make any difference to the way Eigen backend executes the above code?
Eigen seems to have answered these questions here: https://eigen.tuxfamily.org/dox/TopicLazyEvaluation.html
I'm trying to use updated codes of "Frank Luna" book on directX11 where I using VS2017 with WindowsSDK10. I've read some notes about migration from Frank and did eveything he said in the link below :
http://www.d3dcoder.net/Data/Book4/d3d11Win10.htm
but got stuck here . I know there was same question from #poncho and answered well :
Access floats of XMMatrix - () operator not working
But I have trouble with type CXMMATRIX instead of XMMATRIX and I couldn't get result with the solution provided for him.
So I have to access the rows and columns of an CXMMATRIX :
void ExtractFrustumPlanes(XMFLOAT4 planes[6], CXMMATRIX M)
{
//
// Left
//
planes[0].x = M(0,3) + M(0,0);
planes[0].y = M(1,3) + M(1,0);
planes[0].z = M(2,3) + M(2,0);
planes[0].w = M(3,3) + M(3,0);
...
But I get :
call of an object of a class type without appropriate operator() or
conversion functions to pointer-to-function type
and
term does not evaluate to a function taking 2 arguments
It points to argument M of type CXMMATRIX where defined as below in DirectXMath.h :
// Fix-up for (2nd+) XMMATRIX parameters to pass by reference
typedef const XMMATRIX& CXMMATRIX;
What's all these errors about !?
Frank Luna's book is overall a great introduction to the Direct 11 API, but unfortunately suffers from heavily utilizing the legacy DirectX SDK which is deprecated per MSDN. One of those aspects is that he's actually using the xnamath library (a.k.a. xboxmath version 2) instead of the DirectXMath library (a.k.a. xboxmath version 3)
See Book Recommendations and Introducing DirectXMath
I made a number of changes when reworking the library as DirectXMath. First, the types are actually in C++ namespaces instead of the global namespace. In your headers, you should use full name specification:
#include <DirectXMath.h>
void MyFunction(..., DirectX::CXMMATRIX M);
In your cpp source files you should use:
#include <DirectXMath.h>
using namespace DirectX;
Another change was to strongly discourage the use of 'per-element' access on the XMVECTOR and XMMATRIX data types. As discussed in the DirectXMath Programmers Guide, these types are by design proxies for the SIMD register types which cannot be directly accessed by-element. Instead, you covert to the XMFLOAT4X4 representation which allows per-element access because that's a scalar structure.
You can see this by the fact that the operators you are trying to use are only defined for 'no-intrinsics' mode (i.e. when using scalar instead of SIMD operations like SSE, ARM-NEON, etc.):
#ifdef _XM_NO_INTRINSICS_
float operator() (size_t Row, size_t Column) const { return m[Row][Column]; }
float& operator() (size_t Row, size_t Column) { return m[Row][Column]; }
#endif
Again, by design, this process is a bit 'verbose' because it lets you know it's not free. Some people find this aspect of DirectXMath a little frustrating to use especially when they are first getting started. In that case, I recommend you take a look at the SimpleMath wrapper in the DirectX Tool Kit. You can use the types Vector3, Vector4, Matrix, etc. and they freely convert (through C++ operators and constructors) as needed to XMVECTOR and XMMATRIX. It's not nearly as efficient, but it's a lot more forgiving to use.
The particular function you wrote is also a bit problematic. First, it's a little odd to mix XMFLOAT4 and XMMATRIX parameters. For 'in-register, SIMD-friendly' calling convention, you'd use:
void XM_CALLCONV ExtractFrustumPlanes(XMVECTOR planes[6], FXMMATRIX M)
For details on why, see MSDN.
If you want to just entirely scalar math, use either the non-SIMD types:
void ExtractFrustumPlanes(XMFLOAT4 planes[6], const XMFLOAT4X4& M)
or better yet use SimpleMath so you can avoid having to write explicit conversions to/from XMVECTOR or XMMATRIX
using DirectX::SimpleMath;
void ExtractFrustumPlanes(Vector4 planes[6], const Matrix& M)
Note that the latest version of DirectXMath is on GitHub, NuGet, and vcpkg.
I am writing an application that must be very fast. I use Qt 5.5 with Qt Creator, the 64 bit MSVC2013 compiled version of Qt.
I used very sleepy CS to profile my application, and I saw that the function that took the most exclusive time was an operator+= overload (which is called, as you guess, a lot of times).
Here's the piece of code.
struct Coordinate
{
float x;
float y;
Coordinate operator+=(const Coordinate &coord)
{
this->x += coord.x;
this->y += coord.y;
return (*this);
}
};
I wondered if there were a way to improve performance of a function as simple as this one.
operator+= is not quite defined the way you did. Rather, it should be:
Coordinate& operator+=(const Coordinate &coord);
Note the return value of a reference.
This also has the benefit of not creating another copy.
Check if you are profiling Release configurion and compiler optimizations are enabled. Such calls should be inlined by any decent compiler.
I am currently working on my final project for my Cpp class, which involves working with directX11 to create a 2D game. I have been following tutorials from the website rastertek.com (directX 11 series 2), and for the most part it has been going pretty smoothly. However the portion of code on shaders I finished up this morning had some errors right away.
At first it was giving me error C2719 in my colorshaderclass.cpp at lines 44 and 248 with my XMMATRIX values being passed in. After some quick research on the topic I changed those XMMATRIX values being passed in to constant references. I then went into my colorshaderclass.h file and changed the XMMATRIX values on lines 37 and 44 to constant references as necessary.
After doing that I no longer have error C2719 showing up. However now I am getting error C2678 (binary '=': no operator found which takes a left-hand operand of type 'const DirectX::XMMATRIX'), on lines 256, 257, and 258 of my colorshaderclass.cpp file. I've done a bit of research on this error too but it seems to be very situation dependent and I have had no luck with it.
Actually, I should say I think I understand why it is throwing the error (const on one side, a non-constant on the other), but I am stumped on what to do at this point as I had to make parts of the code into constant references to get them to work. I should also mention that I have less than six months of programming experience at this point, so sorry if this seems like an obvious fix or anything. If anybody has any insight or ideas it would be much appreciated.
Cheers!
There are also several other parts to the whole solution I can provide if needed, although none of them were throwing any errors.
The offending code is below (C2678)
worldMatrix = XMMatrixTranspose(worldMatrix);
viewMatrix = XMMatrixTranspose(viewMatrix);
projectionMatrix = XMMatrixTranspose(projectionMatrix);
and the XMMATRIX values I changed to constant references:
bool ColorShaderClass::SetShaderParameters(ID3D11DeviceContext* deviceContext, const XMMATRIX& worldMatrix, const XMMATRIX& viewMatrix, const XMMATRIX& projectionMatrix)
bool ColorShaderClass::Render(ID3D11DeviceContext* deviceContext, int indexCount, const XMMATRIX& worldMatrix, const XMMATRIX& viewMatrix, const XMMATRIX& projectionMatrix)
And what I changed in the header file
bool Render(ID3D11DeviceContext*Int, int, const XMMATRIX&, const XMMATRIX&, const XMMATRIX&);
bool SetShaderParameters(ID3D11DeviceContext*, const XMMATRIX&, const XMMATRIX&, const XMMATRIX&);
It's not clear from your report exactly what all the variable types are. Is your worldMatrix declared as XMFLOAT4X4? Both XMVECTOR and XMMATRIX have alignment requirements, so it is not recommended to use them directly as class/struct variables. If you are following that advice, then you need to use XMStoreFloat4x4 and XMLoadFloat4x4 to convert between XMFLOAT4X4 and XMMATRIX.
So a typical usage would be something like:
class MyClass
{
DirectX::XMFLOAT4X4 m_worldMatrix;
};
// ...
void MyClass::SomeFunction()
{
XMMATRIX worldMatrix = XMLoadFloat4x4( &m_worldMatrix );
// do some stuff with worldMatrix as an ``XMMATRIX``
XMStoreFloat4x4( &m_worldMatrix, worldMatrix );
}
Yes this is verbose, but intentionally. Most of the loss of performance when doing SIMD programming is converting to and from non-aligned and/or scalar types. This pattern encourages the advanced programmer to load the values into 'register proxy' types (XMMATRIX, XMVECTOR) and then do a lot of operations as such before storing them back into scalar or non-aligned types.
If you like the convenience of the C++ operator overloading, then take a look at SimpleMath in the DirectX Tool Kit. It provides some classes that 'wrap' DirectXMath so that it's more intuitive to use. It does have some performance implications, but unless you are really performance sensitive you won't notice. It is also very easy to intermix SimpleMath and DirectXMath types. The above example would be:
class MyClass
{
DirectX::SimpleMath::Matrix m_worldMatrix;
};
// ...
void MyClass::SomeFunction()
{
XMMATRIX worldMatrix = m_worldMatrix;
// do some stuff with worldMatrix as an ``XMMATRIX``
// or just use the methods and operator overloads directly
// of the ``Matrix`` SimpleMath type
m_worldMatrix = worldMatrix;
}
As for your parameter usage, you certainly can use const ref's like you are doing, but you might find it helpful to use the various DirectXMath calling-convention types described on MSDN. For your example, it would end up as:
bool XM_CALLCONV ColorShaderClass::SetShaderParameters(ID3D11DeviceContext* deviceContext, FXMMATRIX worldMatrix, CXMMATRIX viewMatrix, CXMMATRIX projectionMatrix)
This is not strictly necessary, but if you are trying to leverage the various SIMD-friendly calling conventions across x86 __fastcall, x86 __vectorcall, x64 __fastcall, x64 __vectorcall, and ARM these types and the XM_CALLCONV macro can achieve that.
I'm trying to compile old Qt project and i encounter this error:
error: cannot convert 'float*' to 'qreal* {aka double*}' in
initialization
Here's the fragment of code:
void Camera::loadProjectionMatrix()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
qreal *dataMat = projectionMatrix_.data();
GLfloat matriceArray[16];
for (int i= 0; i < 16; ++i)
matriceArray[i] = dataMat[i];
glMultMatrixf(matriceArray);
}
What are my options to overcome this error?
The projection matrix will return float* to you as per documentation:
float * QMatrix4x4::data()
Returns a pointer to the raw data of this matrix.
The best practice would be to eliminate the qreal usage in your codebase regardless this case. When the contributors went through the Qt 5 refactoring, the qreal ancient concept was dropped as much as possible and definitely should not be used much in new code where the API deals with float.
The recommendation is to use float these days in such cases. This is a bit historical, really. Back then, it made sense to define qreal to double where available, but float where not, e.g. ARM platforms. See the old documentation:
typedef qreal
Typedef for double on all platforms except for those using CPUs with ARM architectures. On ARM-based platforms, qreal is a typedef for float for performance reasons.
In Qt 5, the documentation is slightly different, although the main concept seems to have remained the same:
typedef qreal
Typedef for double unless Qt is configured with the -qreal float option.
I would fix your code the following way:
void Camera::loadProjectionMatrix()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float *dataMat = projectionMatrix_.data();
GLfloat matriceArray[16];
for (int i= 0; i < 16; ++i)
matriceArray[i] = dataMat[i];
glMultMatrixf(matriceArray);
}
Strictly speaking, you could also go an alternative way to solve the issue, namely by using this method rather than data():
float & QMatrix4x4::operator()(int row, int column)
Returns a reference to the element at position (row, column) in this matrix so that the element can be assigned to.
In which case, you could even eliminate the dataMat variable and assign the items directly to your matriceArray in the iteration.
Going even further than that, you should consider using a Qt library for this common task, namely e.g. the opengl classes either in QtGui or Qt3D. It would make more sense to mess with low-level opengl API calls if you do something custom.
Apparently, projectionMatrix_.data() returns a float*, and you cannot assign a float* to a double* (which is what qreal* is in this case).
Use
float *dataMat = projectionMatrix_.data();
or
auto dataMat = projectionMatrix_.data();
instead. The latter sometimes has the advantage that it might still be correct code if the return type of the function changes for some reason, although that is nothing to expect from a mature library. Additionally, you cannot get the type wrong on accident.