firework opengl - c++

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]);
}
}

Related

Error due to improper implementation of classes in C++

I wrote the following program, and have reached the following code finally as per my understanding. There
still seem to be a host of errors like:
identifier "lambertian" is undefinedC/C++ in text editor -for lambertian in auto material_ground = make_shared<lambertian>(color(0.8, 0.8, 0.0));
2) pointer to incomplete class type "material" is not allowed - for rec in
if (rec.mat_ptr->scatter(r, rec, attenuation, scattered)) in editor
I'm also facing multiple errors in compilation like:
vec3.h: In member function 'vec3 vec3::reflect(const vec3&, const vec3&)': vec3.h:61:33: error: 'dot' was not declared in this scope return v - 2*dot(v,n)*n;
invalid use of incomplete type 'class hittable_list' class hittable_list : public hittable_list
sphere.h:7:7: note: candidate expects 1 argument, 2 provided sphere.h:7:7: note: candidate: sphere::sphere(sphere&&)
And I think I've most probably implemented classes improperly so, is there any resource that would help me avoid such errors in the near future?
Code:
chap_8.cpp:
#include "camera.h"
#include "rtweekend.h"
#include "vec3.h"
#include "color.h"
#include "hittablelist.h"
#include "sphere.h"
#include "ray.h"
#include <iostream>
#include <fstream>
#include "material.h"
#include "hittable.h"
color ray_color(const ray& r, const hittable_list& world, int depth) {
hit_record rec;
// If we've exceeded the ray bounce limit, no more light is gathered.
if (depth <= 0)
return color(0,0,0);
if (world.hit(r, 0.001, infinity, rec)) {
ray scattered;
color attenuation;
if (rec.mat_ptr->scatter(r, rec, attenuation, scattered))
return attenuation * ray_color(scattered, world, depth-1);
return color(0,0,0);
}
vec3 unit_direction = unit_vector(r.direction());
auto t = 0.5*(unit_direction.y() + 1.0);
return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0);
}
int main() {
// Image
const auto aspect_ratio = 16.0 / 9.0;
const int image_width = 400;
const int image_height = static_cast<int>(image_width / aspect_ratio);
const int samples_per_pixel = 100;
const int max_depth = 50;
// World
hittable_list world;
auto material_ground = make_shared<lambertian>(color(0.8, 0.8, 0.0));
auto material_center = make_shared<lambertian>(color(0.7, 0.3, 0.3));
auto material_left = make_shared<metal>(color(0.8, 0.8, 0.8), 0.3);
auto material_right = make_shared<metal>(color(0.8, 0.6, 0.2), 1.0);
world.add(make_shared<sphere>(point3( 0.0, -100.5, -1.0), 100.0, material_ground));
world.add(make_shared<sphere>(point3( 0.0, 0.0, -1.0), 0.5, material_center));
world.add(make_shared<sphere>(point3(-1.0, 0.0, -1.0), 0.5, material_left));
world.add(make_shared<sphere>(point3( 1.0, 0.0, -1.0), 0.5, material_right));
// Camera
camera cam;
// Render
std::cout << "P3\n" << image_width << " " << image_height << "\n255\n";
for (int j = image_height-1; j >= 0; --j) {
std::cerr << "\rScanlines remaining: " << j << ' ' << std::flush;
for (int i = 0; i < image_width; ++i) {
color pixel_color(0, 0, 0);
for (int s = 0; s < samples_per_pixel; ++s) {
auto u = (i + random_double()) / (image_width-1);
auto v = (j + random_double()) / (image_height-1);
ray r = cam.get_ray(u, v);
pixel_color += ray_color(r, world, max_depth);
}
write_color(std::cout, pixel_color, samples_per_pixel);
}
}
std::cerr << "\nDone.\n";
}
hittablelist.h
#ifndef HITTABLE_LIST_H
#define HITTABLE_LIST_H
#include "hittable.h"
#include <memory>
#include <vector>
using std::shared_ptr;
using std::make_shared;
class hittable_list : public hittable_list {
public:
hittable_list() {}
hittable_list(shared_ptr<hittable_list> object) { add(object); }
void clear() { objects.clear(); }
void add(shared_ptr<hittable_list> object) { objects.push_back(object); }
virtual bool hit(
const ray& r, double t_min, double t_max, hit_record& rec) const override;
public:
std::vector<shared_ptr<hittable_list>> objects;
};
bool hittable_list::hit(const ray& r, double t_min, double t_max, hit_record& rec) const {
hit_record temp_rec;
bool hit_anything = false;
auto closest_so_far = t_max;
for (const auto& object : objects) {
if (object->hit(r, t_min, closest_so_far, temp_rec)) {
hit_anything = true;
closest_so_far = temp_rec.t;
rec = temp_rec;
}
}
return hit_anything;
}
#endif
sphere.h
#ifndef SPHERE_H
#define SPHERE_H
#include "hittable.h"
#include "vec3.h"
class sphere : public hittable_list {
public:
sphere() {}
sphere(point3 cen, double r, shared_ptr<material> m)
: center(cen), radius(r), mat_ptr(m) {};
virtual bool hit(
const ray& r, double t_min, double t_max, hit_record& rec) const override;
public:
point3 center;
double radius;
shared_ptr<material> mat_ptr;
};
bool sphere::hit(const ray& r, double t_min, double t_max, hit_record& rec) const {
vec3 oc = r.origin() - center;
auto a = r.direction().length_squared();
auto half_b = dot(oc, r.direction());
auto c = oc.length_squared() - radius*radius;
auto discriminant = half_b*half_b - a*c;
if (discriminant < 0) return false;
auto sqrtd = sqrt(discriminant);
// Find the nearest root that lies in the acceptable range.
auto root = (-half_b - sqrtd) / a;
if (root < t_min || t_max < root) {
root = (-half_b + sqrtd) / a;
if (root < t_min || t_max < root)
return false;
}
rec.t = root;
rec.p = r.at(rec.t);
vec3 outward_normal = (rec.p - center) / radius;
rec.set_face_normal(r, outward_normal);
rec.mat_ptr = mat_ptr;
return true;
}
#endif

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.

