Hey guys I have come up with a solution for the problem I have but I would like to know how I could do this the way I initially had it set up but without the leak of course.

vec3f.h

``````class vec3f
{
public:
GLfloat _x, _y, _z;

vec3f(){};

vec3f( GLfloat x, GLfloat y, GLfloat z )
{
_x = x;
_y = y;
_z = z;
}

*operator GLfloat()
{
GLfloat *_r = new GLfloat[3]; //the problem
_r[0] = _x;
_r[1] = _y;
_r[2] = _z;
return _r;
}
}``````

Now I know I am calling the new operator without calling the delete operator but if I put in a deconstructor that frees _r (when declared as part of the class) it crashes because it is pointing to something that was freed.

Anyways I am trying to use this in the OpenGL function `glVertex3fv( const GLfloat *v )` .

I don't know if there is an operator that will do exactly what I want since I do not know all of them.

Any help would be great. Thanks.

4
Contributors
9
Replies
10
Views
7 Years
Discussion Span
Last Post by mike_2000_17

You might be able to do this with smart pointers. But then again, its probably better
to just use glVertex3f(...);

Yeah currently I just use this macro but I have to do it for glNormal and glColor

``#define sfVertex3fv(x) glVertex3f(x._x, x._y, x._z)``

``````class vec3f
{
private:
GLfloat q[3];
public:
GLfloat& x() { return q[0]; };
GLfloat& y() { return q[1]; };
GLfloat& z() { return q[2]; };

vec3f(){};

vec3f( GLfloat x, GLfloat y, GLfloat z )
{
q[0] = x;
q[1] = y;
q[2] = z;
}

*operator GLfloat()
{
return q;
}
}``````

For vector/array arithmatic, you should use SIMD (single instruction multiple data) to boost efficiency, for float, 4 times faster, for double, 2 times faster. Here's my library for vector algebra,

``````#ifndef	__VECTOR_H
#define	__VECTOR_H

#include "math.h"

#ifndef	__FLOAT_MIN_DIFF
#define	__FLOAT_MIN_DIFF	0.000003f
#endif

#ifndef	__DOUBLE_MIN_DIFF
#define	__DOUBLE_MIN_DIFF	0.000000000009
#endif

class	Vector3f;
class	Vector4f;

