Beispiel #1
0
int Geometry::rayIntersectSphere(const Vector3 &ray_point, const Vector3 &ray_direction, const Vector3 &sphere_center,
                                 double sphere_radius, Vector3 *hit1, Vector3 *hit2) {
    Vector3 ray_direction_sphere = ray_point.sub(sphere_center);
    double a, b, c, d;

    a = ray_direction.x * ray_direction.x + ray_direction.y * ray_direction.y + ray_direction.z * ray_direction.z;
    b = 2 * (ray_direction.x * ray_direction_sphere.x + ray_direction.y * ray_direction_sphere.y +
             ray_direction.z * ray_direction_sphere.z);
    c = ray_direction_sphere.x * ray_direction_sphere.x + ray_direction_sphere.y * ray_direction_sphere.y +
        ray_direction_sphere.z * ray_direction_sphere.z - sphere_radius * sphere_radius;
    d = b * b - 4 * a * c;

    if (d < 0.0) {
        return 0;
    } else if (d > 0.0) {
        if (hit1 && hit2) {
            *hit1 = ray_point.add(ray_direction.scale((-b - sqrt(d)) / (2 * a)));
            *hit2 = ray_point.add(ray_direction.scale((-b + sqrt(d)) / (2 * a)));
        }
        return 2;
    } else {
        if (hit1) {
            *hit1 = ray_point.add(ray_direction.scale(-b / (2 * a)));
        }
        return 1;
    }
}
Beispiel #2
0
Vector3 Object::computeLocalIllumination(Vector3& position, Vector3& normal,
    Light& light, Vector3& eyePosition) {
    Vector3 color;

    if (!material.skipLocalIllumination) {
        /* compute ambient factor */
        color.add(material.ambient * light.ambient);

        /* compute the diffuse factor */
        /* assume light is directional*/
        real d = - dot(light.direction, normal);
        if (d > 0) {
            /* this is not a back-facing part of the object wrt the light */
            color.add(d * (material.diffuse * light.diffuse));
        }

        /* compute the specular factor */
        Vector3 view = eyePosition - position;
        Vector3 halfway = 0.5f * (view - light.direction);
        halfway.normalize();
        real s = dot(halfway, normal);
        if (s > 0) {
            color.add( pow(s, material.shininess) * material.specular * light.specular);
        }

    }

    return color;
}
void CatmullRomSpline::getPath (std::vector<Vector3>& points, int numPoints) {
    int idx = 0;
    if (controlPoints.size() < 4) return;

    for (unsigned int i = 1; i <= controlPoints.size() - 3; i++) {
        points[idx++] = controlPoints[i];
        float increment = 1.0f / (numPoints + 1);
        float t = increment;

        T1.set(controlPoints[i + 1]).sub(controlPoints[i - 1]).mul(0.5f);
        T2.set(controlPoints[i + 2]).sub(controlPoints[i]).mul(0.5f);

        for (int j = 0; j < numPoints; j++) {
            float h1 = 2 * t * t * t - 3 * t * t + 1; // calculate basis
            // function 1
            float h2 = -2 * t * t * t + 3 * t * t; // calculate basis
            // function 2
            float h3 = t * t * t - 2 * t * t + t; // calculate basis
            // function 3
            float h4 = t * t * t - t * t; // calculate basis function 4

            Vector3 point = points[idx++].set(controlPoints[i]).mul(h1);
            point.add(controlPoints[i + 1].tmp().mul(h2));
            point.add(T1.tmp().mul(h3));
            point.add(T2.tmp().mul(h4));
            t += increment;
        }
    }

    points[idx].set(controlPoints[controlPoints.size() - 2]);
}
Beispiel #4
0
Vector3 Vector3::getNormal5(const Vector3 &posx, const Vector3 &negx, const Vector3 &posy, const Vector3 &negy) const {
    Vector3 dnegx = negx.sub(*this);
    Vector3 dposy = posy.sub(*this);
    Vector3 dposx = posx.sub(*this);
    Vector3 dnegy = negy.sub(*this);

    Vector3 normal = dposy.crossProduct(dnegx);
    normal = normal.add(dposx.crossProduct(dposy));
    normal = normal.add(dnegy.crossProduct(dposx));
    normal = normal.add(dnegx.crossProduct(dnegy));

    return normal.normalize();
}
Beispiel #5
0
void idle() {

	static float position = 0;

	long end = (clock() - start);

	if( end/CLOCKS_PER_SEC > 1 ) {
		printf( "FPS: %d\n", frames );
		frames = 0;
		start = clock();
	}
	
	frames++;
	
	if ( !followPenguin ) {	
		position = min(cameraPath->size() - 1.0f, max(0.0f, position + cameraPlay));

		float percentComplete = position / (cameraPath->size()-1);

		if (cameraPlay != 0) {
			camera->setCenterOfProjection( *cameraPath->at( (int)position ) );
			camera->setLookAtPoint( *lookatPath->at( (int)position ) );			
		}

		if (percentComplete == 0 || percentComplete == 1) {
			cameraPlay = 0;	
		}
	} else {
		// Center camera on penguin.
		Vector3 t = Vector3( pengFrontNormal );
		t.scale( -15 );
		t.add( t, pengLoc );
	
		Vector3 up = Vector3( pengNormal );
		up.scale( 10 );
		t.add( t, up );
		
		Vector3 t2 = Vector3( pengLoc );
		up.scale( .5 );
		t2.add( t2, up );
		
		camera->setCenterOfProjection( t );
		camera->setUp( pengNormal );
		camera->setLookAtPoint( t2 );
		frust->generateFrustumPlanes( camera, frustum );
	}
	
	display();
}
Beispiel #6
0
Vector3 PhysicsConstraint::getWorldCenterOfMass(const Model* model)
{
    Vector3 center;

    const BoundingBox& box = model->getMesh()->getBoundingBox();
    if (!(box.min.isZero() && box.max.isZero()))
    {
        Vector3 bMin, bMax;
        model->getNode()->getWorldMatrix().transformPoint(box.min, &bMin);
        model->getNode()->getWorldMatrix().transformPoint(box.max, &bMax);
        center.set(bMin, bMax);
        center.scale(0.5f);
        center.add(bMin);
    }
    else
    {
        const BoundingSphere& sphere = model->getMesh()->getBoundingSphere();
        if (!(sphere.center.isZero() && sphere.radius == 0))
        {
            model->getNode()->getWorldMatrix().transformPoint(sphere.center, &center);
        }
        else
        {
            // Warn the user that the model has no bounding volume.
            WARN_VARG("Model \'%s\' has no bounding volume - center of mass is defaulting to local coordinate origin.", model->getNode()->getId());
            model->getNode()->getWorldMatrix().transformPoint(&center);
        }
    }

    return center;
}
Beispiel #7
0
void Viewport::getMovementVector(float x, float y, Vector3& v) const 
{
	Vector3 xb(xDir()), yb(yDir());
	xb.inplaceMul(x/scale);
	yb.inplaceMul(y/scale);
	v.add(xb,yb);
}
static Vector3 _getDetailNormal(Vector3 base_location, Vector3 base_normal, TextureLayerDefinition *layer,
                                double precision, bool normal5) {
    Vector3 result;

    /* Find guiding vectors in the appoximated local plane */
    Vector3 dx, dy;
    Vector3 pivot;
    if (base_normal.y > 0.95) {
        pivot = VECTOR_NORTH;
    } else {
        pivot = VECTOR_UP;
    }
    dx = base_normal.crossProduct(pivot).normalize();
    dy = base_normal.crossProduct(dx).normalize();

    /* Apply detail noise locally */
    Vector3 center, north, east, south, west;
    auto detail_noise = layer->propDetailNoise()->getGenerator();
    double detail = precision;
    double offset = precision * 0.1;

    center = base_location.add(base_normal.scale(detail_noise->getTriplanar(detail, base_location, base_normal)));

    east = base_location.add(dx.scale(offset));
    east = east.add(base_normal.scale(detail_noise->getTriplanar(detail, east, base_normal)));

    south = base_location.add(dy.scale(offset));
    south = south.add(base_normal.scale(detail_noise->getTriplanar(detail, south, base_normal)));

    if (normal5) {
        west = base_location.add(dx.scale(-offset));
        west = west.add(base_normal.scale(detail_noise->getTriplanar(detail, west, base_normal)));

        north = base_location.add(dy.scale(-offset));
        north = north.add(base_normal.scale(detail_noise->getTriplanar(detail, north, base_normal)));

        result = center.getNormal5(south, north, east, west);
    } else {
        result = center.getNormal3(south, east);
    }

    if (result.dotProduct(base_normal) < 0.0) {
        result = result.scale(-1.0);
    }
    return result;
}
Beispiel #9
0
void Viewport::getMovementVectorAtDistance(float x, float y, float dist, Vector3& v) const
{
	Vector3 xb(xDir()), yb(yDir());
	Real imagePlaneDepth = w*scale;
	xb.inplaceMul(x*dist/imagePlaneDepth);
	yb.inplaceMul(y*dist/imagePlaneDepth);
	v.add(xb,yb);
}
Vector3 TexturesRenderer::displaceTerrain(const TexturesDefinition *textures, const Vector3 &location,
                                          const Vector3 &normal) const {
    double offset = 0.0;
    int i, n;

    n = textures->getLayerCount();
    for (i = 0; i < n; i++) {
        TextureLayerDefinition *layer = textures->getTextureLayer(i);

        if (layer->hasDisplacement()) {
            offset += _getLayerDisplacement(layer, location, normal);
        }
    }

    return location.add(normal.scale(offset));
}
vector<Vector3> TexturesRenderer::getLayersDisplacement(const TexturesDefinition *textures, const Vector3 &location,
                                                        const Vector3 &normal, const vector<double> &presence) const {
    int n = textures->getLayerCount();
    assert(presence.size() == to_size(n));
    vector<Vector3> result;
    Vector3 displaced = location;
    for (int i = 0; i < n; i++) {
        double layer_presence = presence[i];
        if (layer_presence > 0.0) {
            TextureLayerDefinition *layer = textures->getTextureLayer(i);
            double displacement = _getLayerDisplacement(layer, location, normal, layer_presence);
            displaced = displaced.add(normal.scale(displacement * layer_presence));
        }
        result.push_back(displaced);
    }
    return result;
}
Beispiel #12
0
GodRaysResult GodRaysSampler::getResult(const SpaceSegment &segment) {
    Vector3 step = segment.getEnd().sub(segment.getStart());
    double max_length = step.getNorm();
    step = step.normalize().scale(walk_step);
    Vector3 walker = segment.getStart();
    double travelled = 0.0;
    double inside = 0.0;

    if (max_length > this->max_length) {
        max_length = this->max_length;
    }

    while (travelled < max_length) {
        double light = getCachedLight(walker);

        inside += light * walk_step;

        walker = walker.add(step);
        travelled += walk_step;
    }

    return GodRaysResult(inside, travelled);
}
    /*!
    * creates a BoundingSphere which encloses all given bvhNodes and adds all children
    * to this parent
    */
    void DeformableBvhNode::createBoundingSpherePrecise(const std::list<DeformableBvhNode*>& bvhNodes) {

        //std::cout << "DeformableBvhNode::createBoundingSphere(const std::list<DeformableBvhNode*>& bvhNodes)" << std::endl;

        int counter = 0;
        Vector3 centerVector;
        real biggestDistance = 0.0f;
        real biggestRadius = 0.0f;

        for (std::list<DeformableBvhNode*>::const_iterator iter = bvhNodes.begin();
                                                            iter != bvhNodes.end();
                                                            ++iter) {
            ++counter;
            centerVector.add(((BoundingSphere*)((*iter)->getBoundingVolume()))->getCenterVector());
        }

        centerVector = centerVector * ( 1.0f / counter);

        real tempDistance;
        real tempRadius;

        for (std::list<DeformableBvhNode*>::const_iterator iter = bvhNodes.begin();
                                                            iter != bvhNodes.end();
                                                            ++iter) {

            tempDistance = (centerVector - (((BoundingSphere*)((*iter)->getBoundingVolume()))->getCenterVector())).length();
            tempRadius = ((BoundingSphere*)((*iter)->getBoundingVolume()))->getRadius();

            if (   tempDistance+tempRadius > biggestDistance   ) {
                biggestDistance = tempDistance+tempRadius;
            }
        }

        biggestRadius = biggestDistance;

        mBoundingVolume = new BoundingSphere(centerVector, biggestRadius);
    }
