array not passing the values it should

Started by
8 comments, last by Zahlman 13 years, 4 months ago
Hi there
I am currently attempting to pass an array from one class to another. I have done this previously with no problem.

I am attempting to pass three arrays One with 3 variables one with 4 variables and another one with 3 variables. Upon debugging the values within the arrays are correct. I am entering an array into Collision::CalculateNormal and then outputting to an array called normal. This function seems to work fine. I have checked on paper and online and the results are correct, with no problems.

float normal[3];	Collision::CalculateNormal(normalArray,normal);	float collisionPoint[] = {boatPoint[0],boatPoint[1],boatPoint[2],boatPoint[3]}; //calculates normals	Collision::NormaliseNormal(normal,collisionPoint,array1); //normalises for lighting and point to plane test


I then use the normal array and pass these values to my other function.
Upon debugging it is only getting 1 input. my array Normal[3] = 600,0,0;
When it passes these values to the Collision::NormaliseNormal(Normal it is only inputing 600. array1[3] is -50,0,-150. When this is passed it only passes - 50 to the function.

I have passed arrays previously including in the function above which work fine. I have never had this problem before and can't work out why it isn't passing the whole array, Is it because the arrays have a 0 value in them? Is it something to do with not using pointers?

The code to the function I am passing to is
float Collision::NormaliseNormal(float normalArray[3],float testPoint[4],float corner[3]){		float lengthX = sqrt((normalArray[0]*normalArray[0]) + (normalArray[1]*normalArray[1]) + (normalArray[2]*normalArray[2]));	float normalX = normalArray[0] /= lengthX;	float normalY = normalArray[1] /= lengthX;	float normalZ = normalArray[2] /= lengthX;	float testX[] = {testPoint[0] - corner[0]};	float testY[] = {testPoint[1] - corner[1]};	float testZ[] = {testPoint[2] - corner[2]};	float sX = (testX[0] - corner[0]); 	float sY = (testY[0] - corner[1]);	float sZ = (testZ[0] - corner[2]);	float distanceX = Collision::DotProduct(sX,normalX,0,0,0,0);	float distanceY = Collision::DotProduct(0,0,sY,normalY,0,0);	float distanceZ = Collision::DotProduct(0,0,0,0,sZ,normalZ);	std::cout<<"DistanceX "<<distanceX<<std::endl;	std::cout<<"DistanceY "<<distanceY<<std::endl;	std::cout<<"DistanceZ "<<distanceZ<<std::endl;	float cx = testPoint[0] - distanceX * normalX;	float cy = testPoint[1] - distanceY * normalY;	float cz = testPoint[2] - distanceZ * normalZ;	std::cout<<"cx is "<<cx<<std::endl;	std::cout<<"cy is "<<cy<<std::endl;	std::cout<<"cz is "<<cz<<std::endl;	//float collisionPoints[] = {cx,cy,cz};	return cx;}


In the main where I tested it worked fine. I am now just testing the variables and outputting them the 1 value it passes seems to calculate fine but the other (as they are not being passed) obviously don't rendering the function useless.

Any help would be appreciated I am truly stumped.

Many thanks
Advertisement
You cant return arrays in C++. However you could instead use a struct and return that instead. Like so

struct Normal
{
float values[3];
}

then just create Normal normal. And make the function take a normal as input. A bit sleepy now so maybe this isn't very understandable.

EDIT:
For clarity
struct Point{	float x;	float y;	float z;}struct Normal{	float x;	float y;	float z;	void Normalize()	{		float length = sqrt(normal.x*normal.x + normal.y*normal.y + normal.z*normal.z);		if(length > 0)		{			normal.x /= length;			normal.y /= length;			normal.z /= length;		}	}}Point Collision::NormaliseNormal(Normal normal, Point testPoint, Point corner)


[Edited by - Net-Ninja on December 8, 2010 2:32:34 PM]

Video Game Programmer.
5 years in industry.

Awsome thanks a lot I will replace the arrays with structs.

I understand how to use structs and have a small knowledge of C and understand structs within the language. I was under the impression that with the objects and the way classes are structured in C(plusplus) that structs where slightly redundent. I am now assuming this is completely wrong. I have no problems using them and will be happy to group my variables. the books I have read just breifly mention structs but never really give any importance or relavence.

In the real world are structs an important thing within C(plusplus)?

Would you generally have a static class and then within this have structs and just pass structs between each other. I'm assuming object classes you don't require this as you have the fields you can access directly from the object?

Also is there a reason why cant return arrays? Is it something with the way the langauge operates maybe to do with string acceptence? Or the way in which the memory is allocated?

More of a curiosity

sorry just really intrigued into how things work in the real world on bigger projects as opposed to in examples etc.

Many thanks
structs and classes work exactly the same way in C++. The only difference is that members are default private in classes and default public in structs. Structs in C doesn't have member functions so remove the Normalize() method from the struct if you want it to work in C.

EDIT: just saw a bug, if length is 0 then you will try to divide by zero which you cant do. there should be an if statement there. Will add it to my post now.

Video Game Programmer.
5 years in industry.

Many thanks for the additional help with code and explanation :)
I heard or read somewhere that structs where an old thing in C. I assumed by the way it sounded that they would cause some kind of overhead or problem in c(PLUSPLUS). Obviously I got the wrong impression and will use structs to group stuff together.

Awsome update with the bug spotting. Thanks for the example code and help with how everything should be structured. Could have took me years to figure that out :D

Many thanks for the help and explanation on it and the clarification

I am now going to go back and sort my stuff into nice managable structs to use.

Thanks again
Hi again sorry its probably me being a compete idiot.

I am attmepting to organise everything into structs however I can't seem to pass the values from one place to another.

Within the main I am attempting to generate a wall with the values
{-50,-150,-50,50} (x1,z1,x2,z2) The y axis is the same on every wall and so I draw that fine after and can use a number for the calculations etc.

I am attempting to make a
struct Wall
{
wall[4];
};

I then want the values specified in the main to go to this wall[4];
I then want to be able to use these values in my Enviroment::drawwall and my Collision::CalculateNormal etc.

I keep getting linking erros and problems trying to pass the values.

I am now attempting to create float wall1[] = {-50,-150,-50,50}; in the main

and then using Enviroment::Wall(wall1); To try and input the values into the struct. I have attempted declaring the struct in the main and I can access the variables there but no where else and I cant import any header files etc to my Enviroment to use it?

I want to be able to declare the values in one place and use them in 3 places I can only get the structs to allow me to use them in the 1 class which doesn't allow me to do what I want.

Am doing it completely wrong?

I am very confused by this now.

How do I pass the variables across classes?

Many thanks Sorry again for all the questions
Quote:
I keep getting linking erros and problems trying to pass the values.

You're not showing enough code. Ideally you would post something that would compile, so we can test if it should compile or tell you how to make it work.

Here is how it might be done:
struct Vec2{  float x, z;  Vec2() : x(0), z(0) {}  Vec2(float x, float z) : x(x), z(z) {}};struct Wall{  Vec2 vertices[2];};class Environment{public:   void drawWall(const Wall &wall);   // ...};int main(){  Wall wall = {     Vec2(-50,-150),    Vec2(-50,50)   };    // ...  environment.drawWall(wall);}
Thanks for the help its so frustrating that when I put all the code in the main it worked yet trying to split it up so can be reused and easier to read etc it broke it now is a complete mess I will post the code in seperate boxes to show you the classes I am trying to get this to run on.

My main class is this... The idea is to be able to declare wall here in a line and then be able to pass values to other classes.

#include <windows.h>		// Header File For Windows#include <gl\gl.h>			// Header File For The OpenGL32 Library#include <gl\glu.h>			// Header File For The GLu32 Library#include <vector>#include "console.h"#include "Boat_Pos.h"#include "360_Controller.h"#include "Camera.h"#include "Calculation.h"#include "Enviroment.h"#include <math.h>#include "Collision.h"#include "Controller.h"ConsoleWindow console;#include <iostream>using namespace std;int screenWidth=640, screenHeight=480;bool keys[256];double spin=0;double mouse_x, mouse_y;bool LeftPressed = false;//double speed = 0;//CXBOXController* Player1;//OPENGL FUNCTION PROTOTYPESvoid display();				//called in winmain to draw everything to the screenvoid reshape();				//called when the window is resizedvoid init();				//called in winmain when the program starts.void processKeys();         //called in winmain to process keyboard inputvoid update();				//called in winmain to update variablesvoid drawTriangle();float wall1[] = {-50,-150,-50,50};Enviroment::Wall(test);Boat_Pos Player(0,0,0);Boat_Pos Player2boat(0,0,0);Camera userCamera(1);Camera userCamera2(1);Enviroment track;Collision wallNormal;Collision normalTest;int currentTime=0,lastTime=0;float elapsedTime=0;static float translatePlayerSpeed = 0;static float translateRotation = 0;CXBOXController* Player1Controller;CXBOXController* Player2Controller;Controller Player1;Controller Player2;/*************    START OF OPENGL FUNCTIONS   ****************/void display()									{	currentTime = GetTickCount();	elapsedTime = ((float)currentTime - (float)lastTime)/1000.0f;	lastTime = currentTime;				//Players 1 screen	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	glViewport(0,0,screenWidth/2,screenHeight);							glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix	glLoadIdentity();									// Reset The Projection Matrix	//set up a perspective view (fov, aspect ratio, near, far)	gluPerspective(45.0f,(GLfloat)screenWidth/(GLfloat)screenHeight,0.1f,1000.0f);		glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix	glLoadIdentity();									// Reset The Modelview Matrix			glMatrixMode(GL_PROJECTION);    glLoadIdentity();    gluPerspective(45.0f,(GLfloat)(screenWidth/2)/(GLfloat)screenHeight,0.1f,1000.0f);    glMatrixMode(GL_MODELVIEW);    glLoadIdentity();		userCamera.checkCam(Player1Controller);	userCamera.readCam(Player,Player1Controller);		glPushMatrix();	//all water	int bottomWater = 0;	int MiddleWater = 1;	float Playerbbpoints[] = {Player.boatDirectionX-4,Player.boatDirectionZ-4,Player.boatDirectionX+4,Player.boatDirectionZ+4};	float playerPPTest[] = {Player.boatDirectionX,Player.boatDirectionZ,Player.boatDirectionX,Player.boatDirectionZ};	glColor3f(0.0,0.0,1.0);	track.drawWater(-50,0,-150,50,0,50,0);	track.drawWater(-600,0,-500,50,0,-150,1);	track.drawWater(-600,0,-750,-500,0,-500,0);			Enviroment::InitiliseEnviroment(wall1);						int playerSpeedAccelerate = Player1.RightTrigger(Player1Controller);	int playerSpeedDeccelerate = Player1.LeftTrigger(Player1Controller);	float boatRotation = Player.BoatRotation(Player1Controller);	Player.BoatSpeed(playerSpeedAccelerate,playerSpeedDeccelerate,elapsedTime);		Player.BoatDirectionX(Player1Controller);	Player.BoatDirectionZ(Player1Controller);			glPushMatrix();		glTranslatef(Player.boatDirectionX,0,Player.boatDirectionZ);		glRotatef(boatRotation,0,1,0);		glRotatef((Player.speed*5)*-1,1,0,0);		//std::cout<<"lean"<<(Player.speed*10)*-1<<std::endl;		Player.DrawBoat(1,0,0);	glPopMatrix();



I am then trying to draw the walls an intilise variables etc here

void Enviroment::drawWall(float wallArray[],float boatPoint[]){			glPushMatrix();	glBegin(GL_POLYGON);		glColor3f(0.7,0.7,0.7);		glTexCoord2f(0,0); glVertex3f(wallArray[0], 0, wallArray[1]);		glTexCoord2f(1,0); glVertex3f(wallArray[0], 3, wallArray[1]);		glTexCoord2f(1,1); glVertex3f(wallArray[2], 3, wallArray[3]);		glTexCoord2f(0,1); glVertex3f(wallArray[2], 0, wallArray[3]);		glEnd();		glPopMatrix();	}static Enviroment::Wall InitiliseEnviroment(float testArray[]){	std::cout<<"array 1 is "<<testArray[0]<<std::endl;	std::cout<<"array 2 is "<<testArray[1]<<std::endl;	std::cout<<"array 3 is "<<testArray[2]<<std::endl;	std::cout<<"array 4 is "<<testArray[3]<<std::endl;        //there should be the normal calculation in here}


last but not least the normal calculation and collision detection is done here.
I haven't changed this to work with my structs yet and they are still set up from when I was attempting to pass arrays across.

float * Collision::CalculateNormal(float normalArray[3][3],float normal[3]){	//calcualte cross product	float ux = normalArray[1][0] - normalArray[0][0];	float uy = normalArray[1][1] - normalArray[0][1];	float uz = normalArray[1][2] - normalArray[0][2];	float vx = normalArray[2][0] - normalArray[0][0];	float vy = normalArray[2][1] - normalArray[0][1];	float vz = normalArray[2][2] - normalArray[0][2];	//float normal[3];	normal [0] = ((vy*uz) - (vz*uy))*-1;	normal [1] = ((vz*ux) - (vx*uz));	normal [2] = ((vx*uy) - (vy*ux));	std::cout<<"The normal1 is "<<normal [0]<<std::endl;	std::cout<<"The normal2 is "<<normal [1]<<std::endl;	std::cout<<"The normal3 is "<<normal [2]<<std::endl;		return normal;}bool Collision::BarryCentricEquation(float triA[],float triB[], float triC[],float point[]){	Collision triangle;	float v0[] = {triC[0] - triA[0],triC[1] - triA[1],triC[2] - triA[2]};	float v1[] = {triB[0] - triA[0],triB[1] - triA[1], triB[2] - triA[2]};	float v2[] = {point[0] - triA[0],point[1] - triA[1],point[2] - triA[2]};	float dot00 = Calculation::dotProduct(v0,v0);	float dot01 = Calculation::dotProduct(v0,v1);	float dot02 = Calculation::dotProduct(v0,v2);	float dot11 = Calculation::dotProduct(v1,v1);	float dot12 = Calculation::dotProduct(v1,v2);	float bcc = 1/(dot00 * dot11 - dot01 * dot01);	float u = (dot11 * dot02 - dot01 * dot12) * bcc;	float v = (dot00 * dot12 - dot01 * dot02) *bcc;		if((u>0) && (v>0) && (u+v<1))	{		triangle.bccCollision = true;	}	else	{		triangle.bccCollision = false;	}		return triangle.bccCollision;	}float Collision::NormaliseNormal(float normalArray[3],float testPoint[4],float corner[3]){		float lengthX = sqrt((normalArray[0]*normalArray[0]) + (normalArray[1]*normalArray[1]) + (normalArray[2]*normalArray[2]));	float normalX = normalArray[0] /= lengthX;	float normalY = normalArray[1] /= lengthX;	float normalZ = normalArray[2] /= lengthX;	float testX[] = {testPoint[0] - corner[0]};	float testY[] = {testPoint[1] - corner[1]};	float testZ[] = {testPoint[2] - corner[2]};	float sX = (testX[0] - corner[0]); 	float sY = (testY[0] - corner[1]);	float sZ = (testZ[0] - corner[2]);	float distanceX = Collision::DotProduct(sX,normalX,0,0,0,0);	float distanceY = Collision::DotProduct(0,0,sY,normalY,0,0);	float distanceZ = Collision::DotProduct(0,0,0,0,sZ,normalZ);	std::cout<<"DistanceX "<<distanceX<<std::endl;	std::cout<<"DistanceY "<<distanceY<<std::endl;	std::cout<<"DistanceZ "<<distanceZ<<std::endl;	float cx = testPoint[0] - distanceX * normalX;	float cy = testPoint[1] - distanceY * normalY;	float cz = testPoint[2] - distanceZ * normalZ;	std::cout<<"cx is "<<cx<<std::endl;	std::cout<<"cy is "<<cy<<std::endl;	std::cout<<"cz is "<<cz<<std::endl;	//float collisionPoints[] = {cx,cy,cz};	return cx;}



Sorry as it is a lot of code. I am no longer using the collision stuff anywhere to try and make it easier to solve. I have tested the functions individually and the results work and are fine. When I try to link it all together I cant quite get my head around how it works.

I have not included the header files but that is just full of prototypes, except for my enviroment header File. I have also included the struct Wall in there so I can use it elsewhere.

Would it be easier to get rid of the classes I have now that don't work and start from scratch trying to design them to include the struct format?
If so how do I get the values from the struct from one class to another?

Many thanks again you have been very helpful and patient and I am sorry to keep bugging you this.


P.S I have now changed the code slightly with a for loop in the main to add all the elements of wall 1 into the wall struct
for(int i = 0; i<4; i++)	{	test.wall = wall1;	std::cout<<"will this work "<<test.wall<<std::endl;	}


It prints all the values out right however it doesn't feel right inputting values like this is that just me being paranoid? would I be able to do in theory test2.wall = wall2, and just do that for every wall?
After much rewriting going over and sorting stuff out I have finally got the information to pass from the main to my enviroment class using the struct as opposed to any arrays.

I am now just going to pass the struct to my collision class and calculate everything.

I would like to say a big thank you to the hlep provided and everyone who looked.

I will end this topic now and hopefully be able to sort everything out.

If I have any more problems I will start a new topic hopefully not to soon though

:D

Many thanks again
To get a struct that "behaves like" an array (in the sense of letting you index the elements with [], and not have to refer to the struct member explicitly), try boost::array.

This topic is closed to new replies.

Advertisement