class Vector3f{
public:
float		val[3];
bool		operator	==	(Vector3f&);		//exact comparison (vector)
bool		operator	==	(float);			//inexact comparison (magnitude)
bool		operator	<	(Vector3f&);		//exact comparison (magnitude)
bool		operator	>	(Vector3f&);		//exact comparison (magnitude)
bool		operator	!=	(Vector3f&);		//inexact comparison (vector)
bool		operator	<<	(Vector3f&);		//inexact comparison (magnitude)
bool		operator	>>	(Vector3f&);		//inexact comparison (magnitude)
Vector3f&	operator	=	(Vector3f&);
Vector3f&	operator	<<=	(float);			//normalize vector
float	&	operator	>>=	(float&);			//calculate magnitude
Vector3f&	operator	+=	(Vector3f&);
Vector3f&	operator	-=	(Vector3f&);
Vector3f&	operator	^=	(Vector3f&);
Vector3f&	operator	*=	(float);			//constant product
Vector3f&	operator	/=	(float);			//constant product
Vector3f	operator	+	(Vector3f&);
Vector3f	operator	-	(Vector3f&);
Vector3f	operator	^	(Vector3f&);		//cross product
Vector3f	operator	*	(float);			//constant product
Vector3f	operator	/	(float);			//constant product
float		operator	*	(Vector3f&);		//dot product
Vector3f(){}
Vector3f(float x,float y,float z){
val[0] = x;
val[1] = y;
val[2] = z;
}
Vector3f(float*p){
memcpy(val,p,sizeof(Vector3f));
}
};
bool	Vector3f::operator == (Vector3f& _rhs){
return	memcmp(this,&_rhs,sizeof(float)*3)==0;
}
bool	Vector3f::operator == (float _rhs){
float	norm;
*this >>= norm;
return	fabsf(norm-_rhs) < __FLOAT_MIN_DIFF;
}
bool	Vector3f::operator < (Vector3f& _rhs){
float	lhs, rhs;
*this >>= lhs;
_rhs  >>= rhs;
return	lhs<rhs;
}
bool	Vector3f::operator > (Vector3f& _rhs){
float	lhs, rhs;
*this >>= lhs;
_rhs  >>= rhs;
return	lhs>rhs;
}
bool	Vector3f::operator << (Vector3f& _rhs){
float	lhs, rhs;
*this >>= lhs;
_rhs  >>= rhs;
return	(rhs-lhs)>__FLOAT_MIN_DIFF;
}
bool	Vector3f::operator >> (Vector3f& _rhs){
float	lhs, rhs;
*this >>= lhs;
_rhs  >>= rhs;
return	(lhs-rhs)>__FLOAT_MIN_DIFF;
}
bool	Vector3f::operator != (Vector3f& _rhs){
if(fabsf(this->val[0]-_rhs.val[0]) > __FLOAT_MIN_DIFF)return true;
if(fabsf(this->val[1]-_rhs.val[1]) > __FLOAT_MIN_DIFF)return true;
if(fabsf(this->val[2]-_rhs.val[2]) > __FLOAT_MIN_DIFF)return true;
return	false;
}
Vector3f& Vector3f::operator = (Vector3f& _rhs){
memcpy(this,&_rhs,sizeof(Vector3f));
return	*this;
}
Vector3f& Vector3f::operator <<= (float _rhs){
float	_mag;
*this >>= _mag;
_mag /=	_rhs;
*this /= _mag;
return	*this;
}
float& Vector3f::operator >>= (float& _rhs){
float	_res[4];
#ifdef SIMD
__asm{
mov		eax,	this
movups	xmm0,	[eax]
movaps	xmm1,	xmm0
mulps	xmm0,	xmm1
movups	_res,	xmm0
}
#else
_res[0] = this->val[0]*this->val[0];
_res[1] = this->val[1]*this->val[1];
_res[2] = this->val[2]*this->val[2];
#endif
_rhs = sqrtf(_res[0]+_res[1]+_res[2]);
return	_rhs;
}
Vector3f& Vector3f::operator +=	(Vector3f& _rhs){
#ifdef SIMD
__asm{
mov		eax,	this
mov		ebx,	_rhs
movups	xmm0,	[eax]
movups	xmm1,	[ebx]
movlps	[eax],	xmm0
movhlps	xmm0,	xmm0
movss	[eax+8],xmm0
}
#else
this->val[0] += _rhs.val[0];
this->val[1] += _rhs.val[1];
this->val[2] += _rhs.val[2];
#endif
return	*this;
}
Vector3f& Vector3f::operator -=	(Vector3f& _rhs){
#ifdef SIMD
__asm{
mov		eax,	this
mov		ebx,	_rhs
movups	xmm0,	[eax]
movups	xmm1,	[ebx]
subps	xmm0,	xmm1
movlps	[eax],	xmm0
movhlps	xmm0,	xmm0
movss	[eax+8],xmm0
}
#else
this->val[0] -= _rhs.val[0];
this->val[1] -= _rhs.val[1];
this->val[2] -= _rhs.val[2];
#endif
return	*this;
}
Vector3f& Vector3f::operator *=	(float _rhs){
#ifdef SIMD
__asm{
movss	xmm1,	_rhs
mov		eax,	this
unpcklps	xmm1,	xmm1
movups	xmm0,	[eax]
movlhps	xmm1,	xmm1
mulps	xmm0,	xmm1
movlps	[eax],	xmm0
movhlps	xmm0,	xmm0
movss	[eax+8],xmm0
}
#else
this->val[0] *= _rhs;
this->val[1] *= _rhs;
this->val[2] *= _rhs;
#endif
return	*this;
}
Vector3f& Vector3f::operator /=	(float _rhs){
#ifdef SIMD
__asm{
movss	xmm1,	_rhs
mov		eax,	this
unpcklps	xmm1,	xmm1
movups	xmm0,	[eax]
movlhps	xmm1,	xmm1
divps	xmm0,	xmm1
movlps	[eax],	xmm0
movhlps	xmm0,	xmm0
movss	[eax+8],xmm0
}
#else
this->val[0] *= _rhs;
this->val[1] *= _rhs;
this->val[2] *= _rhs;
#endif
return	*this;
}
Vector3f& Vector3f::operator ^=	(Vector3f& _rhs){
#ifdef SIMD
__asm{
mov		ebx,	[_rhs]
mov		eax,	[this]
movups	xmm3,	[ebx]
movups	xmm0,	[eax]
movaps	xmm1,	xmm3
movaps	xmm2,	xmm0
psrldq	xmm1,	4
psrldq	xmm2,	4
movhps	xmm1,	[ebx]
movhps	xmm2,	[eax]
mulps	xmm0,	xmm1
mulps	xmm2,	xmm3
subps	xmm0,	xmm2
movss	[eax+8],xmm0
psrldq	xmm0,	4
movlps	[eax],	xmm0
}
#else
Vector3f _tmp = *this;
this->val[0] = _tmp.val[1]*_rhs.val[2]-_tmp.val[2]*_rhs.val[1];
this->val[1] = _tmp.val[2]*_rhs.val[0]-_tmp.val[0]*_rhs.val[2];
this->val[2] = _tmp.val[0]*_rhs.val[1]-_tmp.val[1]*_rhs.val[0];
#endif
return	*this;
}
Vector3f Vector3f::operator + (Vector3f& _rhs){
Vector3f	_sum;
#ifdef SIMD
__asm{
mov		eax,	this
mov		ebx,	_rhs
movups	xmm0,	[eax]
movups	xmm1,	[ebx]
movups	[_sum],	xmm0
}
#else
_sum = *this;
_sum.val[0] += _rhs.val[0];
_sum.val[1] += _rhs.val[1];
_sum.val[2] += _rhs.val[2];
#endif
return	_sum;
}
Vector3f Vector3f::operator - (Vector3f& _rhs){
Vector3f	_sum;
#ifdef SIMD
__asm{
mov		eax,	this
mov		ebx,	_rhs
movups	xmm0,	[eax]
movups	xmm1,	[ebx]
subps	xmm0,	xmm1
movups	[_sum],	xmm0
}
#else
_sum = *this;
_sum.val[0] -= _rhs.val[0];
_sum.val[1] -= _rhs.val[1];
_sum.val[2] -= _rhs.val[2];
#endif
return	_sum;
}
Vector3f Vector3f::operator ^ (Vector3f& _rhs){
Vector3f _sum;
#ifdef SIMD
__asm{
mov		ebx,	[_rhs]
mov		eax,	[this]
movups	xmm3,	[ebx]
movups	xmm0,	[eax]
movaps	xmm1,	xmm3
movaps	xmm2,	xmm0
psrldq	xmm1,	4
psrldq	xmm2,	4
movhps	xmm1,	[ebx]
movhps	xmm2,	[eax]
mulps	xmm0,	xmm1
mulps	xmm2,	xmm3
subps	xmm0,	xmm2
movss	[_sum+8],xmm0
psrldq	xmm0,	4
movlps	[_sum],	xmm0
}
#else
_sum.val[0] = this->val[1]*_rhs.val[2]-this->val[2]*_rhs.val[1];
_sum.val[1] = this->val[2]*_rhs.val[0]-this->val[0]*_rhs.val[2];
_sum.val[2] = this->val[0]*_rhs.val[1]-this->val[1]*_rhs.val[0];
#endif
return	_sum;
}
Vector3f Vector3f::operator * (float _rhs){
Vector3f	_sum;
#ifdef SIMD
__asm{
movss	xmm1,	_rhs
mov		eax,	this
unpcklps	xmm1,	xmm1
movups	xmm0,	[eax]
movlhps	xmm1,	xmm1
mulps	xmm0,	xmm1
movups	[_sum],	xmm0
}
#else
_sum.val[0] = this->val[0]*_rhs;
_sum.val[1] = this->val[1]*_rhs;
_sum.val[2] = this->val[2]*_rhs;
#endif
return	_sum;
}
Vector3f Vector3f::operator / (float _rhs){
Vector3f	_sum;
#ifdef SIMD
__asm{
movss	xmm1,	_rhs
mov		eax,	this
unpcklps	xmm1,	xmm1
movups	xmm0,	[eax]
movlhps	xmm1,	xmm1
divps	xmm0,	xmm1
movups	[_sum],	xmm0
}
#else
_sum.val[0] = this->val[0]/_rhs;
_sum.val[1] = this->val[1]/_rhs;
_sum.val[2] = this->val[2]/_rhs;
#endif
return	_sum;
}
float Vector3f::operator * (Vector3f& _rhs){
#ifdef SIMD
float	res[4];
__asm{
mov		eax,	[this]
mov		ebx,	[_rhs]
movups	xmm0,	[eax]
movups	xmm1,	[ebx]
mulps	xmm0,	xmm1
movups	[res],	xmm0
}
return	res[0]+res[1]+res[2];
#else
return	 (this->val[0] * _rhs.val[0])
+(this->val[1] * _rhs.val[1])
+(this->val[2] * _rhs.val[2]);
#endif
}