C++ & SFML Separating Axis Theorem

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;
}

Why does my vector of pointers keep on resulting in a EXC_BAD_ACCESS?

I am attempting to create a graphical representation of finite automata using xcode, and as such I have created classes for states and transitions. In order to make moving objects easy, I have included a collection of pointers of transitions going in and out of the state. Compiling is fines, but when I try to append to the vector, it produces the following error. EXC_BAD_ACCESS(code=1, address=0x3f35)
Following the error takes me to the std library, and shows the error being in this line.
template <class _Tp, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY
void
vector<_Tp, _Allocator>::push_back(const_reference __x)
{
if (this->__end_ != this->__end_cap())
{
__annotate_increase(1);
__alloc_traits::construct(this->__alloc(),
_VSTD::__to_raw_pointer(this->__end_), __x);
++this->__end_;
}
else
__push_back_slow_path(__x);
}
Here is a simplified version of my State class, my Transition class is declared before and is then defined afterwards.
class State
{
int id;
std::vector<Transition *> links_in;
std::vector<Transition *> links_out;
float x;
float y;
int r = radius; //x, y are centre coordinates of the circle representing the state, while r is the radius
bool is_active = false;
bool is_end = false;
bool is_shown = true;
bool is_moving;
public:
// Get Functions go here
// Set Functions go here
//Add functions
void add_in_trans(Transition * t){
links_in.push_back(t);
}
void add_out_trans(Transition * t){
links_out.push_back(t);
}
//Delete Functions
void remove_in_trans(){
links_in.pop_back();
}
void remove_out_trans(){
links_out.pop_back();
}
void draw_state();
State(int ix, int iy);
State(){}
}
If you have any suggestions for a better way of doing this, I am more then happy to hear them. I have spent all day trying to sort this out, to no avail.
Thanks in advance.
UPDATE:
I attempted to use integers and vectors as a temporary fix, but I came up with the same problem, so I assume that the problem isn't the pointers but the way I'm using vectors.
This is the code
#include <vector>
class Transition;
class State
{
int id;
std::vector<int> links_in;
std::vector<int> links_out;
float x;
float y;
int r = radius; //x, y are centre coordinates of the circle representing the state, while r is the radius
bool is_active = false;
bool is_end = false;
bool is_shown = true;
bool is_moving;
public:
// Get Functions
int get_x(){
return x;
}
int get_y(){
return y;
}
int get_id(){
return id;
}
bool is_it_active(){
return is_active;
}
bool is_it_moving(){
return is_moving;
}
bool is_in(int ix, int iy){ //Function to tell if pair of coordinates are in the circle, used to select.
std::cerr << ix-x << " " << iy-y << " " << r*r << std::endl;
if ((ix-x)*(ix-x) + (iy-y)*(iy-y) < r*r)
return true;
else
return false;
}
// Set Functions
void set_active(bool s){
is_active = s;
}
void set_moving(bool s){
is_moving = s;
}
void end_switch(){
is_end = !is_end;
}
void set_start(){
g_start_state = id;
}
void set_x(int ix){
x = ix;
}
void set_y(int iy){
y = iy;
}
//Add functions
void add_in_trans(int t){
links_in.push_back(t);
}
void add_out_trans(int t){
links_out.push_back(t);
}
//Delete Functions
void remove_in_trans(){
links_in.pop_back();
}
void remove_out_trans(){
links_out.pop_back();
}
void draw_state();
State(int ix, int iy);
State(){}
};
State::State(int ix, int iy){
id = g_state_num;
if (g_start_state == 0)
g_start_state = id;
x = ix;
y = iy;
}
void State::draw_state(){
if (is_shown){
if (is_moving)
glTranslatef(g_cursor_x, g_cursor_y, 0.0);
else
glTranslatef(x, y, 0.0);
fill_colour();
if (is_active)
active_fill_colour();
glBegin(GL_POLYGON);
for (size_t i=0; i<24; i++){
float n[2] = {static_cast<float>(r * cos(i*6)), static_cast<float>(r * sin(i*6))};
glVertex2fv(n);
}
glEnd();
line_colour();
glBegin(GL_LINES);
for (size_t i=0; i<24; i++){
float n[2] = {static_cast<float>(r * cos(i*6)), static_cast<float>(r * sin(i*6))};
glVertex2fv(n);
}
glEnd();
if(is_end){
glPushMatrix();
glScalef(0.9, 0.9, 0.9);
for (size_t i=0; i<24; i++){
float n[2] = {static_cast<float>(r * cos(i*6)), static_cast<float>(r * sin(i*6))};
glVertex2fv(n);
}
glPopMatrix();
}
text_colour();
std::string s = std::to_string(id);
for (int i=0; i<s.length(); i++){
glPushMatrix();
glTranslatef(-radius/2 + i*kerning, -radius/2, 0.0);
glScalef(0.3, 0.3, 1.0);
glutStrokeCharacter(GLUT_STROKE_ROMAN, s[i]);
glPopMatrix();
}
}
}
class Character{
int id;
char c;
public:
int get_id(){
return id;
}
char get_char(){
return c;
}
void set_char(char ic){
c = ic;
}
Character(char ic);
Character(){};
};
Character::Character(char ic){
id = g_character_num;
g_character_num++;
c = ic;
}
class Transition{
int ident;
State * from_state;
State * to_state;
float from[2];
float to[2];
Character c;
public:
void set_from(float x, float y){
from[0] = x;
from[1] = y;
}
void set_to(float x, float y){
to[0] = x;
to[1] = y;
}
void set_char(Character ic){
c = ic;
}
int get_id(){
return ident;
}
void draw_trans();
void set_trans(State * ifrom, State * ito, Character ic){
from_state = ifrom;
to_state = ito;
from[0] = ifrom->get_x();
from[1] = ifrom->get_y();
to[0] = ito->get_x();
to[1] = ito->get_y();
c = ic;
}
Transition(){};
Transition(State ifrom, State ito, Character ic){
from_state = &ifrom;
to_state = &ito;
from[0] = ifrom.get_x();
from[1] = ifrom.get_y();
to[0] = ito.get_x();
to[1] = ito.get_y();
c = ic;
}
};
void Transition::draw_trans(){
line_colour();
glBegin(GL_LINES);
glVertex2fv(from);
glVertex2fv(to);
glEnd();
float grad = (from[0] - to[0]) /(from[1] - to[1]); //(By finding the gradient of the slope, we can fin good place to show it's information, it's character.
if (grad < -1 || grad > 1){
glPushMatrix();
glTranslatef(from[0] - to[0] - 20, from[1] - to[1], 1.0);
}
else{
glPushMatrix();
glTranslatef(from[0] - to[0], from[1] - to[1] + 20, 1.0);
}
glutStrokeCharacter(GLUT_STROKE_ROMAN, (c.get_char()));
glPopMatrix();
}

