C++ & SFML Separating Axis Theorem - c++

I'm trying to implement collision detection in sfml using the separating axis theorem but my function to get the min translation vector (getMtv()) is always returning that there is a collision (MTV::IsValid()). I was following a tutorial here
but I can't see where I went wrong.
#include <iostream>
#include <math.h>
#include <SFML/Graphics.hpp>
#include <gtest/gtest.h>
typedef sf::Vector2f Vector2;
typedef sf::Vector2f Axis;
typedef sf::Vector2f Projection;
typedef std::vector<Axis> AxesVec;
class MTV
{
private:
bool _valid;
Axis _axis;
float _overlap;
public:
MTV(Axis axis, float overlap, bool valid)
{
_valid = valid;
_overlap = overlap;
_axis = axis;
}
bool IsValid() const
{
return _valid;
}
};
Vector2 perpendicular(Vector2 v)
{
return Vector2(v.y, -v.x);
}
float dot(Vector2 vec1, Vector2 vec2)
{
return (vec1.x * vec2.x) + (vec1.y * vec2.y);
}
float magnitude(Vector2 v)
{
return std::sqrt(dot(v,v));
}
class Polygon : public sf::ConvexShape
{
public:
const AxesVec& GetAxes() const
{
return axes;
}
AxesVec axes;
void generateAxes()
{
for (int i = 0; i < getPointCount(); i++)
{
// get the current vertex
Vector2 p1 = getPoint(i); //shape.vertices[i];
// get the next vertex
Vector2 p2 = getPoint(i + 1 == getPointCount() ? 0 : i + 1);
// subtract the two to get the edge vector
Vector2 edge = p1 - p2;
// get either perpendicular vector
Vector2 normal = perpendicular(edge);
// the perp method is just (x, y) => (-y, x) or (y, -x)
axes.push_back(normal / magnitude(normal));
}
};
float cross(Vector2 vec1, Vector2 vec2)
{
return (vec1.x * vec2.y) - (vec1.y * vec2.x);
}
Vector2 project(Polygon p, Axis axis)
{
float min = dot(axis, p.getPoint(0)); //axis.dot(shape.vertices[0]);
float max = min;
for (int i = 1; i < p.getPointCount(); i++)
{
// NOTE: the axis must be normalized to get accurate projections
float prj = dot(axis, p.getPoint(i));//axis.dot(shape.vertices[i]);
if (prj < min)
{
min = prj;
}
else if (prj > max)
{
max = prj;
}
}
//Projection proj = new Projection(min, max);
return Projection(min, max);
}
class Collison
{
private:
Vector2 mtv;
Polygon a;
Polygon b;
};
bool overlap(Projection a, Projection b)
{
// x = min & y = max
return !(a.x > b.y || a.x > b.y);
}
float getOverlap(Projection a, Projection b)
{
// x = min & y = max
return (a.y < b.y) ? a.y - b.x : b.y - a.x;
}
MTV getMtv(Polygon a, Polygon b)
{
float overlapMax = std::numeric_limits<float>::infinity();// really large value;
float Overlap;
Axis smallest;// = null;
AxesVec axesA = a.GetAxes();
AxesVec axesB = b.GetAxes();
// loop over the axes1
for (auto&& axis : axesA) //for (int i = 0; i < axes1.length; i++)
{
//Axis axis = axes1[i];
// project both shapes onto the axis
Projection pA = project(a, axis);
Projection pB = project(b, axis);
// do the projections overlap?
if (!overlap(pA, pB)) //(!p1.overlap(p2))
{
// then we can guarantee that the shapes do not overlap
return MTV(smallest, 0, false);
}
else
{
// get the overlap
float o = getOverlap(pA, pB); //p1.getOverlap(p2);
// check for minimum
if (o < overlapMax)
{
// then set this one as the smallest
Overlap = o;
smallest = axis;
}
}
}
for (auto&& axis : axesB) //for (int i = 0; i < axes1.length; i++)
{
//Axis axis = axes1[i];
// project both shapes onto the axis
Projection pA = project(a, axis);
Projection pB = project(b, axis);
// do the projections overlap?
if (!overlap(pA, pB)) //(!p1.overlap(p2))
{
// then we can guarantee that the shapes do not overlap
return MTV(smallest, 0, false);
}
else
{
// get the overlap
double o = getOverlap(pA, pB); //p1.getOverlap(p2);
// check for minimum
if (o < overlapMax)
{
// then set this one as the smallest
Overlap = o;
smallest = axis;
}
}
}
//MTV mtv = new MTV(smallest, overlap);
// if we get here then we know that every axis had overlap on it
// so we can guarantee an intersection
return MTV(smallest, Overlap, true);
}
int main(int argc, char **argv)
{
Polygon polygon;
polygon.setPointCount(3);
polygon.setPoint(0, sf::Vector2f(500, 100));
polygon.setPoint(1, sf::Vector2f(250, 500));
polygon.setPoint(2, sf::Vector2f(750, 500));
polygon.setFillColor(sf::Color::Red);
polygon.generateAxes();
Polygon polygon2;
polygon2.setPointCount(3);
polygon2.setPoint(0, sf::Vector2f(100, 0));
polygon2.setPoint(1, sf::Vector2f(50, 150));
polygon2.setPoint(2, sf::Vector2f(150, 150));
polygon2.generateAxes();
//polygon2.setPoint(0, sf::Vector2f(100, 0));
//polygon2.setPoint(1, sf::Vector2f(500, 150));
//polygon2.setPoint(2, sf::Vector2f(250, 150));
polygon2.setFillColor(sf::Color::Green);
sf::RenderWindow window(sf::VideoMode(800, 600), "My window");
// run the program as long as the window is open
while (window.isOpen())
{
// check all the window's events that were triggered since the last iteration of the loop
sf::Event event;
while (window.pollEvent(event))
{
// "close requested" event: we close the window
if (event.type == sf::Event::Closed)
window.close();
}
// clear the window with black color
window.clear(sf::Color::Black);
// draw everything here...
window.draw(polygon);
window.draw(polygon2);
std::cout << getMtv(polygon, polygon2).IsValid() << std::endl;
// end the current frame
window.display();
}
return 0;
}

Related

sfml - textures are not rendered

I decided to make a multiplayer game in sfml, the map is a text variable
one step lower,! - block with a collider, # - ground.
It looks something like this:
"## !;
! # !;
###;"
I have a special class "Qardrat" that represents a block with a texture, that is, an alternative to a sprite.
class Quardrat {
public:
void spriteSetPosition(int Vx, int Vy) {
sprite.setPosition(Vx, Vy);
}
void LoadTexture(String textureName) {
texture.loadFromFile(textureName);
// RectangleShape tmpSprite(texture);
sprite.setScale(sizeX, sizeY);
sprite.setTexture(&texture);
}
void ShapeMove(int Vx, int Vy) {
sprite.move(Vx, Vy);
//sprite.setPosition(sprite.getPosition().x+Vx, sprite.getPosition().y+Vy);
std::cout << "Сдвинулся на " << Vx << "По x" << std::endl;
}
Quardrat(float x = 0, float y = 0, float sx = 1, float sy = 1, String textureName = "player.png") {
LoadTexture(textureName);
sizeX = sx;
sizeY = sy;
sprite.setPosition(x, y);
sprite.setSize(Vector2f(sx, sy));
}
sf::RectangleShape GetShape() {
return sprite;
}
void DrawShape() {
::window.draw(sprite);
}
float GetSizeX() {
return sizeX;
}float GetSizeY() {
return sizeY;
}
private:
Texture texture;
std::string texutreName = "player.png";
float sizeX = 10;
float sizeY = 10;
//Sprite sprite;
RectangleShape sprite;
};
It is declared as follows: x position, y position, height, width, texture name.
To draw objects, 3 cities are used, which are placed in the square classes:
sloi0, sloi1, player /
here is the drawing code
void DrawOnDisplay(const std::vector<std::reference_wrapper<Quardrat>>& a) {//РИСОВАНИЕ
for (Quardrat i : sloi0)
i.DrawShape();
//::window.draw(i.GetShape());
for (Quardrat i : sloi1)
i.DrawShape();
// ::window.draw(i.GetShape());
for (Quardrat i : a) {
i.DrawShape();
// ::window.draw(i.GetShape());
}
}
And I'll leave the card reading code here, just in case:
for (char block : map) {
if (block == '#') {
Quardrat bl = Quardrat(BlockPosX * StandartBlockSize, BlockPosY * StandartBlockSize, StandartBlockSize, StandartBlockSize);
sloi0.push_back(bl); BlockPosX++;
// }
if (block == '!') {
Quardrat bl = Quardrat(BlockPosX * StandartBlockSize, BlockPosY * StandartBlockSize,
StandartBlockSize / 10, StandartBlockSize / 10, "block.png");
sloi0.push_back(bl); BlockPosX++;
collisions.push_back(bl);
}
if (block == ';') {
BlockPosY++;
BlockPosX = 0;
}
}
And here's the problem - from all the blocks of the map, a texture appears only for one, for all the rest - a white square.

Invalid operands to binary expression (‘const Vector’ and ‘const Vector’)

I am new to c++ and I get this error “Invalid operands to binary expression (‘const Vector’ and ‘const Vector’)” and I have no idea where to look at in my own code.
The error appears at the line “{return __x < __y;}” in _functional_base:
#if _LIBCPP_STD_VER > 11
template <class _Tp = void>
#else
template <class _Tp>
#endif
struct _LIBCPP_TYPE_VIS_ONLY less : binary_function<_Tp, _Tp, bool>
{
_LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
bool operator()(const _Tp& __x, const _Tp& __y) const
{return __x < __y;}
};
But my real code looks like this:
//
// MCP.cpp
// Speciale
//
// Created by Zaki G on 21/11/15.
// Copyright © 2015 Zaki G. All rights reserved.
//
#include "mcp.h"
#include <cmath>
#include <string>
#include <iomanip>
#include "Vector.h"
#include "Particle.h"
#include "Detector.h"
#include "Cave.h"
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <map>
MCP::MCP(char* name,Vector& dimension,Vector& QuartzDimension, int NumberSubQuartz, double ElectronicThickness, double Reflective_index, double z_axis_sign): Detector(name, dimension, 0)
{
MCP_Dimension = dimension;
MCP_QuartDimension = QuartzDimension;
MCP_NumberSubQuartz = NumberSubQuartz;
MCP_ElectronicThickness = ElectronicThickness;
MCP_Quartz_Reflective_index = Reflective_index;
MCP_z_axis_sign = z_axis_sign;
}
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
Vector MCP::Quartz_wall_Intersection(Detector& name, Vector &inter_front_quartz, Vector &path_photon, Vector &direction_vector, int reflection_on_off, Vector &Cherenkov_photon) //The direction vector is the vector against the normal vectors of the walls, and the Cherenkov_photon is only called to
//calculate the refelcted photon.
{ // Function for finding the intersection with the quartz walls and it can also calculated the reflected photon vector//
Vector detector_posi = name.fPosition; // The position of the detector
double Quartz_L_corner_x = detector_posi.GetX()-(0.053/2);
double Quartz_L_corner_y = detector_posi.GetY()-(0.053/2);
double Quartz_L_corner_z = detector_posi.GetZ();
Vector loop_Quartz_Lcorner = (Quartz_L_corner_x, Quartz_L_corner_y, Quartz_L_corner_z); //The position of the Quartz down left corner.
//Generating walls and roofs position for every sub MCP quartz.
int number_of_walls =int(sqrt(MCP_NumberSubQuartz)); //4+1 walls in total remember "+1"
int walls_position[number_of_walls+1];
for (int i = 0; i<=number_of_walls; i++)
{
walls_position[i] = loop_Quartz_Lcorner.GetX()+i*(0.053/sqrt(MCP_NumberSubQuartz)); // 0.053 is the length and width of the MCP Quartz
}
int number_of_roof =int(sqrt(MCP_NumberSubQuartz));
int roofs_position[number_of_roof+1];
for (int i = 0; i<=number_of_roof; i++)
{
roofs_position[i] = loop_Quartz_Lcorner.GetY()+i*(0.053/sqrt(MCP_NumberSubQuartz));
}
//loop for which section (Divided quartz) is the generated particle close to.
int en = 0;
int to = 0;
double x_array[2];
double y_array[2];
for (int i = 0; i<=number_of_walls; i++)
{
if ( abs(inter_front_quartz.GetX()) - abs(walls_position[i])<= (0.053/sqrt(MCP_NumberSubQuartz))){
x_array[en] = walls_position[i];
en =+1;
if ( abs(inter_front_quartz.GetY()) - abs(roofs_position[i]) <= (0.053/sqrt(MCP_NumberSubQuartz))){
y_array[to] = roofs_position[i];
to =+1;
}
}
}
// Defining the four point in which the particle is incapsuled within the divided quartz:
Vector position_array_one_zero = Vector(x_array[0], y_array[0], 0);
Vector position_array_one_one = Vector(x_array[0], y_array[1], 0);
Vector position_array_two_zero = Vector(x_array[1], y_array[0], 0);
Vector position_array_two_one = Vector(x_array[1], y_array[1], 0);
//Defining the four normal vectors for the incapsuled walls and roofs:
//Walls normal vector:
//Left:
Vector normal_left = (position_array_one_one-position_array_one_zero).Cross(Vector(position_array_one_zero.GetX(),position_array_one_zero.GetY(),position_array_one_zero.GetZ()-0.020)-position_array_one_zero);
//Right:
Vector normal_right = (position_array_two_one-position_array_two_zero).Cross(Vector(position_array_two_zero.GetX(),position_array_two_zero.GetY(),position_array_two_zero.GetZ()-0.020)-position_array_two_one);
//Roof normal vectors:
//Top:
Vector normal_top = (position_array_two_one-position_array_one_one).Cross(Vector(position_array_one_one.GetX(),position_array_one_one.GetY(),position_array_one_one.GetZ()-0.020)-position_array_one_one);
//Bottom:
Vector normal_bottom = (position_array_one_zero-position_array_two_zero).Cross(Vector(position_array_two_zero.GetX(),position_array_two_zero.GetY(),position_array_two_zero.GetZ()-0.020)-position_array_two_zero);
// Putting the normal vectors in a array
Vector normal_walls_roof[4]={normal_left,normal_right,normal_top,normal_bottom};
//point on the surface for every normal vector which coresponds to the each surface
map<Vector, Vector> quartz_surface_position;
quartz_surface_position[normal_walls_roof[1]] =Vector(position_array_one_zero) + Vector(0, (0.053/8), (0.020/2)*MCP_z_axis_sign ) ; //Left
quartz_surface_position[normal_walls_roof[2]] =Vector(position_array_two_zero) + Vector(0, (0.053/8), (0.020/2)*MCP_z_axis_sign ); //Right
quartz_surface_position[normal_walls_roof[3]] =Vector(position_array_one_one) + Vector((0.053/8), 0, (0.020/2)*MCP_z_axis_sign ); //Top
quartz_surface_position[normal_walls_roof[4]] =Vector(position_array_two_one) + Vector(-(0.053/8), 0, (0.020/2)*MCP_z_axis_sign );//Bottom
Vector Quartz_wall_Intersection; //The intersection point on one of the walls
Vector return_intersection_vector;
//Looping over which wall it hits
for (int i=0; i<=3; i++){
double dot_normal = direction_vector.Dot(normal_walls_roof[i]);
if (dot_normal < 10e-18)
{ //the dot product should be less than zero so the angle is stump (over 90 degree)
//The intersection point on one of the walls
Vector Quartz_wall_Intersection = path_photon-(((path_photon-quartz_surface_position[i]).Dot(normal_walls_roof[i])/dot_normal)*direction_vector);
Vector w_quartz = Quartz_wall_Intersection - quartz_surface_position[i];
// If the intersection of the plane falls outside window, return a
// NAN vector.
if (w_quartz.GetY() > name.GetHeight() || w_quartz.GetZ() > name.GetWidth())
{
return_intersection_vector = Vector(NAN,NAN,NAN);
}
else
{
if (reflection_on_off==1) //If the reflected momentum is needed:
{
// Refelction vector with in the quartz walls for the Cherenkov photons
Vector Reflection_vector_quartz = Cherenkov_photon -2.0*(Cherenkov_photon.Dot(normal_walls_roof[i]))*normal_walls_roof[i];
return_intersection_vector = Reflection_vector_quartz;
}
else
{
return_intersection_vector = Quartz_wall_Intersection;
}
}
}
}
return return_intersection_vector;
}
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
void MCP::Cherenkov_Photon_Generation(const Particle& pname, Vector &first_intersection, Vector &second_intersection, Vector pathPhoton_array[], Vector CherenkovPhoton_array[])
{
// Now we generates cherenkov photons along the particle path.//
Vector particle_momentum = pname.GetMomentum();
// The end_value is a constant, which describes the position where the particle is at the end of the quart plan.
double end_value =(second_intersection.GetX()-first_intersection.GetX())/particle_momentum.GetX();
// Generating the path for the particles where the photon should emits as Cherenkov light.
for (int n=0; n<=1000; n++) //1000 Cherenkov photons per particle
{
srand( (unsigned int) time(0) );
double random_number_d = ( double(rand()) / double(RAND_MAX))*end_value; // generate numbers between 0 and end_value.
double path_photon_x =first_intersection.GetX() + random_number_d*particle_momentum.GetX();
double path_photon_y =first_intersection.GetY() + random_number_d*particle_momentum.GetY();;
double path_photon_z =first_intersection.GetZ() + random_number_d*particle_momentum.GetZ();
Vector path_photon(path_photon_x,path_photon_y,path_photon_z);
double random_angle = (rand()/RAND_MAX)* (2*M_PI); //Generate number between 0 and 2*Pi
Vector velocity_vector = pname.GetVelocity();
double v = velocity_vector.Length();
double Cherenkov_Angle = acos((1.0)/(MCP_Quartz_Reflective_index*v));
double x = (pname.GetMomentum()).Length()*sin(Cherenkov_Angle)*cos(random_angle); //random angle is from 0-2pi
double y = (pname.GetMomentum()).Length()*sin(Cherenkov_Angle)*sin(random_angle);
double z = (pname.GetMomentum()).Length()*cos(Cherenkov_Angle);
Vector Cherenkov_photon(x,y,z);
//pathPhoton_Cherenkov_array[path_photon] = Cherenkov_photon;
pathPhoton_array[n] = path_photon;
CherenkovPhoton_array[n] = Cherenkov_photon;
}
return;
}
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
Vector MCP::MCP_end_Intersection_for_particle(const Particle& pname, Vector &particle_pos, Detector& name)
{
// Intersection with the end surface of the quartz//
// end_position is the position of the end plan of the quartz.
Vector front_quartz_position = name.fPosition;
Vector end_position(front_quartz_position.GetX(),front_quartz_position.GetY(),front_quartz_position.GetZ()+(0.020*MCP_z_axis_sign));
Vector particle_momentum = pname.GetMomentum();
Vector normal_end_quartz(0, 0, MCP_QuartDimension.GetX()*MCP_QuartDimension.GetY()*MCP_z_axis_sign);
double dot_end_quartz = particle_momentum.Dot(normal_end_quartz);
if (dot_end_quartz > 10e-18)
{
return Vector(NAN,NAN,NAN);
}
// inter_end_quartz is the intersection point on the end surface of the quartz
Vector inter_end_quartz = particle_pos-(((particle_pos-end_position).Dot(normal_end_quartz)/dot_end_quartz)*particle_momentum);
Vector w_end_quartz = inter_end_quartz - end_position;
// If the intersection of the plane falls outside window, return a
// Zero vector.
if (w_end_quartz.GetX() > MCP_QuartDimension.GetX() || w_end_quartz.GetY() > MCP_QuartDimension.GetY())
{
return Vector(NAN,NAN,NAN);
}
return inter_end_quartz;
}
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
Vector MCP::MCP_end_Intersection_for_Photon(Vector &Photon_momentum, Vector &particle_pos, Detector& name)
{
// Intersection with the end surface of the quartz//
// end_position is the position of the end plan of the quartz.
Vector front_quartz_position = name.fPosition;
Vector end_position(front_quartz_position.GetX(),front_quartz_position.GetY(),front_quartz_position.GetZ()+(0.020*MCP_z_axis_sign));
Vector normal_end_quartz(0, 0, MCP_QuartDimension.GetX()*MCP_QuartDimension.GetY()*MCP_z_axis_sign);
double dot_end_quartz = Photon_momentum.Dot(normal_end_quartz);
if (dot_end_quartz > 10e-18)
{
return Vector(NAN,NAN,NAN);
}
// inter_end_quartz is the intersection point on the end surface of the quartz
Vector inter_end_quartz = particle_pos-(((particle_pos-end_position).Dot(normal_end_quartz)/dot_end_quartz)*Photon_momentum);
Vector w_end_quartz = inter_end_quartz - end_position;
// If the intersection of the plane falls outside window, return a
// Zero vector.
if (w_end_quartz.GetX() > MCP_QuartDimension.GetX() || w_end_quartz.GetY() > MCP_QuartDimension.GetY())
{
return Vector(NAN,NAN,NAN);
}
return inter_end_quartz;
}
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
void MCP::MCP_Intersection(const Particle& pname, Vector &particle_pos, Detector& name, Vector intersection_array[], int array_size)
{
//Intersection with the front surface of the MCP which is the quartz.//
Vector particle_momentum = pname.GetMomentum(); //Momentum of the particle
Vector front_quartz_position = name.fPosition; // position of the MCP on the FIT (Husk nedeunder MCP flad position)
Vector normal_front_quartz(0,0,MCP_QuartDimension.GetY()*MCP_QuartDimension.GetX());
double dot_front_quartz = particle_momentum.Dot(normal_front_quartz);
if (dot_front_quartz > 10e-18)
{
//return Vector(NAN, NAN, NAN);
}
// inter_front_quartz is the intersection point on the quartz
Vector inter_front_quartz = particle_pos-(((particle_pos-front_quartz_position).Dot(normal_front_quartz)/dot_front_quartz)*particle_momentum);
Vector w = inter_front_quartz - front_quartz_position;
// If the intersection of the plane falls outside window, return a
// Zero vector.
if (w.GetX() > name.GetHeight() || w.GetY() > name.GetWidth())
{
//return Vector(NAN,NAN,NAN);
}
//---------------------------------------------------------------------
// Intersection with the end surface of the quartz//
// end_position is the position of the end plan of the quartz. ---------.men hvad med protonen flyver den videre igennem MCP?!!!
Vector end_position(front_quartz_position.GetX(),front_quartz_position.GetY(),front_quartz_position.GetZ()+(0.020*MCP_z_axis_sign));
Vector normal_end_quartz(0, 0, MCP_QuartDimension.GetX()*MCP_QuartDimension.GetY()*MCP_z_axis_sign);
double dot_end_quartz = particle_momentum.Dot(normal_end_quartz);
if (dot_end_quartz > 10e-18) // If it does not intersect with the end panel, then it must intersect with the walls of the MCP.
{
//Here I find the wall intersection
Vector zero_vector(NAN,NAN,NAN);
Vector particle_intersection_with_wall = Quartz_wall_Intersection(name, inter_front_quartz, particle_pos , particle_momentum, 0 , zero_vector);
//Defining the two arrays for path of the photons and the cherenkov photon vector:
Vector pathPhoton_array[1000];
Vector CherenkovPhoton_array[1000];
Cherenkov_Photon_Generation(pname, inter_front_quartz, particle_intersection_with_wall, pathPhoton_array, CherenkovPhoton_array);
//slette Vector array_path_cherenkov_photon = Cherenkov_Photon_Generation(pname, inter_front_quartz, particle_intersection_with_wall);
static Vector intersection_array[1000];
//Here it finds out that the photon intersect with the walls or not.
for (int i = 0; i <= sizeof(pathPhoton_array); i++)
{
Vector photon_intersection_with_wall = Quartz_wall_Intersection(name, inter_front_quartz, pathPhoton_array[i] , CherenkovPhoton_array[i], 0, zero_vector);
if (photon_intersection_with_wall.GetX() != zero_vector.GetX()) //If the photon interc. with the wall:
{
// Here the reflected photon is found:
Vector reflected_photon = Quartz_wall_Intersection(name, inter_front_quartz, pathPhoton_array[i] , CherenkovPhoton_array[i], 1, CherenkovPhoton_array[i]);
//The reflected photon is intersected with MCP
Vector intersection_with_end_MCP = MCP_end_Intersection_for_Photon(reflected_photon, photon_intersection_with_wall, name);
intersection_array[i] = intersection_with_end_MCP;
//return Intersection; // tænk lige over det
}
else // If the photon do not intersect with the wall then:
{
Vector intersection_with_end_MCP = MCP_end_Intersection_for_Photon(CherenkovPhoton_array[i], pathPhoton_array[i], name);
//Intersection[] = intersection_with_end_MCP;
intersection_array[i] = intersection_with_end_MCP;
//return Intersection; // tænk lige over det
}
}
}
//The particle intersection with the MCP directly
Vector intersection_with_end_MCP = MCP_end_Intersection_for_particle(pname, particle_pos, name);
//Intersection[] = intersection_with_end_MCP;
//Generate Cherenkov photon in 2D array
Vector pathPhoton_array[1000] = {};
Vector CherenkovPhoton_array[1000] = {};
Cherenkov_Photon_Generation(pname, inter_front_quartz, intersection_with_end_MCP, pathPhoton_array, CherenkovPhoton_array);
Vector zero_vector(NAN,NAN,NAN);
for (int i = 0; i <= sizeof(CherenkovPhoton_array); i++)
{
Vector photon_intersection_with_wall = Quartz_wall_Intersection(name, inter_front_quartz, pathPhoton_array[i], CherenkovPhoton_array[i], 0, zero_vector);
if (photon_intersection_with_wall.GetX()!= NAN) //If the photon interc. with the wall:
{
// Here the reflected photon is found:
Vector reflected_photon = Quartz_wall_Intersection(name, inter_front_quartz, pathPhoton_array[i] , CherenkovPhoton_array[i], 1, CherenkovPhoton_array[i]);
//The reflected photon is intersected with MCP
Vector intersection_with_end_MCP = MCP_end_Intersection_for_Photon(reflected_photon, photon_intersection_with_wall, name);
intersection_array[i] = intersection_with_end_MCP;
}
else
{
Vector intersection_with_end_MCP = MCP_end_Intersection_for_Photon(CherenkovPhoton_array[i], pathPhoton_array[i], name);
intersection_array[i] = intersection_with_end_MCP;
}
}
}
Hope someone can figure this out.
#ifndef _VECTOR_H
#define _VECTOR_H
//class ostream;
using namespace std;
class Vector
{
private:
double fX;
double fY;
double fZ;
public:
Vector(double x=0, double y=0, double z=0);
double Length(void) const;
void SetX(double x) { fX= x; }
void SetY(double y) { fY= y; }
void SetZ(double z) { fZ= z; }
double GetX(void) const { return fX; }
double GetY(void) const { return fY; }
double GetZ(void) const { return fZ; }
Vector Cross(const Vector& v) const;
double Dot(const Vector& v) const;
Vector operator+(const Vector& v);
Vector operator-(const Vector& v);
Vector operator=(const Vector& v);
bool operator() (const Vector& lhs, const Vector& rhs) const
{
return (lhs.GetX(),lhs.GetY(),lhs.GetZ()) < (rhs.GetX(),rhs.GetY(),rhs.GetZ());
}
}
;
// Global functions
Vector operator*(const double a, const Vector& v);
Vector operator*(const Vector& v, const Vector& u);
std::ostream& operator<<(std::ostream& o, const Vector& v);
#endif
The problem, as pointed out in the last comment, is map<Vector, Vector>. This is a sorted associative container. Its Key is a Vector, and the default order is std::less<Vector>. The compiler duly instantiates std::less<Vector>, finds no specializations, and fails on <. You'll need to provide one, but it can be simple: return std::tie(r.x, r.y, r.z) < std::tie(l.x, l.y, l.z).
PS. normal_walls_roof[] runs from [0] to [3], not [1] to [4].

Why doesn't this polygon clipping code give desired result?

This is my implementation of Sutherland-Hodgman Polygon Clipping Algorithm.
I am trying to clip a Positively Oriented and Convex polygon with a rectangular clipping area.
I am using BGI library from colorado university. I am using OS=Win7. Visual C++ 2008 Express.
This program isn't working correctly.
//Sutherland-Holdgman Line Clipping
#include "Line2d.h"
#include "Rectangle2d.h"
#include "Coordinates2d.h"
#include "Bits.h"
#include "Polygon2d.h"
#include <list>
typedef enum PointPosition
{
Left, Right
} PointPosition;
typedef enum LinePosition
{
CompletelyOut, CompletelyIn, ClippingCandidate, ClippingCandidateExtended
} LinePosition;
class ClippingPolygon2d
{
private:
Rectangle2d rectangle;
Polygon2d polygon;
public:
ClippingPolygon2d(){}
//ClippingPolygon2d(Rectangle2d & rectangle, Polygon2d & polygon): rectangle(rectangle), polygon(polygon){}
void SetCandidatePolygon(Polygon2d & pol)
{
polygon = pol;
}
void SetClippingPolygon(Rectangle2d & rect)
{
rectangle = rect;
}
public:
std::vector<Point2d> GetClippedPoints()
{
std::vector<Point2d> vertexList = polygon.GetVertices();
std::vector<Point2d> clipping = rectangle.GetVertices();
for (size_t i = 0; i < clipping.size(); i++)
{
//obtaining one vertex and the next one from the clipping region.
//Then, constructing a line from them.
Line2d clippingEdge(clipping[i], clipping[(i + 1) % clipping.size()]);
std::vector<Point2d> temp;
for (size_t j = 0; j < vertexList.size(); j++)
{
Point2d polygonEdgeStart = vertexList[j];
Point2d polygonEdgeEnd = vertexList[(j + 1) % vertexList.size()];
if (clippingEdge.onLeft(polygonEdgeStart))
{
if (clippingEdge.onLeft(polygonEdgeEnd))
{
// point on the left, just add to vertexList
temp.push_back(polygonEdgeEnd);
}
else //Right
{
// calculate intersection I and add it to vertexList
temp.push_back(clippingEdge.GetIntersection(Line2d(polygonEdgeStart, polygonEdgeEnd)));
}
}
else //Right
{
if (clippingEdge.onLeft(polygonEdgeEnd))
{
//calculate intersection I and add I and polygonEdgeEnd to vertexList
temp.push_back(clippingEdge.GetIntersection(Line2d(polygonEdgeStart, polygonEdgeEnd)));
temp.push_back(polygonEdgeEnd);
}
else //Right
{
// nothing to do: outside of the window
}
}
}
vertexList = temp;
}
return vertexList;
}
};
int main()
{
//////////////////////// Initialize ///////////////////////
Coordinates2d::ShowWindow("Sutherland-Hodgeman Line Clipping");
///////////////////////////////////////////////////////////////
Rectangle2d rectangle(Point2d(20, 20), Point2d(200, 140));
Polygon2d polygon;
polygon.Add(Point2d(30, 40));
polygon.Add(Point2d(110,40));
polygon.Add(Point2d(130,110));
polygon.Add(Point2d(70,150));
polygon.Add(Point2d(10,110));
ClippingPolygon2d clip;
clip.SetClippingPolygon(rectangle);
clip.SetCandidatePolygon(polygon);
std::vector<Point2d> clippedVerticesList = clip.GetClippedPoints();
Coordinates2d::Draw(polygon, Red);
Coordinates2d::Draw(rectangle, Magenta);
Coordinates2d::Draw(clippedVerticesList, Thick, Yellow);
//////////////////////// Draw /////////////////////////
Coordinates2d::Wait(); return 0;
///////////////////////////////////////////////////////////////
}
double Line2d :: orientationOf(Point2d & point)
{
return (end.x - start.x) * (point.y - start.y) - (end.y - start.y) * (point.x - start.x);
}
bool Line2d :: onRight(Point2d & point)
{
return orientationOf(point) < -E; //for precision reason
}
bool Line2d :: onLeft(Point2d & point)
{
return orientationOf(point) > E;//for precision reason
}
I found at least 2 problems in GetClippedPoints function:
you use if(i) - it's not right because i iterates on windows edges. I think that you suppose to use if(j).
supposed that for(size_t i=0 ; i<clippingRegionLines.size() ; i++) should transform (generate new) vertexList (initially vertexList==allPolygonVertexes) and use it in next step. (so after all iterations of this loop you will get clipped polygon). So my advice here: represent input polygon as list of vertexes instead of list of edges.
Also you need to be sure that std::vector<Line2d> clippingRegionLines = rectangle.GetLines(); returns segments oriented counter-clockwise.

sfml ship not wrapping at the window end

Well friends, I have returned here to try and get a little help once again. The issue is this, the ship on build doesn't wrap. That is to say it doesn't reappear on the other side of the window when it goes past the windows limit. The function called setmaxLocations() is being very strange. It erases the ship, or doesn't set the max location. So here is my code. Bear with me, this is a large project. If I messed up the format just let me know, I check often so it'll get fixed close to when you tell me.
main implementation cpp:
#include <SFML/Graphics.hpp>
#include "ship.h"
const int WINDOW_WIDTH = 700;
const int WINDOW_HEIGHT = 700;
//==============================================================================
int main()
{
Ship ship;
sf::RenderWindow window( sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT),
"Delta Quadrant", sf::Style::Titlebar | sf::Style::Close);
window.setFramerateLimit(120);
// this causes loop to execute 120 times a second at most.
// (a delay is automatically added after screen is drawn)
//set's the limit on the ship's location to the window dimensions;
ship.setmaxLocations(WINDOW_WIDTH, WINDOW_HEIGHT);
//sets position of the ship in the middle of the screen
ship.setLocation(WINDOW_WIDTH/2, WINDOW_HEIGHT/2);
while (window.isOpen())
{
//----------------------------------------------------------
//handle user input (events and keyboard keys being pressed)
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed)
window.close();
}
//turn left with press of left button
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
ship.rotateLeft();
//turn right with press of right button
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
ship.rotateRight();
//apply thrust with press of up button
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
ship.applyThrust();
//----------------------------------------------------------
//draw new frame
window.clear();
//draw ship
ship.updateLocation();
ship.draw(window);
//redisplay window
window.display();
}
return 0;
}
SpaceObject header:
#ifndef SPACE_OBJECT_H
#define SPACE_OBJECT_H
#include "vector.h"
class SpaceObject {
private:
Vector maxLocations; //maximum allowable values for location
Vector location; //current location (x,y)
Vector velocity; //current velocity (in pixels/frame)
double angleDeg; //angle ship is facing, in degrees
double radius; //gross radius (for collision detection)
public:
SpaceObject();
//--------------------------------------------
//mutators
void setLocation(double x, double y);
void setVelocity(double velocityX, double velocityY);
void setAngle(double angDeg);
void setRadius(double radius);
//--------------------------------------------
//accessors
Vector getLocation();
Vector getVelocity();
double getAngle();
double getRadius();
//--------------------------------------------
//others
void updateLocation();
void setmaxLocations(double x, double y);
};
#endif
SpaceObject source file:
#include<cmath>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include"vector.h"
#include "SpaceObject.h"
//constructor
SpaceObject::SpaceObject() {
maxLocations.x = 500;
maxLocations.y = 500;
radius = 5;
location.x = 0;
location.y = 0;
velocity.x = 0;
velocity.y = 0;
angleDeg = 0;
}
//================================================================
//mutators
//================================================================
// Function: setLocation
//
// Description: Sets the x and y values of the SpaceObject's location
// Argument list:
// x(I) - x coordinate for SpaceObject's location
// y(I) - y coordinate for SpaceObject's location
//=================================================================*/
void SpaceObject::setLocation(double x, double y){
//Check and correct for the SpaceObject going out of bounds.
if (x < 0)
location.x += maxLocations.x;
else if (x > maxLocations.x)
location.x -= maxLocations.x;
else
location.x = x;
if (y < 0)
location.y += maxLocations.y;
else if (y > maxLocations.y)
location.y -= maxLocations.y;
else
location.y = y;
}
//================================================================
// Function: setVelocity
//
// Description: Sets the velocity for the x and y direction of the SpaceObject
// Argument list:
// velocityX(I) - sets the velocity in the x direction
// velocityY(I) - sets the velocity in the y direction
//=================================================================
void SpaceObject::setVelocity(double velocityX, double velocityY){
velocity.x = velocityX;
velocity.y = velocityY;
}
//================================================================
// Function: setLocation
//
// Description: Sets the directional angle of the SpaceObject
// Argument List:
// angDeg(I) - sets the SpaceObjects angle
//=================================================================*/
void SpaceObject::setAngle(double angDeg){
while (angDeg >= 360)
angDeg -= 360;
while (angDeg < 0)
angDeg += 360;
angleDeg = angDeg;
}
//================================================================
//accessors
//================================================================
// Function: getRadius
// Description: Returns the Radius
//
// Return value:
// Radius - the SpaceObjects turning axis
//=================================================================*/
double SpaceObject::getRadius(){
return radius;
}
//================================================================
// Function: getLocation
// Description: Returns the x and y values of the SpaceObjects location
//
// Return value:
// location - the location of the SpaceObject
//=================================================================*/
Vector SpaceObject::getLocation(){
return location;
}
//================================================================
// Function: getVelocity
// Description: Returns the x and y values of the SpaceObjects directional velocity
//
// Return value:
// Velocity
//=================================================================*/
Vector SpaceObject::getVelocity(){
return velocity;
}
//================================================================
// Function: getAngle
// Description: returns the angle
//
// Return value:
// Angle - the SpaceObjects direction
//=================================================================*/
double SpaceObject::getAngle(){
return angleDeg;
}
//============================================
//other functions
//================================================================
// Function: setmaxLocations
//
// Description: Sets the x and y values of the SpaceObject's max possible area of movement
// Argument list:
// x(I) - max width of SpaceObject's possible positions
// y(I) - max heigth of SpaceObject's possible positions
//=================================================================*/
void SpaceObject::setmaxLocations(double x, double y){
maxLocations.x = x;
maxLocations.y = y;
}
//================================================================
// Function: updateLocations
//
// Description: Sets the x and y values of the SpaceObject's location while including the change with velocity
//=================================================================*/
void SpaceObject::updateLocation(){
location.x = location.x + velocity.x;
location.y = location.y + velocity.y;
}
ship header file:
#ifndef SHIP_H
#define SHIP_H
#include "SpaceObject.h"
class Ship: public SpaceObject {
public:
Ship();
void rotateLeft();
void rotateRight();
void applyThrust();
void draw(sf::RenderWindow& win);
};
#endif
ship source file:
#include<cmath>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include"vector.h"
#include "ship.h"
//Constants
const double PI = 3.14159;
const double THRUST = 0.005;
const double TURN_SPEED = 1;
Ship::Ship() {
}
//============================================
//other functions
//================================================================
// Function: rotateLeft
//
// Description: turns the ship left by subtracting from the ship's angle
//=================================================================*/
void Ship::rotateLeft(){
int newAngle;
newAngle = getAngle() - TURN_SPEED;
setAngle(newAngle);
}
//================================================================
// Function: rotateRight
//
// Description: turns the ship Right by adding to the ship's angle
//=================================================================*/
void Ship::rotateRight(){
int newAngle;
newAngle = getAngle() + TURN_SPEED;
setAngle(newAngle);
}
//================================================================
// Function: applyThrust
//
// Description: Sets the x and y value of the ship's movement
//=================================================================*/
void Ship::applyThrust(){
double forcex = cos((getAngle()-90)*PI/180) * .005;
double forcey = sin((getAngle()-90)*PI/180) * .005;
setVelocity(getVelocity().x + forcex, getVelocity().y + forcey);
}
//--------------------------------------------------------------------------
// Function: draw
// Description: draws the ship on the given window
// Parameters:
// win - the window for drawing the ship
//--------------------------------------------------------------------------
void Ship::draw(sf::RenderWindow& win) {
// draw ship
sf::ConvexShape ship;
ship.setPointCount(3);
ship.setPoint(0, sf::Vector2f(10, 0));
ship.setPoint(1, sf::Vector2f(0, 25));
ship.setPoint(2, sf::Vector2f(20, 25));
sf::Vector2f midpoint(10,15);
ship.setOrigin(midpoint);
ship.setFillColor(sf::Color(0, 0, 0));
ship.setOutlineThickness(1);
ship.setOutlineColor(sf::Color(255, 255, 255));
ship.setPosition(getLocation().x, getLocation().y);
ship.setRotation(getAngle());
win.draw(ship);
}
vector header file (just for clarity):
#ifndef VECTOR_H
#define VECTOR_H
struct Vector{
float x;
float y;
};
#endif
It seems that SpaceObject::setLocation() does the actual checking to see if the ship is in bounds, yet this function is only called once at the beginning of your main(). It needs to be called within the loop so it can continually check that the ship has a valid location. I would recommend calling it within SpaceObject::updateLocation()