/*
//For 4-Vectors
class Vector4f{
public:
float val[4];
operator	<<=		(Vector4f&);
operator	>>=		(Vector4f&);
bool		operator == (Vector3f&);
Vector3f	&		operator =	(Vector4f&);
Vector3f	&		operator += (Vector4f&);
Vector3f	&		operator -= (Vector4f&);
Vector3f	&		operator ^= (Vector4f&);
Vector3f	&		operator *= (float&);
Vector3f	&		operator /= (float&);
Vector3f	operator + (Vector4f&);
Vector3f	operator - (Vector4f&);
Vector3f	operator ^ (Vector4f&);		//cross product
Vector3f	operator * (float);			//constant product
Vector3f	operator / (float);			//constant product
float		operator * (Vector4f&);		//dot product
};
Vector3f::operator	<<=	(Vector4f& _rhs){
memcpy(this,&_rhs,sizeof(float)*4);
}
bool	Vector3f::operator == (Vector4f& _rhs){
return memcmp(this,&_rhs,sizeof(float)*4)==0;
}
Vector4f& Vector4f::operator =	(Vector4f& _rhs){
#ifdef SIMD
__asm{
mov		eax,	_rhs
movups	xmm0,	[eax]
mov		eax,	this
movups	[eax],	xmm0
}
#else
if(this == &_rhs)return *this;
memcpy(this,&_rhs,sizeof(Vector4f));
#endif
return	*this;
}
Vector4f& Vector4f::operator +=	(Vector4f& _rhs){
#ifdef SIMD
__asm{
mov		eax,	_rhs
movups	xmm1,	[eax]
mov		eax,	this
movups	xmm0,	[eax]
movups	[eax],	xmm0
}
#else
this->val[0] += _rhs.val[0];
this->val[1] += _rhs.val[1];
this->val[2] += _rhs.val[2];
#endif
return	*this;
}
Vector4f& Vector4f::operator -=	(Vector4f& _rhs){
#ifdef SIMD
__asm{
mov		eax,	_rhs
movups	xmm1,	[eax]
mov		eax,	this
movups	xmm0,	[eax]
subps	xmm0,	xmm1
movups	[eax],	xmm0
}
#else
this->val[0] -= _rhs.val[0];
this->val[1] -= _rhs.val[1];
this->val[2] -= _rhs.val[2];
#endif
return	*this;
}
Vector4f& Vector4f::operator *=	(float& _rhs){
this->val[0] *= _rhs;
this->val[1] *= _rhs;
this->val[2] *= _rhs;
return	*this;
}
Vector4f& Vector4f::operator /=	(float& _rhs){
this->val[0] /= _rhs;
this->val[1] /= _rhs;
this->val[2] /= _rhs;
return	*this;
}
Vector4f& Vector4f::operator ^=	(Vector4f& _rhs){
#ifdef SIMD
__asm{
mov		ebx,	[_rhs]
mov		eax,	[this]
movups	xmm4,	[ebx]
movups	xmm0,	[eax]
movaps	xmm1,	xmm4
movaps	xmm2,	xmm0
psrldq	xmm1,	4
psrldq	xmm2,	4
movhps	xmm1,	[ebx]
movhps	xmm2,	[eax]
mulps	xmm0,	xmm1
mulps	xmm2,	xmm4
subps	xmm0,	xmm2
movss	[eax+8],xmm0
psrldq	xmm0,	4
movlps	[eax],	xmm0
}
#else
Vector4f _tmp = *this;
this->val[0] = _tmp.val[1]*_rhs.val[2]-_tmp.val[2]*_rhs.val[1];
this->val[1] = _tmp.val[2]*_rhs.val[0]-_tmp.val[0]*_rhs.val[2];
this->val[2] = _tmp.val[0]*_rhs.val[1]-_tmp.val[1]*_rhs.val[0];
#endif
return	*this;
}
Vector4f Vector4f::operator + (Vector4f& _rhs){
Vector4f _sum = *this;
#ifdef SIMD
__asm{
mov		eax,	_rhs
movups	xmm1,	[eax]
movups	xmm0,	[_sum]
movups	[_sum],	xmm0
}
#else
_sum.val[0] += _rhs.val[0];
_sum.val[1] += _rhs.val[1];
_sum.val[2] += _rhs.val[2];
#endif
return	_sum;
}
Vector4f Vector4f::operator - (Vector4f& _rhs){
Vector4f _sum = *this;
#ifdef SIMD
__asm{
mov		eax,	_rhs
movups	xmm1,	[eax]
movups	xmm0,	[_sum]
subps	xmm0,	xmm1
movups	[_sum],	xmm0
}
#else
_sum.val[0] -= _rhs.val[0];
_sum.val[1] -= _rhs.val[1];
_sum.val[2] -= _rhs.val[2];
#endif
return	_sum;
}
Vector4f Vector4f::operator ^ (Vector4f& _rhs){
Vector4f _sum;
#ifdef SIMD
__asm{
mov		ebx,	[_rhs]
mov		eax,	[this]
movups	xmm4,	[ebx]
movups	xmm0,	[eax]
movaps	xmm1,	xmm4
movaps	xmm2,	xmm0
psrldq	xmm1,	4
psrldq	xmm2,	4
movhps	xmm1,	[ebx]
movhps	xmm2,	[eax]
mulps	xmm0,	xmm1
mulps	xmm2,	xmm4
subps	xmm0,	xmm2
movss	[_sum+8],xmm0
psrldq	xmm0,	4
movlps	[_sum],	xmm0
}
#else
_sum.val[0] = this->val[1]*_rhs.val[2]-this->val[2]*_rhs.val[1];
_sum.val[1] = this->val[2]*_rhs.val[0]-this->val[0]*_rhs.val[2];
_sum.val[2] = this->val[0]*_rhs.val[1]-this->val[1]*_rhs.val[0];
#endif
return	_sum;
}
Vector4f Vector4f::operator * (float _rhs){
Vector4f _sum;
_sum.val[0] = this->val[0]*_rhs;
_sum.val[1] = this->val[1]*_rhs;
_sum.val[2] = this->val[2]*_rhs;
return	_sum;
}
Vector4f Vector4f::operator / (float _rhs){
Vector4f _sum;
_sum.val[0] = this->val[0]/_rhs;
_sum.val[1] = this->val[1]/_rhs;
_sum.val[2] = this->val[2]/_rhs;
return	_sum;
}
float Vector4f::operator * (Vector4f& _rhs){
#ifdef SIMD
__asm{
mov		eax,	[_rhs]
movups	xmm1,	[eax]
mov		eax,	[this]
movups	xmm0,	[eax]
mulps	xmm0,	xmm1
movups	[eax],	xmm0
}
return	this->val[0]+this->val[1]+this->val[2];
#else
return	 (this->val[0] * _rhs.val[0])
+(this->val[1] * _rhs.val[1])
+(this->val[2] * _rhs.val[2]);
#endif
}
*/
#endif``````

