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.

Recommended Answers

All 9 Replies

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)

What about this:

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]
		addps	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 -=	(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;
	float		_pad;
#ifdef SIMD
	__asm{
		mov		eax,	this
		mov		ebx,	_rhs
		movups	xmm0,	[eax]
		movups	xmm1,	[ebx]
		addps	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;
	float		_pad;
#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;
	float		_pad;
#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;
	float		_pad;
#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]
		addps	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 -=	(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]
		addps	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 = *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

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.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.