firework opengl

I'm trying to create a firework with OpenGL (I must put 100 particles in the position (0,0,0)) with the function
Particle *p[100];
void Build()
{
for (int i = 1; i <= 100; i++)
{
p[i]->pos.x = 0.0;
p[i]->pos.y = 1.0;
p[i]->pos.z = 5.0;
p[i]=AddParticle(*p[i]);
}
}
but I get the following error:
Unhandled exception at 0x771b15de in ass.exe: 0xC0000005: Access violation writing location 0x00000000.
this is the rest of the code:
class Particle
{
public:
Vector3 pos; // current position
Vector3 vel; // velocity
Vector3 restPos; // rest (initial) position
Vector3 oldPos; // previous position
Vector3 acc; // acceleration
Particle()
{
oldPos = restPos = pos = Vector3(0, 0, 0);
Init();
}
Particle(float x, float y, float z)
{
oldPos = restPos = pos = Vector3(x, y, z);
Init();
}
Particle(const Vector3 & _p)
{
oldPos = restPos = pos = _p;
Init();
}
void Init()
{
acc = Vector3(0, 0, 0);
vel = Vector3(0, 0, 0);
}
void Update(const float & time_step)
{
Verlet(time_step);
}
// integration step with Verlet
void Verlet(const float & time_step)
{
Vector3 temp = pos;
pos += vel * time_step + acc * time_step * time_step ;
vel = (temp - oldPos) / time_step;
oldPos = temp;
}
};
# endif // _PARTICLE__
using namespace std;
class ParticleSystem
{
vector<Particle> _particles; // the particles
Vector3 m_vGravity; // gravity force applied to the particles system
float m_fTimeStep; // time step
Vector3 attractor;
public:
ParticleSystem()
{
m_vGravity = Vector3(0, -9.81f, 0);
m_fTimeStep = TIME_STEP;
attractor = Vector3(0, 0, 0);
}
void Reset()
{
_particles.clear();
}
// accessing the fields
void SetGravity(Vector3 g) { m_vGravity = g;}
void SetTimeStep(float ts) { m_fTimeStep = ts;}
// adding a particle
Particle* AddParticle(Particle _p)
{
_particles.push_back(_p);
return &(_particles.back());
}
void Build()
{
for (int i = 1; i <= 100; i++)
{
Particle p;
p.pos.x = 0.0;
p.pos.y = 1.0;
p.pos.z = 5.0;
p[i]=AddParticle(p);
}
}
void Draw()
{
// draw round points
glPointSize(4.f);
glEnable(GL_POINT_SMOOTH);
glAlphaFunc(GL_GREATER,0.5f);
glEnable(GL_ALPHA_TEST);
glEnable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
// draws the particles
glBegin(GL_POINTS);
glColor3f(1.f, 0.f, 0.f);
vector<Particle>::iterator pIt;
for(pIt = _particles.begin(); pIt != _particles.end(); pIt++)
{
Vector3& pos = pIt->pos;
glVertex3f(pos.x, pos.y, pos.z);
}
glEnd();
glEnable(GL_LIGHTING);
}
#endif // __PARTICLE_SYSTEM__
You've declared an array of pointers to Particles, but not actually allocated any of them.
(and as someone else points out, arrays are 0 indexed, not 1 - so your loop is out by 1 anyway)
It's not entirely clear how this is supposed to work, as you seem to be filling in a particle structure, which you pass to AddParticle(), which returns a pointer to a particle, which you put back in the array you've already tried to reference.
Looking at your code, you probably just need something like:
void Build()
{
for (int i = 1; i <= 100; i++)
{
AddParticle(Particle(0.f, 1.f, 5.f));
}
}
No array needed as the particle class looks after the particles.
i think it's because the array goes from 0 to 99...not 1 to 100 .
Change the for statement to for (int i = 0; i < 100; i++) and remember the array starts with a 0
Also i think i know what you're trying to do..try this code:
void Build()
{
Particle p[100];
for (int i = 0; i < 100; i++)
{
p[i].pos.x = 0.0;
p[i].pos.y = 1.0;
p[i].pos.z = 5.0;
AddParticle(p[i]);
}
}