Remember to define SIMD in order to enable SIMD instruction set. This code only works for Visual C++, for linux compiler, you need to convert assembly instructions to AT&T syntax.

Xuancong

Edited by xuancong: n/a

I would not particularly recommend the code Xuancong posted. First, the operator semantics are quite confusing and I doubt that the operator priorities make sense. When overloading operators, only overload the operators for which the semantics are kept (i.e. + always means an addition, - a subtraction, etc.), operators like >>= for the magnitude is just weird and will confuse people. Operator overloading is syntaxic sugar, nothing more, if it isn't obvious what the operator does than don't overload it.

Second, I'm not much of an expert, but I think all the asm code in there is probably not any better than what the compiler will produce with proper optimization flags (like SSE2 optimizations), it's not worth the trouble for you sfuo at this point, if even it improves performance at all.

I mean you should only extract the portion doing vector addition and delete the rest which are irrelavant. Btw, compiler SSE optimization will not optimize in this way and it will never be faster than this code (although this code can be made even faster by us), compiler optimization can only optimize certain lumped operations. If you don't believe me, you can simply compile with full optimization and view the disassembly.

I have to agree, your operator overloading is rather superfluous and rather confusing.
For example you would know what this mean :

``````Vector3f pos = Vector3f(-1,0,1);
Vector3f view = Vector3f(0,1,1);
float d = pos^view*pos;``````