Help understanding some OpenGL stuff

I am working with some code to create a triangle that moves with arrow keys. I want to create a second object that moves independently. This is where I am having trouble, I have created the second actor, but cannot get it to move. There is too much code to post it all so I will just post a little and see if anyone can help at all.
ogl_test.cpp
#include "platform.h"
#include "srt/scheduler.h"
#include "model.h"
#include "controller.h"
#include "model_module.h"
#include "graphics_module.h"
class blob : public actor {
public:
blob(float x, float y) : actor(math::vector2f(x, y)) { }
void render() {
transform();
glBegin(GL_TRIANGLES);
glVertex3f(0.25f, 0.0f, -5.0f);
glVertex3f(-.5f, 0.25f, -5.0f);
glVertex3f(-.5f, -0.25f, -5.0f);
glEnd();
end_transform();
}
void update(controller& c, float dt) {
if (c.left_key) {
rho += pi / 9.0f * dt;
c.left_key = false;
}
if (c.right_key) {
rho -= pi / 9.0f * dt;
c.right_key = false;
}
if (c.up_key) {
v += .1f * dt;
c.up_key = false;
}
if (c.down_key) {
v -= .1f * dt;
if (v < 0.0) { v = 0.0; }
c.down_key = false;
}
actor::update(c, dt);
}
};
class enemyOne : public actor {
public:
enemyOne(float x, float y) : actor(math::vector2f(x, y)) { }
void render() {
transform();
glBegin(GL_TRIANGLES);
glVertex3f(0.25f, 0.0f, -5.0f);
glVertex3f(-.5f, 0.25f, -5.0f);
glVertex3f(-.5f, -0.25f, -5.0f);
glEnd();
end_transform();
}
void update(controller& c, float dt) {
if (c.left_key) {
rho += pi / 9.0f * dt;
c.left_key = false;
}
if (c.right_key) {
rho -= pi / 9.0f * dt;
c.right_key = false;
}
if (c.up_key) {
v += .1f * dt;
c.up_key = false;
}
if (c.down_key) {
v -= .1f * dt;
if (v < 0.0) { v = 0.0; }
c.down_key = false;
}
actor::update(c, dt);
}
};
int APIENTRY WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
char* lpCmdLine,
int nCmdShow
)
{
model m;
controller control(m);
srt::scheduler scheduler(33);
srt::frame* model_frame = new srt::frame(scheduler.timer(), 0, 1, 2);
srt::frame* render_frame = new srt::frame(scheduler.timer(), 1, 1, 2);
model_frame->add(new model_module(m, control));
render_frame->add(new graphics_module(m));
scheduler.add(model_frame);
scheduler.add(render_frame);
blob* prime = new blob(0.0f, 0.0f);
m.add(prime);
m.set_prime(prime);
enemyOne* primeTwo = new enemyOne(2.0f, 0.0f);
m.add(primeTwo);
m.set_prime(primeTwo);
scheduler.start();
control.start();
return 0;
}
model.h
#include <vector>
#include "vec.h"
const double pi = 3.14159265358979323;
class controller;
using math::vector2f;
class actor {
public:
vector2f P;
float theta;
float v;
float rho;
actor(const vector2f& init_location) :
P(init_location),
rho(0.0),
v(0.0),
theta(0.0)
{ }
virtual void render() = 0;
virtual void update(controller&, float dt) {
float v1 = v;
float theta1 = theta + rho * dt;
vector2f P1 = P + v1 * vector2f(cos(theta1), sin(theta1));
if (P1.x < -4.5f || P1.x > 4.5f) { P1.x = -P1.x; }
if (P1.y < -4.5f || P1.y > 4.5f) { P1.y = -P1.y; }
v = v1;
theta = theta1;
P = P1;
}
protected:
void transform() {
glPushMatrix();
glTranslatef(P.x, P.y, 0.0f);
glRotatef(theta * 180.0f / pi, 0.0f, 0.0f, 1.0f); //Rotate about the z-axis
}
void end_transform() {
glPopMatrix();
}
};
class model {
private:
typedef std::vector<actor*> actor_vector;
actor_vector actors;
public:
actor* _prime;
model() { }
void add(actor* a) {
actors.push_back(a);
}
void set_prime(actor* a) {
_prime = a;
}
void update(controller& control, float dt) {
for (actor_vector::iterator i = actors.begin(); i != actors.end(); ++i) {
(*i)->update(control, dt);
}
}
void render() {
for (actor_vector::iterator i = actors.begin(); i != actors.end(); ++i) {
(*i)->render();
}
}
};
Your blob is erasing the keypresses before the second actor sees them:
if (c.left_key) {
rho += pi / 9.0f * dt;
c.left_key = false; // <-- HERE
}
Clearing the keyboard state after each frame should not be the concern of any single actor, the controller itself should do that.
Both blob and enemyOne both have an update function that checks the arrow keys to see whether to move. If you commented out all of the if statements inside one of the update function then it should not move anymore. Alternatively, you could change the if statements in the update function to check other keys and use those to control the other object.
EDIT: As noted in another answer, when you set c.left_key = false; (or one on the other keys) you prevent any of the other actors from seeing that the key was pressed. Either not passing the controller around as a reference, or removing these lines of code should fix this.