Beispiel #14
0
Vector3 Vector3::lerp(Vector3& target, float alpha) {
    Vector3 r = this->mul(1.0f - alpha);
    r.add(target.tmp().mul(alpha));
    return r;
}
Beispiel #15
0
/** détecte, entre b1 et b2, la collision et donne les informations nécessaires à la réponse dans *collision
  - principe : il faut déterminer les distances de recouvrement sur chacun des 4 axes possibles (2 axes pour b1 et 2 axes pour b2).
    si on trouve une distance négative, c'est que les boites ne se recouvrent pas sur cet axe => pas de collision (arrêt).
    si toutes les distances sont positives : b1 et b2 sont en intersection, et on renseigne *collision :
    - collision->mtd=un double : distance minimal sur les 4 axes (i.e. distance nécessaire pour séparer les 2 boites : sera utilisé pour la correction en position)
    - collision->normale=un Vector3 : l'axe de la distance minimal qui donne la normale au contact (i.e. direction de séparation)
    - collision->apply=un Vector3 : le point d'application qui sera utilisé pour l'impulsion (utilisé pour le calcul du moment de la force d'impulsion) :
      Le point d'application est déjà calculé (moyenne de tous les sommets intérieurs aux boites).
**/
bool Box::detectCollision(Box *b1,Box *b2,CollisionInfo *collision) {
  double dist;
  double dist_min;


  Vector3 axis[4]; // 4 axes à tester
  Vector3 axe_min; // l'axe qui correspond à la plus petite distance de séparation.


  double direction;

  // les 4 axes potentiellement séparateurs
  axis[0]=b1->directionX(); // axe x de b1
  axis[1]=b1->directionY(); // axe y de b1
  axis[2]=b2->directionX(); // axe x de b2
  axis[3]=b2->directionY(); // axe y de b2

  bool detect;

  // A completer (1 seul axe pour l'instant => il faut tenir compte des 4 axes) :
  // - déterminez la distance minimale dist_min de recouvrement entre les 4 axes axis[i] qui sont non séparateurs (Attention : minimale en valeur absolue !, mais dist_min est négative s'il y a recouvrement)
  // - vous devez affecter correctement axe_min (l'axe correspondant à dist_min) qui est un des axis[i] *mais* en tenant compte du sens de séparation de
  //   b2 par rapport à b1 (i.e. multiplier axis[i] par le signe (-1 ou 1) retourné par la méthode distance(b1,b2,...,)).
  // - assurez vous d'avoir affecté correctement detect à la fin (==true il y a collision, == false pas de collision).

  distance(b1,b2,axis[0],&dist,&direction);
  if (dist<0) p3d::addDebug(b1->position(),b1->position()-direction*dist*axis[0],"",Vector3(0.2,0.2,1));
  detect=false; // force une non détection (à enlever lorsque la détection est implémentée...).

  // affecter les informations nécessaires à la réponse
  if (detect) {
    collision->mtd(dist_min);
    collision->axis(axe_min);

    // Calcul du point d'application de l'impulsion (ici barycentre des sommets intérieurs).
    // on créé la liste de tous les sommets inclus dans une des boites
    vector<Vector3> liste;
    liste.clear();
    for(unsigned int i=0; i<4; i++) {
      if (b1->isInside(b2->vertex(i))) liste.push_back(b2->vertex(i));
    }

    for(unsigned int i=0; i<4; i++) {
      if (b2->isInside(b1->vertex(i))) liste.push_back(b1->vertex(i));
    }

    Vector3 apply;
    apply.set(0,0,0);
    for(unsigned int i=0; i<liste.size(); i++) {
      apply.add(liste[i]);
    }
    apply=apply/liste.size();

    collision->applicationPoint(apply);

    collision->box1(b1);
    collision->box2(b2);
  }

  return detect;
}
Beispiel #16
0
void update(int t) {

	if (currentCamera == 0) {

		cameraAngle += (diffMouseDownX / 100.0);
		cameraDistance = (cameraDistance += (diffMouseDownY / 20.0)) < 10 ? 10 : cameraDistance;
		camera.set(
			cameraDistance * cos(cameraAngle * (M_PI / 180)),
			cameraElevation,
			cameraDistance * sin(cameraAngle * (M_PI / 180))
			);
		cameraLookAt = Vector3();
		cameraUp = Vector3(0, 1, 0);

	}
	else if (currentCamera == 1) {

		aboveCamera.y = (std::max(50.0, aboveCamera.y + (diffMouseDownY / 100.0)));

		aboveCameraLookAt = Vector3(0, aboveCamera.y - 100, aboveCamera.z);
		cameraLookAt = aboveCameraLookAt;
		camera.set(aboveCamera.x, aboveCamera.y, aboveCamera.z);
		cameraUp = aboveCameraUp;

	}
	else if (currentCamera == 2) {

		frontCamera.y = (frontCamera.y + (diffMouseDownY / 100.0));
		frontCamera.x = (frontCamera.x - (diffMouseDownX / 100.0));
		frontCamera.z = (cameraDistance);

		frontCameraLookAt = frontCamera.add(Vector3(0.0, 0.0, -1.0));
		cameraLookAt = frontCameraLookAt;

		camera.set(frontCamera.x, frontCamera.y, frontCamera.z);

		cameraUp = frontCameraUp;

	}
	else if (currentCamera == 3) {

		getFreeCameraLookAt();
		cameraLookAt = freeCameraLookAt;

		camera.set(freeCamera.x, freeCamera.y, freeCamera.z);

		freeCameraUp.x = sin(upAngle * (M_PI / 180));
		freeCameraUp.y = cos(upAngle * (M_PI / 180));

		cameraUp = freeCameraUp;

	}
	else if (currentCamera >= 4) {

		updateFlyBy();

		cameraLookAt = flyBySettings.lookAt;
		camera.set(
			flyBySettings.position.x,
			flyBySettings.position.y,
			flyBySettings.position.z
			);

		cameraUp = flyBySettings.up;

	}

	gravity.y = gravityIntensity;

	particleSystem.applyForce(gravity);

	for (int i = 0; i < 9; i++) {
		if (gravitationalForce[i].type != GRAVITATIONALFORCETYPE_NONE) {
			particleSystem.applyGravitationalForce(gravitationalForce[i]);
		}
	}

	if (cycleColours) {
		colourSwitch--;
		if (colourSwitch == 0) {
			colourSwitch = 10;
			Particle::startColour = emitColours[initialColour];
			currentColour = Particle::startColour;
			initialColour = (++initialColour) == colourCount ? 0 : initialColour;
		}
		else {
			Particle::startColour.r = linearEase(10 - colourSwitch, currentColour.r, emitColours[initialColour].r - currentColour.r, 10);
			Particle::startColour.g = linearEase(10 - colourSwitch, currentColour.g, emitColours[initialColour].g - currentColour.g, 10);
			Particle::startColour.b = linearEase(10 - colourSwitch, currentColour.b, emitColours[initialColour].b - currentColour.b, 10);
		}
	}

	particleSystem.update();

	// FPS monitoring
	frame++;
	elapsedTime = glutGet(GLUT_ELAPSED_TIME);
	if (elapsedTime - timebase > 1000) {
		fps = frame * 1000.0 / (elapsedTime - timebase);
		timebase = elapsedTime;
		frame = 0;
	}

	glutPostRedisplay();
	glutTimerFunc(30, update, 0);

}
Beispiel #17
0
void idle() {
	keyboardEvent();
	int time_ = glutGet(GLUT_ELAPSED_TIME);
	float angle = time_ / 1000.0 * 10;

	Vector3 pos = player.getPosition();
	float angX = player.getRotationX(),
		  angY = player.getRotationY();

	Vector3 cpos = cube.getPosition(),
			cpos2= cube2.getPosition();

	GLfloat D = cpos.distance(&cpos2),
			W = (cube.dimension() + cube2.dimension())/2;
	float bound = 6.0;
	//if(time_%100 < 10)
	//	gravity = Vector3(rand()%10-5, rand()%10-5, rand()%10-5);
	cvelocity.add(&gravity);
	Vector3 s = cvelocity;
	s.mult(-mass/1000).add(&cpos2);
	bool collides = true;
	if(cpos2.x < -bound && cvelocity.x > 0.0f){
		cvelocity.x = -abs(cvelocity.x)*0.5;
		gravity.x = -abs(gravity.x);
	}
	else if(cpos2.x > bound && cvelocity.x < 0.0f){
		cvelocity.x = abs(cvelocity.x)*0.5;
		gravity.x = abs(gravity.x);
	}
	else if(cpos2.y < -bound && cvelocity.y > 0.0f){
		cvelocity.y = -abs(cvelocity.y)*0.5;
		gravity.y = -abs(gravity.y);
	}
	else if(cpos2.y > bound && cvelocity.y < 0.0f){
		cvelocity.y = abs(cvelocity.y)*0.5;
		gravity.y = abs(gravity.y);
	}
	else if(cpos2.z < -bound && cvelocity.z > 0.0f){
		cvelocity.z = -abs(cvelocity.z)*0.5;
		gravity.z = -abs(gravity.z);
	}
	else if(cpos2.z > bound && cvelocity.z < 0.0f){
		cvelocity.z = abs(cvelocity.z)*0.5;
		gravity.z = abs(gravity.z);
	}
	else{
		collides = false;
	}
	
	if(!collides){
		if(cpos.x + cube.min.x <= cpos2.x + cube2.max.x && cpos.x + cube.max.x >= cpos2.x + cube2.min.x && 
			cpos.z + cube.min.z <= cpos2.z + cube2.max.z && cpos.z + cube.max.z >= cpos2.z + cube2.min.z && 
			cpos.y + cube.min.y <= cpos2.y + cube2.max.y && cpos.y + cube.max.y >= cpos2.y + cube2.min.y){
			collides = true;
			cvelocity.x = cvelocity.y = cvelocity.z = 0.0f;
		}
		
		if(!collides)
			cube2.setPosition(s);
	}

	player.updateForce();
	for (int i = 0; i < BALLS; i++){
		balls[i].updateForce();
		Vector3 ball_pos = balls[i].getPosition(),
				ball_vel = balls[i].dynamics.velocity;
		//printf("x: %f, y: %f, z %f: %f\n", ball_pos.x, ball_pos.y, ball_pos.z, BOUNDARY);
		if(ball_pos.x < -BOUNDARY || ball_pos.x > BOUNDARY)
			balls[i].addVelocity(Vector3(-2 * ball_vel.x, 0.0f, 0.0f));
		if(ball_pos.y < -BOUNDARY || ball_pos.y > BOUNDARY)
			balls[i].addVelocity(Vector3(0.0f, -2 * ball_vel.y, 0.0f));
		if(ball_pos.z < -BOUNDARY || ball_pos.z > BOUNDARY)
			balls[i].addVelocity(Vector3(0.0f, 0.0f, -2 * ball_vel.z));
	}

	Matrix4 model = cube.getTransformMatrix(),
			model2 = cube2.getTransformMatrix();
	Matrix4 projection = Matrix4().Perspective(45.0f, 1.0f*screen_width/screen_height, 0.1f, 50.0f),
			view = Matrix4().lookAt(pos, Vector3(pos.x-cos(angX), pos.y + sin(angY), pos.z + sin(angX)), Vector3(0.0f, 1.0f, 0.0f));
	Matrix4 anim = Matrix4().RotateA(angle*3.0f, Vector3(1, 0, 0)) * 	// X axis
					Matrix4().RotateA(angle*2.0f, Vector3(0, 1, 0)) *	// Y axis
					Matrix4().RotateA(angle*4.0f, Vector3(0, 0, 1));	// Z axis


	Matrix4 m_transform = projection * view;

	glUseProgram(cube.getProgram());
	glUniformMatrix4fv(cube.getUniform("m_transform"), 1, GL_FALSE, m_transform * model);

	glUseProgram(cube2.getProgram());
	glUniformMatrix4fv(cube2.getUniform("m_transform"), 1, GL_FALSE, m_transform * model2);

	for (int i = 0; i < BALLS; i++){
		glUseProgram(balls[i].getProgram());
		glUniformMatrix4fv(
			balls[i].getUniform("m_transform"), 	// m_transform is the transformation of balls[i] in shaders
			1, 										// one uniform-buffer 
			GL_FALSE, 								// no nprmalization
			m_transform * balls[i].getTransformMatrix()
		);
	}
	for (int i = 0; i < DETAIL_GRID*3; i++){
		grid[i].updateForce();
		glUseProgram(grid[i].getProgram());
		glUniformMatrix4fv(
			grid[i].getUniform("m_transform"), 	// m_transform is the transformation of grid[i] in shaders
			1, 										// one uniform-buffer 
			GL_FALSE, 								// no nprmalization
			m_transform * grid[i].getTransformMatrix()
		);
	}

	glutPostRedisplay();
}
Beispiel #18
0
		Vector3 operator+(Vector3 vectorA, const Vector3& vectorB)
		{
			return vectorA.add(vectorB);
		}