But if I was just looking at this code without the full understanding of your
Vector3f interface, then I would be confused, and would have to come and hunt you
down to kill you. Plus do you want the '^' to go first, or did you mean '*' to go first? Of course you might be able to determine by the type of 'd' variable. But imagine if this was a more complicate expression.

For most of Vector operations, I suggest you just write a normal function like so
code like the one below is easy to understand :

``````Vector3f pos = Vector3f(-1,0,1);
Vector3f view = Vector3f(0,1,1);
float d =  (pos.cross( view )).dot( view );``````

And lastly, You would definitely make me hunt you down, if I seen your code using
SIMD.

I use Code::Blocks so according to you this wouldn't work and also your vector class does not even have the operator that I am looking for.

I want to be able to type

``````vec3f sean(1.0, 1.0, 1.0);
glVector3fv(sean);``````

So the vec3f class needs to return a const GLfloat* without leaking memory (because I already got that far).

Mike I tried what you posted and it didn't work.

xuangcong thanks for posting what you got but sorry that is not what I am looking for.

Oh, you mis-wrote the conversion operator, it should be:

``````class vec3f
{
private:
GLfloat q[3];
public:
GLfloat& x() { return q[0]; };
GLfloat& y() { return q[1]; };
GLfloat& z() { return q[2]; };

vec3f(){};

vec3f( GLfloat x, GLfloat y, GLfloat z )
{
q[0] = x;
q[1] = y;
q[2] = z;
}

operator GLfloat *()
{
return q;
}
}``````

That has to work, it is too simple to not work.

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.