rendered paste body/* Revised the code since Attention_test_3.cpp
* 2 slabs appear on the groun floor in constant positions, and 4 objects that randomly change positions;
* association with the bar has been removed. ISI was removed.
*
* GOALS: 1. remove the difference between OBJ_NUM_1 and OBJ_NUM_2 because we don't have 2 frames anymore;
* 2. figure out how to add the slabs in the drawPolygons() function and randomize them
* independent of the other objects.
* 3. Clean up code
* 4. Change orientation of "slabs" between horizontal and vertical
* Q: what is bshow doing here? how do the frame 2 objects disappear? (update: solved, 8/8/2005)
*/
//#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream>
#include <windows.h> //comment for os x compiling
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h> /* for cos(), sin(), and sqrt() */
#include <gl/glut.h> /* OpenGL Utility Toolkit header */
//#include <GLUT/glut.h> //use this for os x compiling
#include <mmsystem.h> //comment for os x compiling
#include <assert.h>
#include <vector>
using namespace std;
#define FRAMELENGTH 750 // presentation duration of frame 1 & 2; should be 750
char subjStr[100]; //character input for subject name
char checkImage1[100][100][3]; //i don't know what this is but used to be char checkImage1[576][576][3];
FILE * infile;
FILE * outfile;
char infilename[40];
char outfilename[40];
//int abs(float num){return abs((int)num);} //uncomment for os x compiling
//maximum number of objects in the scene for this program
const unsigned OBJECT_NUM_1 = 4; //# of objects in Frame 1, used for array numOfObjects[0]
const unsigned OBJECT_NUM_2 = 4; //# of objects in Frame 2, used for array numOfObjects[2]
const unsigned MAX_OBJECT_NUM = OBJECT_NUM_1; //maximum limit to number of objects
const unsigned TEXTURE = 0; //0=.002, 1=.003, 2=.004, 3=.005
// 8 x 1 x 1 x 1 x 1 x 1
// (heading, numOfObjects, RandomizedPostion, isi, bar, nearwide, leftright, contrast)
const unsigned CONDITIONS = 8;
const unsigned REPETITION = 1; //# of times each trial is repeated
const unsigned OBJ_RANDOM_NUM = 1; //# of times all trials are repeated
const unsigned TOTALTRIALS = CONDITIONS * REPETITION * OBJ_RANDOM_NUM; //TOTAL number of trials in the run
const unsigned REPEAT = 10; //add this because of new floor without texture
const int SCENE_LEFT_BDR = -50; //defines borders of screen
const int SCENE_RIGHT_BDR = 50;
const int SCENE_NEAR_BDR = -30;
const int SCENE_FAR_BDR = -273;
const int FIXED_OBJ_POS = 0;
const int RAND_SWITCH_OBJ_POS = 1;
const int RAND_MV_OBJ_KEEP_REL = 2;
const int RAND_MV_OBJ_NOKEEP_REL = 3;
const float L_MARGIN = 5; //defines margin (of screen? or for objects? probably screen)
const float R_MARGIN = 5;
const float U_MARGIN = 5;
const float D_MARGIN = 5;
const float VISUAL_ANGLE = 20.0; //i think this is the angle which the objs occupy, if too large, objs will disappear
const double M_PI = 3.14159265; //pi value, comment for os x compiling
float XX,ZZ;
float mv_distance = 24.0;
float disp = 0;
float circlex[500]; //I need to figure out why these circles are not being drawn; these are supposed to be on the ground floor
float circlez[500];
int posMatrix[300][300];
int objorder[MAX_OBJECT_NUM];
int objPlacOrder[MAX_OBJECT_NUM];
int order[TOTALTRIALS]; //for ordering the total number of trials each time the exe. is ran
int correct = 0;
int frame = 0;
int phase = 0; //there are four phases to each trial: frame1, blank, frame2, blank.
int ticks1, ticks0; /*clock_t*/
int moving, startx, starty;
int lightStartX, lightStartY;
int blank = 0;
//int duration = 3000; //increase time of frame presentation //1000
int resp = 0;
int resp_lock = 1; //when 1, no [4|6] responses will be accepted
int ntrials; //number of trials in the block
int trial=0; //initialize trial to 0
short ord_change_num, rel_to_eye_change_num;
unsigned windW = 1280, windH = 1024; //window width and height
/* Variable controlling various rendering modes. */
int stencilReflection = 0, stencilShadow = 1, offsetShadow = 1;
int renderShadow = 1, renderPolygons = 1;
int linearFiltering = 0, useMipmaps = 1, useTexture = 1;
int reportSpeed = 0;
GLboolean lightSwitch = GL_TRUE;
int directionalLight = 1;
int forceExtension = 0;
/* Time varying or user-controled variables. */
float lightAngle = -12.0, lightHeight = 25;
GLfloat angle = 0; //-150; /* in degrees */ /*angle and angle2 for drawing the bar?*/
GLfloat angle2 = 0; //30; /* in degrees */
typedef struct {
/* int kind; //looks like we're not using these variables at the moment
* float rot;
* float scale; */
float x[2]; //0 is frame 1, 1 is frame 2
float z[2];
} objtype;
objtype obj[TOTALTRIALS][MAX_OBJECT_NUM]; /*for every object in frame 1 and for all the trials in the exp,
*specify the x and z positions of the objects on the plane */
/*build structure of type Condition with all these variables*/
typedef struct _condition {
//float bar_angle;
float abs_heading; //4 heading angles
float rel_heading; //4 heading angles
//float isi; //2 isi conditions
int contrast; //1 level of contrast, 180
int obj_num[2]; // number of objects in the first and second frames
bool bshow[MAX_OBJECT_NUM];//for every object, should we show it or not
int objRandom;
} Condition;
//32 conditions total, 2 repetitions for each condition
Condition trialConditions[TOTALTRIALS]; //creates an array (for all trials) containing the elements defined in structure "conditions"
Condition trial_cond; //trial_cond has all the vars. inside the structure Condition
enum {
MISSING, EXTENSION, ONE_DOT_ONE
};
int polygonOffsetVersion;
GLfloat lightPosition[4];
GLfloat lightColor[] = {1.0, 1.0, 1.0, 1.0};
/* FUNCTION PROTOTYPES BEGIN!! */
void zeroMatrix(); /* initializes all params of posMatrix[][] to 0 */
void readTrialParams();
void MakeRandomPlacOrder(int, int); /* Shuffle objects... but i don't know how */
void makeSubFile();
void GenerateConditions();
void MakeTrialOrderRandom(int, int);
int checkAroundMatrix(int, int);
int checkMatrix(float, float);
void setPosMatrix(float, float, int);
float RandomPosX();
float RandomPosZ();
float RandomPosXZ(float, float, float);
unsigned randMVObject(float);
void SortOrder(vector<float> & tan_v, vector<short> & order);
bool IsRelToEyeChange(objtype);
bool IsObjectOutOfView(objtype);
bool IsOrdRelChange(objtype);
void SetInitialObjPos(int, float);
void SetObjectPos(unsigned, int, objtype);
void setParams();
void makeCheckImage();
void makeFloorTexture();
void shadowMatrix(GLfloat, GLfloat, GLfloat);
void findPlane(GLfloat, GLfloat, GLfloat, GLfloat);
void drawPolygons(bool);
void drawBlankScreen();
void drawFloor();
void MoveEye(double, float);
void redraw();
void motion(int, int);
void idle();
void controlLights(int);
void visible(int);
void key(unsigned char, int, int);
int supportsOneDotOne();
/* FUNCTION DEFINITIONS BEGIN!! */
/* *INDENT-ON* */
void zeroMatrix() /* initializes all params of posMatrix[][] to 0 */
{
int i,k;
for (i=0; i<101; ++i)
for (k=0; k<201; ++k)
posMatrix[i][k] = 0;
}
void readTrialParams(void)
{
ntrials = TOTALTRIALS;
printf("ntrials = %i\n", ntrials);
//trial_cond.bar_angle = trialConditions[order[trial]].bar_angle;
trial_cond.rel_heading = trialConditions[order[trial]].abs_heading;
//trial_cond.abs_heading = trial_cond.rel_heading + trialConditions[order[trial]].bar_angle;
//trial_cond.isi = trialConditions[order[trial]].isi;
trial_cond.contrast = trialConditions[order[trial]].contrast;
trial_cond.obj_num[0] = trialConditions[order[trial]].obj_num[0]; //# of objs in Frame 1(?)
trial_cond.obj_num[1] = trialConditions[order[trial]].obj_num[1]; //# of objs in Frame 2(?)
trial_cond.objRandom = trialConditions[order[trial]].objRandom;
unsigned i, obj_num = trial_cond.obj_num[0];
for (i=0; i<obj_num; ++i)
trial_cond.bshow[i] = trialConditions[order[trial]].bshow[i];
}
void MakeRandomPlacOrder(int object_num, int obj_place_ord[])
{
int i, j;
int rep, temp;
for(i=0; i<object_num; ++i){ //how does the loop know how many times to loop if we don't know value of Object_num?
obj_place_ord[i] = i;
}
//checks for objects being in initial position after shuffle
//can reduce rep without changing outcome to save time
for(rep=0; rep<10; ++rep) {
for(i=0; i<object_num; ++i) {
j = rand() % object_num; //use line below if shuffles don't seem sufficiently random
//j = (int)((float)rand()/(float)(RAND_MAX+1) * object_num);
temp = obj_place_ord[j];
obj_place_ord[j] = obj_place_ord[i];
obj_place_ord[i] = temp;
}
}
}
void makeSubFile(void)
{
char temp[100],base[100];
int again;
do {
printf("Enter participant name:");
gets(subjStr);
// strcpy(base, subjStr);
// if (RANDOMIZE_OBJECT_POS==FIXED_OBJ_POS)
sprintf(base,"data\\f_");
// else if (RANDOMIZE_OBJECT_POS==RAND_SWITCH_OBJ_POS)
// sprintf(base,"data\\o_");
// else if (RANDOMIZE_OBJECT_POS==RAND_MV_OBJ_KEEP_REL)
// sprintf(base,"data\\m_");
// else if (RANDOMIZE_OBJECT_POS==RAND_MV_OBJ_NOKEEP_REL)
// sprintf(base,"data\\b_");
// else
// assert(0);
strcat(base, subjStr);
// if (trialConditions[order[trial]].isi==50) /*took this out because we don't have an ISI option anymore */
strcat(base, "A");
// else
// strcat(base, "B");
printf("Enter run number (1 or 2):");
gets(temp);
strcat(base, temp);
strcpy(infilename,base);
strcpy(outfilename,base);
strcat(outfilename, ".txt");
printf("%s\n", infilename);
printf("data\\M%d%s\n", TEXTURE, outfilename);
outfile = fopen(outfilename, "r+");
if(outfile == NULL) {
outfile = fopen(outfilename, "w+");
if (outfile==NULL) {
cout << "Error: open file " << outfilename << "fail\n"; exit(1);
}
again = 0;
}
else {
printf("File already exists. Try again.");
again = 1;
}
} while(again);
}
/*generate conditions, fills the array for every level of the variable,
and randomize them in the experiment*/
//4 heading, 2 nearwide, 3 of c for contrast == removed ISI condition
void GenerateConditions()
{
int i = 0;
int r, h, l, nobj, c; //heading, location, nearwide, contrast
int reps;
float heading[8] = {-23, -17, -11, -5, 5, 11, 17, 23}; //in degrees
//float isiA[2] = {50, 1000}; //isi
int contrastA[3] = {120, 180, 240};
int numOfObjects[2] = {OBJECT_NUM_1, OBJECT_NUM_2}; //{3,6,12,24};
int objectRandom[4] = {FIXED_OBJ_POS, RAND_SWITCH_OBJ_POS, RAND_MV_OBJ_KEEP_REL,
RAND_MV_OBJ_NOKEEP_REL};
//assert(REPETITION % 2 == 0); //took this out because we don't need an even number of conditions for bar angle
// short bar_side[REPETITION];
// float bar_angle = 8.0;
for (r=0; r<OBJ_RANDOM_NUM; ++r) //# times all trials repeated, according to earlier comment
for(h = 0; h < 8; ++h) //heading index
for(c = 0; c < 1; ++c) //c goes from 0 to 0 (loop once) (contrast)
for(l = 2; l < 3; ++l) //l goes from 2 to 2 (loop once) (location)
for(nobj = 0; nobj < 1; ++nobj) { //nobj goes from 0 to 0 (loop once) (nearwide)
// for (j = 0; j < REPETITION; ++j) //repetition index
// bar_side[j] = -1;
/*for (j = 0; j < REPETITION / 2; ++j) {
do {
idx = rand() % REPETITION;
if (bar_side[idx]==-1) {
bar_side[idx] = 1; break;
}
} while(true);
}*/
for(reps = 0; reps < REPETITION; ++reps) {
trialConditions[i].abs_heading = heading[h];
//trialConditions[i].isi = isiA[0];
trialConditions[i].contrast = contrastA[1];
trialConditions[i].obj_num[0] = numOfObjects[0];
trialConditions[i].obj_num[1] = numOfObjects[1];
trialConditions[i].objRandom = objectRandom[r];
// trialConditions[i].bar_angle = bar_side[reps] * bar_angle;
unsigned ii, idx, obj_num_1 = numOfObjects[0], obj_num_2 = numOfObjects[1];
for (ii=0; ii<obj_num_1; ++ii)
{
trialConditions[i].bshow[ii] = true; //makes all objects (obj_num_1) visible
}
for (ii=0; ii<obj_num_1-obj_num_2; ++ii) //loop as many times as the difference between the max and min # of objects
{
while(true){ //do this forever until the break
idx = rand() % obj_num_1; //picks number from 0 to a value==obj_num_1
if (trialConditions[i].bshow[idx]==true) //assign bshow[] true and break out of the while loop
break;
}
trialConditions[i].bshow[idx] = false; //assign bshow[] false value
} //go back up to for loop
++i;
}
}
printf("\n\nTOTALTRIALS:%d i:%d \n\n",TOTALTRIALS,i);
}
void MakeTrialOrderRandom(int trial_num, int trial_ord[])
{
int i, j, k;
int temp;
/* for(i = 0; i < trial_num; ++i) { //creates a list of numbers from 0 to (number of trials)-1
* trial_ord[i] = i;
* }
*
* for(k = 0; k < 1000; ++k) //shuffles list of indices (created above) to the trials
* for(i = 0; i < trial_num; ++i) {
* j = rand() % trial_num; //use line below if trials don't seem sufficiently shuffled
* //j = (int)((float)rand()/(float)(RAND_MAX+1) * trial_num); //pick a random number for j from 0 to (trial_num-1)
* temp = trial_ord[j]; //these three operations swap trial_ord[j] and trial_ord[i]
* trial_ord[j] = trial_ord[i];
* trial_ord[i] = temp;
* }
*/
for(i = 0; i < trial_num; ++i)
{
trial_ord[i]=-1;
}
for(i = 0; i < trial_num; ++i)
{
do
{
j = rand() % trial_num;
} while(trial_ord[j] != -1);
trial_ord[j]=i;
}
//prints out conditions for each level, showing that they're shuffled
for(i = 0; i < trial_num; ++i) {
cout << " trial: " << i << " " << order[i];
cout << " heading: " << trialConditions[trial_ord[i]].abs_heading;
// cout << " isi: " << trialConditions[trial_ord[i]].isi;
cout << " obj: (" << trialConditions[trial_ord[i]].obj_num[0];
cout << ", " << trialConditions[trial_ord[i]].obj_num[1] << ") ";
cout << " random:" << trialConditions[trial_ord[i]].objRandom;
cout << " " << TEXTURE << endl;
}
}
const unsigned STEPX = 7; // 10 size of the matrix, X steps
const unsigned STEPZ = 15; // 20 size of the matrix, Z steps
int checkAroundMatrix(int rX, int rZ)
{
int i, j;
int check=0;
// increase sp value to increase spacing allowed
// (how close objects can be to each other)
int sp = 2;
for (j=rZ-sp; j<=rZ+sp; ++j)
for (i=rX-sp; i<=rX+sp; ++i)
if ((i>=0) && (j>=0))
check = posMatrix[i][j] || check;
return(check);
}
int checkMatrix(float X, float Z)
{
int rX, rZ;
rX = (X+50) / STEPX;
rZ = abs(Z / STEPZ);
//printf("rx %d rZ %d \n",rX,rZ);
if ( checkAroundMatrix(rX,rZ) ) { // if position already taken, return NO GOOD
return(0);
}
posMatrix[rX][rZ] = 1; // else set the position as taken, and return GOOD
return 1;
}
void setPosMatrix(float x, float z, int value)
{
int rX, rZ;
rX = (x+50) / STEPX;
rZ = abs(z / STEPZ);
posMatrix[rX][rZ] = value;
}
float RandomPosX ()
{
// size of the visiable world is X: -50, 50
unsigned width = abs(SCENE_RIGHT_BDR - SCENE_LEFT_BDR - L_MARGIN - R_MARGIN);
return (((float)rand() / (float)(RAND_MAX+1) * width) + SCENE_LEFT_BDR + L_MARGIN);
}
float RandomPosZ()
{
// size of the visiable world in Z = -30 to -200
unsigned length = abs(SCENE_NEAR_BDR - SCENE_FAR_BDR - U_MARGIN - D_MARGIN);
return (((float)rand() / (float)(RAND_MAX + 1) * length) + SCENE_FAR_BDR + U_MARGIN);
}
float RandomPosXZ(float *XX, float *ZZ, float dis_x)
{
float dis_xl_thr = dis_x + L_MARGIN + 10;
float dis_xr_thr = dis_x + R_MARGIN + 10;
unsigned it = 0;
do {
for (;;) {
*XX = RandomPosX();
if (*XX < 0 && fabs(*XX) > dis_xl_thr || *XX > 0 && *XX > dis_xr_thr) break;
}
*ZZ = RandomPosZ();
// 40 degrees total, 20 degrees from the center, give 5 deg to be sure
if (abs(*XX / *ZZ) < tan(VISUAL_ANGLE / 180.0 * M_PI) ) {
if (checkMatrix(*XX, *ZZ) ) {
// printf("%3.2f %3.2f \n",*XX,*ZZ);
return 1;
}
}
++it;
} while (it < 100);
return 0;
}
unsigned randMVObject(float radius)
{
zeroMatrix();
unsigned i, move_num, old_move_num = 0;
unsigned try_no, try2_no, try3_no, try4_no, try_thr = 100;
double direction;
unsigned num_object = trial_cond.obj_num[0];
vector<short> move(num_object);
unsigned trial_no = order[trial];
for (i=0; i<unsigned(num_object); ++i) {
setPosMatrix(obj[trial_no][i].x[0], obj[trial_no][i].z[0], 1); //
move[i] = 0;
}
move_num = try2_no = try3_no = try4_no = 0;
do {
for (i=0; i<unsigned(num_object); ++i) {
if (move[i]) continue;
setPosMatrix(obj[trial_no][i].x[0], obj[trial_no][i].z[0], 0);
try_no = 0;
do {
// unsigned deg = rand() % 360;
unsigned deg = (rand() % 2) * 180;
direction = deg * M_PI / 180.0;
float x_dis = float(radius * cos(direction));
float z_dis = float(radius * sin(direction));
float xn, zn;
float x = obj[trial_no][i].x[0], z = obj[trial_no][i].z[0];
xn = x + x_dis; zn = z + z_dis;
++try_no;
if (xn < SCENE_LEFT_BDR + L_MARGIN || xn > SCENE_RIGHT_BDR - R_MARGIN ||
zn < SCENE_FAR_BDR + U_MARGIN || zn > SCENE_NEAR_BDR - D_MARGIN)
continue;
if (checkMatrix(xn, zn)) {
obj[trial_no][i].x[1] = xn; obj[trial_no][i].z[1] = zn;
++move_num;
move[i] = deg==0 ? 1 : -1; break;
}
if (try_no > try_thr) {
setPosMatrix(obj[trial_no][i].x[0], obj[trial_no][i].z[0], 1);
break;
}
} while(true);
}
if (move_num < unsigned(num_object)) {
if (old_move_num!=move_num) {
old_move_num = move_num;
try2_no = 0;
}
else {
++try2_no;
if (try2_no==10) {
if (++try3_no==10) return 0;
try2_no = move_num = old_move_num = 0;
zeroMatrix();
for (i=0; i<unsigned(num_object); ++i) {
move[i] = 0;
setPosMatrix(obj[trial_no][i].x[0], obj[trial_no][i].z[0], 1);
}
}
}
}
else {
short sum = 0;
for (i=0; i<unsigned(num_object); ++i) sum += move[i];
if (sum==-3 || sum==3) { // move along the same direction
if (++try4_no==10) return 0;
try2_no = move_num = old_move_num = 0; // I don't set try3_no = 0
zeroMatrix();
for (i=0; i<unsigned(num_object); ++i) {
move[i] = 0;
setPosMatrix(obj[trial_no][i].x[0], obj[trial_no][i].z[0], 1);
}
}
}
// if (move_num) break;
} while (move_num < unsigned(num_object));
return move_num;
}
void SortOrder(vector<float> & tan_v, vector<short> & order)
{
float tan_tmp;
short order_tmp;
int num_object = trial_cond.obj_num[0];
int i, j;
for (i=0; i<num_object-1; ++i)
for (j=i+1; j<num_object; ++j)
if (tan_v[i] > tan_v[j]) {
tan_tmp = tan_v[i]; tan_v[i] = tan_v[j]; tan_v[j] = tan_tmp;
order_tmp = order[i]; order[i] = order[j]; order[j] = order_tmp;
}
}
bool IsRelToEyeChange(objtype obj[])
{
int num_object = trial_cond.obj_num[0];
vector<short> order_bm(num_object), order_am(num_object);
vector<float> tan_bm(num_object), tan_am(num_object);
float eyex = mv_distance * sin(trial_cond.abs_heading * M_PI / 180);
float eyez = 80.0 - mv_distance * cos(trial_cond.abs_heading * M_PI / 180);
float x, z;
int i;
for (i=0; i<num_object; ++i) {
order_bm[i] = i+1;
x = obj[i].x[0]; z = 80.0 - obj[i].z[0]; tan_bm[i] = x / z; // z cannot be 0.
}
SortOrder(tan_bm, order_bm);
for (i=0; i<num_object; ++i) {
order_am[i] = i+1;
x = obj[i].x[1] - eyex; z = eyez - obj[i].z[1];
tan_am[i] = x / z; // z cannot be 0.
}
SortOrder(tan_am, order_am);
rel_to_eye_change_num = 0;
for (i=0; i<num_object; ++i)
if (order_bm[i] != order_am[i])
rel_to_eye_change_num += 1;
if (rel_to_eye_change_num) return true;
return false;
}
bool IsObjectOutOfView(objtype obj[])
{
float eyex = mv_distance * sin(trial_cond.abs_heading * M_PI / 180);
float eyez = 80.0 - mv_distance * cos(trial_cond.abs_heading * M_PI / 180);
float x, z;
int num_object = trial_cond.obj_num[0];
int i;
for (i=0; i<num_object; ++i) {
x = obj[i].x[1] - eyex; z = eyez - obj[i].z[1];
if (x > 0) x += R_MARGIN;
else if (x < 0) x -= L_MARGIN;
if (abs(x / z) >= tan(VISUAL_ANGLE / 180.0 * M_PI))
return true;
}
return false;
}
bool IsOrdRelChange(objtype obj[])
{
int num_object = trial_cond.obj_num[0];
vector<vector<short> > x_order_bm(num_object), x_order_am(num_object);
vector<vector<short> > z_order_bm(num_object), z_order_am(num_object);
int i, j;
for (i=0; i<num_object; ++i) {
x_order_bm[i].resize(num_object);
z_order_bm[i].resize(num_object);
x_order_am[i].resize(num_object);
z_order_am[i].resize(num_object);
for (j=0; j<num_object; ++j) {
if (obj[i].x[0] < obj[j].x[0])
x_order_bm[i][j] = -1;
else if (obj[i].x[0] > obj[j].x[0])
x_order_bm[i][j] = 1;
else
x_order_bm[i][j] = 0;
if (obj[i].x[1] < obj[j].x[1])
x_order_am[i][j] = -1;
else if (obj[i].x[1] > obj[j].x[1])
x_order_am[i][j] = 1;
else
x_order_am[i][j] = 0;
if (obj[i].z[0] < obj[j].z[0])
z_order_bm[i][j] = -1;
else if (obj[i].z[0] > obj[j].z[0])
z_order_bm[i][j] = 1;
else
z_order_bm[i][j] = 0;
if (obj[i].z[1] < obj[j].z[1])
z_order_am[i][j] = -1;
else if (obj[i].z[1] > obj[j].z[1])
z_order_am[i][j] = 1;
else
z_order_am[i][j] = 0;
}
}
vector<vector<short> > ord_rel(num_object);
for (i=0; i<num_object; ++i) {
ord_rel[i].resize(num_object);
for (j=0; j<num_object; ++j) ord_rel[i][j] = 0;
for (j=0; j<num_object; ++j) {
if (x_order_bm[i][j]!=x_order_am[i][j])
ord_rel[i][j] = 1;
if (z_order_bm[i][j]!=z_order_am[i][j])
ord_rel[i][j] = 1;
}
}
short sum = 0;
vector<short> rel(num_object);
for (i=0; i<num_object; ++i) {
rel[i] = 0;
for (j=0; j<num_object; ++j) {
rel[i] += ord_rel[i][j];
}
sum += rel[i];
}
assert(sum % 2 == 0);
ord_change_num = sum / 2;
bool bret = false;
if (sum) bret = true;
return bret;
}
void SetInitialObjPos(int object_num, float obj_coord[MAX_OBJECT_NUM][2])
{
int obj_no;
bool bdone;
float dis_x = mv_distance * fabs(sin(trial_cond.abs_heading * M_PI / 180));
do {
bdone = true;
zeroMatrix();
for(obj_no = 0; obj_no < object_num; ++obj_no) {
if (RandomPosXZ(&XX, &ZZ, dis_x)==0) {
bdone = false; break;
}
obj_coord[obj_no][0]=XX;
obj_coord[obj_no][1]=ZZ;
}
} while (!bdone);
/*
cout << '\n';
for(obj_no = 0; obj_no < num_object; ++obj_no) {
XX =obj_coord[obj_no][0]; ZZ = obj_coord[obj_no][1];
cout << XX << " --- " << ZZ << '\n';
}
cout << '\n';
*/
}
void SetObjectPos(unsigned trial_num, int trial_ord[], objtype obj_pos[][MAX_OBJECT_NUM])
{
unsigned i, obj, trial_no, obj_num;
cout << '\n';
for (i=0; i<trial_num; ++i) {
trial_no = trial_ord[i];
obj_num = trialConditions[trial_no].obj_num[0];
cout << i << ": set object positions for trial " << trial_no << '\n';
float obj_coord[MAX_OBJECT_NUM][2];
SetInitialObjPos(obj_num, obj_coord);
for(obj=0; obj<obj_num; ++obj) {
obj[trial_no][obj].x[1] = obj[trial_no][obj].x[0] = obj_coord[obj][0];
obj[trial_no][obj].z[1] = obj[trial_no][obj].z[0] = obj_coord[obj][1];
}
}
cout << '\n';
}
void setParams(void)
{
readTrialParams();
unsigned trial_no = order[trial];
/*from the original positions i added -20 in the z to move back the objects
farther into the scene closer to the wall, then adjusted the individual
coordinances so it would look more "randomly" spread out*/
int object_num = trial_cond.obj_num[0];
float obj_coord[MAX_OBJECT_NUM][2];
MakeRandomPlacOrder(object_num, objPlacOrder);
float radius = 9.0;
if (trial_cond.objRandom == FIXED_OBJ_POS) {
ord_change_num = rel_to_eye_change_num = 0;
}
else if (trial_cond.objRandom == RAND_SWITCH_OBJ_POS) {
for (;;) {
unsigned move_num, try_no = 0, try_thr = 100;
do {
move_num = randMVObject(radius);
ord_change_num = rel_to_eye_change_num = 0;
if (move_num==object_num && !IsObjectOutOfView(obj[trial_no]) &&
(IsOrdRelChange(obj[trial_no]) || IsRelToEyeChange(obj[trial_no]))) break;
++try_no;
} while(try_no < try_thr);
if (try_no < try_thr) break;
SetInitialObjPos(object_num, obj_coord);
MakeRandomPlacOrder(object_num, objPlacOrder);
}
}
else if (trial_cond.objRandom == RAND_MV_OBJ_KEEP_REL) {
for (;;) {
unsigned move_num, try_no = 0, try_thr = 100;
do {
move_num = randMVObject(radius);
ord_change_num = rel_to_eye_change_num = 0;
if (move_num==object_num && !IsObjectOutOfView(obj[trial_no]) &&
!IsOrdRelChange(obj[trial_no]) && !IsRelToEyeChange(obj[trial_no])) break;
++try_no;
} while(try_no < try_thr);
if (try_no < try_thr) break;
SetInitialObjPos(object_num, obj_coord);
MakeRandomPlacOrder(object_num, objPlacOrder);
}
}
else if (trial_cond.objRandom == RAND_MV_OBJ_NOKEEP_REL) {
assert(false);
}
else
assert(false);
}
/*This must be for making some sort of code for the floor texture; related to the next function MakeFloorTexture*/
void makeCheckImage(void)
{
/*
int i, j, c;
for (i=0; i<100; ++i)
for (j=0; j<100; ++j) {
c = (((i&0x8)==0)^((j&0x8)==0))*255;
checkImage1[i][j][0] = GLubyte(c);
checkImage1[i][j][1] = GLubyte(c);
checkImage1[i][j][2] = GLubyte(c);
// checkImage1[i][j][3] = GLubyte(c);
}
*/
int i, j;
GLfloat temp1,temp2,temp3;
// loop to move from input array to proper checkImage array
for (i=0; i<100; ++i) {
for (j=0; j<100; ++j) {
if(rand()>.5*RAND_MAX) {
temp1 = 90;
}
else {
temp1 = 90; //trialConditions[order[trial]].contrast;
}
if(rand()>.5*RAND_MAX) {
temp2 = 0;
}
else {
temp2 = 1;
}
if(rand()>.5*RAND_MAX) {
temp3=0;
}
else {
temp3=1;
}
checkImage1[i][100-1-j][0] = temp1;
checkImage1[i][100-1-j][1] = temp1;
checkImage1[i][100-1-j][2] = temp1;
}
}
}
//end new texture code
/*Create the floor texture*/
void makeFloorTexture(void)
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (useMipmaps) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR);
gluBuild2DMipmaps(GL_TEXTURE_2D,3,100,40,GL_RGB, GL_UNSIGNED_BYTE, &checkImage1[0][0][0]);
}
else {
if (linearFiltering) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
glTexImage2D(GL_TEXTURE_2D, 0, 3, 16, 16, 0,
GL_RGB, GL_UNSIGNED_BYTE, &checkImage1[0][0][0]);
}
}
enum {
X, Y, Z, W
};
enum {
A, B, C, D
};
/* Create a matrix that will project the desired shadow. */
void shadowMatrix(GLfloat shadowMat[4][4], GLfloat groundplane[4],
GLfloat lightpos[4])
{
GLfloat dot;
/* Find dot product between light position vector and ground plane normal. */
dot = groundplane[X] * lightpos[X] + groundplane[Y] * lightpos[Y] +
groundplane[Z] * lightpos[Z] + groundplane[W] * lightpos[W];
shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];
shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];
shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];
shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
shadowMat[3][3] = dot - lightpos[W] * groundplane[W];
}
/* Find the plane equation given 3 points. */
void findPlane(GLfloat plane[4],
GLfloat v0[3], GLfloat v1[3], GLfloat v2[3])
{
GLfloat vec0[3], vec1[3];
/* Need 2 vectors to find cross product. */
vec0[X] = v1[X] - v0[X];
vec0[Y] = v1[Y] - v0[Y];
vec0[Z] = v1[Z] - v0[Z];
vec1[X] = v2[X] - v0[X];
vec1[Y] = v2[Y] - v0[Y];
vec1[Z] = v2[Z] - v0[Z];
/* find cross product to get A, B, and C of plane equation */
plane[A] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y];
plane[B] = -(vec0[X] * vec1[Z] - vec0[Z] * vec1[X]);
plane[C] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X];
plane[D] = -(plane[A] * v0[X] + plane[B] * v0[Y] + plane[C] * v0[Z]);
}
void drawPolygons(bool bShadow)
{
int i;
int object_num = trial_cond.obj_num[0]; //i think this is the max # of objects (in other words, objs in Frame 1
float X, Z;
unsigned trial_no;
for(i=0; i<object_num; ++i) { //loop until all objects are drawn
//if (frame==2 && !trial_cond.bshow[i]) continue; //if it is frame 2 and bshow[] is false, skip all this stuff below and go back up to the top of this for loop
GLfloat mat_specular_old[4];
GLfloat mat_diffuse_old[4];
GLfloat mat_ambient_old[4];
GLfloat mat_shine_old[1];
if (!bShadow && trial_cond.bshow[i]) {
glGetMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular_old);
glGetMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse_old);
glGetMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_old);
glGetMaterialfv(GL_FRONT, GL_SHININESS, mat_shine_old);
GLfloat rf_sp = 0, rf_df = 1.0, rf_ab = 1.0;
// GLfloat mat_specular[] = {rf_sp, rf_sp, rf_sp, 1.0};
// GLfloat mat_diffuse[] = {rf_df, rf_df, rf_df, 1.0};
// GLfloat mat_ambient[] = {rf_ab, rf_ab, rf_ab, 1.0};
GLfloat mat_specular[] = {1.0, 0.0, 0.0, 1.0};
GLfloat mat_diffuse[] = {1.0, 0.0, 0.0, 1.0};
GLfloat mat_ambient[] = {1.0, 0.0, 0.0, 1.0};
// GLfloat mat_diffuse[] = {rf_df, 0, 0, 1.0};
// GLfloat mat_ambient[] = {rf_ab, 0, 0, 1.0};
GLfloat mat_shine[] = {50.0};
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shine);
}
trial_no = order[trial];
X = obj[trial_no][i].x[frame-1];
Z = obj[trial_no][i].z[frame-1];
/* Push/Draw polygons on the floor */
glPushMatrix();
/* TO DO: put slab on the right place; create 2 of them
* Also, put the slabs in another function (or whatever)
* so they can switch between orientations randomly?? */
/* draw objects in the scene */
switch (objPlacOrder[i]) {
case 0: //cube 1
glTranslatef(X, 3, Z);
//glRotatef(150.0, 0.0, 1.0, 0.0);
//glScalef(2.0, 0.5, 4.0);
glutSolidCube(6);
break;
case 1: //cone
glTranslatef(X, 0, Z);
glRotatef(270.0, 1.0, 0.0, 0.0);
glutSolidCone(3.25, 10.5, 45, 22.5);
break;
case 2: //slab 1
glTranslatef(-30, 1.0, -100); //make x and z positions constant, not defined by obj[] array (see above)
//glRotatef(150.0, 0.0, 1.0, 0.0);
glScalef(3.0, (GLfloat)0.2, 10.0);
glutSolidCube(9);
break;
case 3: //slab 2
glTranslatef(25, 1.0, -130); //make x and z positions constant, not defined by obj[] array (see above)
//glRotatef(150.0, 0.0, 1.0, 0.0);
glScalef(3.0, (GLfloat)0.2, 20.0);
glutSolidCube(9);
break;
case 4: //sphere
glTranslatef(X, 3, Z);
glutSolidSphere(3, 30, 15);
break;
case 5: //wirecone stretched vertically a litte bit
glTranslatef(X, 0., Z);
glScalef(1, (GLfloat)1.3, 1);
glRotatef(270.0, 1.0, 0.0, 0.0);
glutWireCone(3.25, 10.5, 8, 6);
break;
case 6: //solid sphere stretched out vertically
glTranslatef(X, 5, Z);
glScalef(1 , (GLfloat)1.7 , 1);
glutSolidSphere(3., 30, 15);
break;
case 7: //wirecube stretched out horizontally
glTranslatef(X, 3., Z);
glScalef(2, (GLfloat)0.9, (GLfloat)0.9);
glRotatef(160.0, 0.0, 1.0, 0.0);
glutWireCube(6);
break;
default: //problem!!! define more objects/cases
glScalef(4.0, 4.0, 4.0);
glutSolidCube(6);
break;
}
if (!bShadow && trial_cond.bshow[i]) {
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular_old);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse_old);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_old);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shine_old);
}
glPopMatrix(); //end PushMatrix()
} //end "for" loop
} //end function
void drawBlankScreen(void)
{
if(blank==1) {
glDisable(GL_LIGHTING);
}
if (useTexture) {
glEnable(GL_TEXTURE_2D);
}
glBegin(GL_QUADS);
glVertex3f(-100, -100, 32);
glVertex3f(-100, 100, 32);
glVertex3f(100, 100, 32);
glVertex3f(100, -100, 32);
glEnd();
if (useTexture) {
glDisable(GL_TEXTURE_2D);
}
if(blank==1){
glEnable(GL_LIGHTING);
}
}
/*vertices for textured floor and wall*/
GLfloat floorVertices[4][3] = {
{ -200.0, 0.0, 100.0 },
{ 200.0, 0.0, 100.0 },
{ 200.0, 0.0, -300.0 },
{ -200.0, 0.0, -300.0 },
};
/*vertices for grid on floor */
GLfloat gridVertices[4][3] = {
{ -200.0, 0.0, 100.0 },
{ 200.0, 0.0, 100.0 },
{ 200.0, 0.0, -300.0 },
{ -200.0, 0.0, -300.0 },
};
//This code is to draw a textured floor; from Objects no texture (Expt. 3) cpp file
void drawFloor(void)
//generate 20 circles randomly placed on the ground for each trial
{
int i, j, cosine, sine;
float textureA[4] = {(GLfloat)0.002, (GLfloat)0.003, (GLfloat)0.004, (GLfloat)0.005};
float texmult=textureA[TEXTURE];
glDisable(GL_LIGHTING);
if (useTexture) {
glEnable(GL_TEXTURE_2D);
}
glBegin(GL_QUADS);
// glTexCoord2f(0.0, 0.0);
// glTexCoord2f(texmult*floorVertices[0][0],texmult*floorVertices[0][2]);
glVertex3fv(floorVertices[0]);
// glTexCoord2f(0.0, REPEAT);
// glTexCoord2f(texmult*floorVertices[1][0],texmult*floorVertices[1][2]);
glVertex3fv(floorVertices[1]);
// glTexCoord2f(REPEAT, REPEAT);
// glTexCoord2f(texmult*floorVertices[2][0],texmult*floorVertices[2][2]);
glVertex3fv(floorVertices[2]);
// glTexCoord2f(REPEAT, 0.0);
// glTexCoord2f(texmult*floorVertices[3][0],texmult*floorVertices[3][2]);
glVertex3fv(floorVertices[3]);
glEnd();
//make cirlces on the ground
for (i = 0; i < 500; ++i) {
glBegin (GL_POLYGON);
//Generate the points of the circle
for (j = 0; j < 100; ++j) {
cosine = cos(j * 2 * 3.14 / 100.0);
sine = sin(j * 2 * 3.14 / 100.0);
glVertex3f(cosine+circlex[i], 0, sine+circlez[i]);
//or glVertex3f(2*cosine+circlex[i], 0, 2*sine+circlez[i]);
}
glEnd();
}
if (useTexture) {
glDisable(GL_TEXTURE_2D);
}
glEnable(GL_LIGHTING);
}
GLfloat floorPlane[4];
GLfloat floorShadow[4][4];
void MoveEye(double theta, float disp)
{
glLoadIdentity();
gluLookAt(0.0 + disp * (sin(theta * (M_PI / 180))), 16.0,
80.0 - (disp * (cos(theta * (M_PI / 180)))),
0.0 + disp * (sin(theta * (M_PI / 180))), 16.0,
0.0 - (disp * (cos(theta * (M_PI / 180)))),
0.0, 1.0, 0.); /* up is in positive Y direction */
}
// short ph = 0;
void redraw(void)
{
int start, end;
// int frame = 0;
// static float bar_angle;
ticks1 = (int)(clock()*1000/CLOCKS_PER_SEC); //milliseconds
if (phase == 0) { // press ' ' to set phase to 1
MoveEye(trial_cond.abs_heading, 0);
blank = 2;
ticks0 = (int)(clock()*1000/CLOCKS_PER_SEC);
}
//phase 1==frame 1; taken out in this current program because we told phase == 0 to step over
//to phase ==3 so that we only see one frame instead of 2 frames with a shift in eye movement
//someday i will fix this and take out phase 1 and 2 completely, and refine the other phases
else if (phase == 1){
frame = 1;
disp = 0;
MoveEye(trial_cond.abs_heading, 0);
blank = 0;
if ((ticks1-ticks0)>=FRAMELENGTH){
//phase = 2;
ticks0 = (int)(clock()*1000/CLOCKS_PER_SEC);
}
}
//phase 2 is also taken out because it's not necessary; see description in phase 1
else if(phase == 2){ //blank; ISI presentation
blank = 1;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
disp = 0;
//if ((ticks1-ticks0)>= trial_cond.isi){
phase = 3;
// bar_angle = trialConditions[order[trial]].bar_angle;
ticks0 = (int)(clock()*1000/CLOCKS_PER_SEC);
// }
}
else if (phase == 3){ //frame2
blank = 0;
frame = 2;
MoveEye(trial_cond.abs_heading, mv_distance);
if ((ticks1-ticks0)>=(FRAMELENGTH-250)); //this isn't doing anything
if ((ticks1-ticks0)>=FRAMELENGTH){
phase = 4;
resp_lock=0; // responses will be accepted from now til lock is reengaged
ticks0 = (int)(clock()*1000/CLOCKS_PER_SEC);
}
}
else if (phase == 4){ //wait for response
printf("phase = %i trial = %i\n", phase, trial);
blank = 0;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// MoveEye(trial_cond.abs_heading, 0);
if(resp!=0){
resp_lock=1;
ticks0 = (int)(clock()*1000/CLOCKS_PER_SEC);
blank = 1;
phase = 5;
}
}
else if (phase == 5){ //inter trial interval (ITI)
blank = 1;
MoveEye(trial_cond.abs_heading, 0);
if (((ticks1-ticks0) >= FRAMELENGTH) && resp != 0){
resp_lock=1;//to prevent multiple responses being entered in the ITI
disp = 0; //goes back to 0 position
correct = ((resp * trial_cond.rel_heading) /
(abs(resp) * abs(trial_cond.rel_heading)) + 1) / 2;
fprintf(outfile, "%s, %d, %d, %f, %4.2f, %d, %d, %d, %d, %f, %d, %d, \n",
//fprintf(outfile, "%s, %d, %d, %f, %d, %d, %d, %d, %d, \n",
subjStr, trial, FRAMELENGTH, trial_cond.rel_heading, //removed trial_cond.isi,
trial_cond.obj_num[0], trial_cond.obj_num[1], trial_cond.objRandom,
// resp, correct, bar_angle --removed these because these all depend ond the bar angle
ord_change_num, rel_to_eye_change_num); //changetype was here
fflush(outfile);
if (!correct) cout << "\7\n";
resp=0; //remember to write to file before resetting!
++trial;
if(trial==ntrials){
fclose(outfile);
exit(0);
}
//makeCheckImage();
//makeFloorTexture();
//setParams();
phase = 3;
ticks0 = (int)(clock()*1000/CLOCKS_PER_SEC);
}
}
if (reportSpeed) {
start = glutGet(GLUT_ELAPSED_TIME);
}
/* Clear; default stencil clears to zero. */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
lightPosition[0] = 1000+12*cos(lightAngle);
lightPosition[1] = 50*lightHeight;
lightPosition[2] = 12*sin(lightAngle);
if (directionalLight) {
lightPosition[3] = 0.0;
}
else {
lightPosition[3] = 1.0;
}
shadowMatrix(floorShadow, floorPlane, lightPosition);
glPushMatrix();
/* Perform scene rotations based on user mouse input. */
glRotatef(angle2, 1.0, 0.0, 0.0);
glRotatef(angle, 0.0, 1.0, 0.0);
/* Tell GL new light source position. */
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
/* Back face culling will get used to only draw either the top or the
bottom floor. This let's us get a floor with two distinct
appearances. The top floor surface is reflective and kind of red.
The bottom floor surface is not reflective and blue. */
/* Draw "bottom" of floor in blue. */
glFrontFace(GL_CW); /* Switch face orientation. */
glColor4f((GLfloat)0.1, (GLfloat)0.1, (GLfloat)0.7, 1.0);
glColor4f(1.0, 1.0, 1.0, (GLfloat)0.3);
//drawWall();
if (blank!=0) {
drawBlankScreen();
}
glFrontFace(GL_CCW);
if (phase==1 || phase==3 || phase==4 || phase==5){
if (renderShadow) {
if (stencilShadow) {
// Draw the floor with stencil value 3. This helps us only
// draw the shadow once per floor pixel (and only on the
// floor pixels).
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 3, 0xffffffff);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
}
}
}
/* Draw "top" of floor. Use blending to blend in reflection. */
// glEnable(GL_BLEND);
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f((GLfloat)0.7, 0.0, 0.0, (GLfloat)0.3);
glColor4f(1.0, 1.0, 1.0, (GLfloat)0.3);
drawFloor();
if (blank!=1){//*******************why is this 1, when 0 in other similar cases?
drawBlankScreen();
}
glDisable(GL_BLEND);
if (renderPolygons) { /* Draw "actual" Polygons, not its reflection. */
if (phase==1 || phase==3 || phase==4 || phase==5) { /* don't draw objs when not frame 1 or 2*/
drawPolygons(false);
}
}
if (phase==1 || phase==3 || phase==4 || phase==5){
if (renderShadow) {
/* Render the projected shadow. */
if (stencilShadow) {
/* Now, only render where stencil is set above 2 (ie, 3 where
the top floor is). Update stencil with 2 where the shadow
gets drawn so we don't redraw (and accidently reblend) the
shadow). */
// glStencilFunc(GL_LESS, 2, 0xffffffff); /* draw if ==1 */
// glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
}
/* To eliminate depth buffer artifacts, we use polygon offset
to raise the depth of the projected shadow slightly so
that it does not depth buffer alias with the floor. */
if (offsetShadow) {
switch (polygonOffsetVersion) {
#ifdef GL_EXT_polygon_offset
case EXTENSION:
glEnable(GL_POLYGON_OFFSET_EXT);
break;
#endif
#ifdef GL_VERSION_1_1
case ONE_DOT_ONE:
glEnable(GL_POLYGON_OFFSET_FILL);
break;
#endif
case MISSING:
/* Oh well. */
break;
}
}
/* Render 50% black shadow color on top of whatever the
floor appareance is. */
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_LIGHTING); /* Force the 50% black. */
glColor4f(0.0, 0.0, 0.0, 0.5);
glPushMatrix();
/* Project the shadow. */
glMultMatrixf((GLfloat *) floorShadow);
drawPolygons(true);
glPopMatrix();
glDisable(GL_BLEND);
glEnable(GL_LIGHTING);
if (offsetShadow) {
switch (polygonOffsetVersion) {
#ifdef GL_EXT_polygon_offset
case EXTENSION:
glDisable(GL_POLYGON_OFFSET_EXT);
break;
#endif
#ifdef GL_VERSION_1_1
case ONE_DOT_ONE:
glDisable(GL_POLYGON_OFFSET_FILL);
break;
#endif
case MISSING:
/* Oh well. */
break;
}
}
if (stencilShadow) {
glDisable(GL_STENCIL_TEST);
}
}
}
glPopMatrix();
if (reportSpeed) {
glFinish();
end = glutGet(GLUT_ELAPSED_TIME);
printf("Speed %.3g frames/sec (%d ms)\n", 1000.0/(end-start), end-start);
}
glutSwapBuffers();
}
/* ARGSUSED1 */
void motion(int x, int y)
{
if (moving) {
angle = angle + (x - startx);
angle2 = angle2 + (y - starty);
startx = x;
starty = y;
glutPostRedisplay();
}
}
/* Advance time varying state when idle callback registered. */
void idle(void)
{
static float time = 0.0;
time = glutGet(GLUT_ELAPSED_TIME) / 500.0;
glutPostRedisplay();
}
enum {
M_NONE, M_MOTION, M_LIGHT, M_TEXTURE, M_SHADOWS, M_REFLECTION, M_Polygons,
M_STENCIL_REFLECTION, M_STENCIL_SHADOW, M_OFFSET_SHADOW,
M_POSITIONAL, M_DIRECTIONAL, M_PERFORMANCE
};
void controlLights(int value)
{
switch (value) {
case M_NONE:
return;
case M_LIGHT:
lightSwitch = !lightSwitch;
if (lightSwitch) {
glEnable(GL_LIGHT0);
} else {
glDisable(GL_LIGHT0);
}
break;
case M_TEXTURE:
useTexture = !useTexture;
break;
case M_SHADOWS:
renderShadow = 1 - renderShadow;
break;
case M_Polygons:
renderPolygons = 1 - renderPolygons;
break;
case M_STENCIL_REFLECTION:
stencilReflection = 1 - stencilReflection;
break;
case M_STENCIL_SHADOW:
stencilShadow = 1 - stencilShadow;
break;
case M_OFFSET_SHADOW:
offsetShadow = 1 - offsetShadow;
break;
case M_POSITIONAL:
directionalLight = 0;
break;
case M_DIRECTIONAL:
directionalLight = 1;
// frame2 = 1;
break;
case M_PERFORMANCE:
reportSpeed = 1 - reportSpeed;
break;
}
glutPostRedisplay();
}
/* When not visible, stop animating. Restart when visible again. */
void visible(int vis)
{
glutIdleFunc(idle);
}
/* Press any key to redraw; good when motion stopped and
performance reporting on. */
/* ARGSUSED */
void key(unsigned char c, int x, int y)
{
switch (c) {
case ' ':
if (phase==0) {
phase = 3;
}
/*
else if (phase==1)
phase = 2;
else if (phase==2)
phase = 3;
else if (phase==3 && ph==0) {
ph = 1;
}
else if (ph==1) {
ph = 0;
phase = 4;
}
*/
break;
case '4':
if (phase==4 && resp_lock!=1) {
resp = -1;
}
break;
case '6':
if (phase==4 && resp_lock!=1){
resp = 1;
}
break;
case 27: //esc key exits program
exit(0);
}
glutPostRedisplay();
}
int supportsOneDotOne(void)
{
const char *version;
int major, minor;
version = (char *) glGetString(GL_VERSION);
if (sscanf(version, "%d.%d", &major, &minor) == 2)
return major >= 1 && minor >= 1;
return 0; /* OpenGL version string malformed! */
}
int main(int argc, char **argv)
{
int i;
glutInit(&argc, argv);
unsigned seed = (unsigned int)time(NULL); //give me the current time as an integer
srand(seed); //sets up rand num generator using the current time as its seed; should be done only once
ticks0 = clock()/CLOCKS_PER_SEC*1000;
ofstream ofs("seed.txt");
assert(ofs);
ofs << "seed = " << seed << '\n';
assert(ofs);
ofs.close();
GenerateConditions();
MakeTrialOrderRandom(TOTALTRIALS, order);
SetObjectPos(TOTALTRIALS, order, obj);
makeSubFile();
setParams();
for (i=1; i<argc; ++i) {
if (!strcmp("-linear", argv[i])) {
linearFiltering = 1;
}
else if (!strcmp("-mipmap", argv[i])) {
useMipmaps = 1;
}
else if (!strcmp("-ext", argv[i])) {
forceExtension = 1;
}
}
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL |
GLUT_MULTISAMPLE);
glutCreateWindow("Lots of objects");
if (glutGet(GLUT_WINDOW_STENCIL_SIZE) <= 1) {
printf("dinoshade: Sorry, I need at least 2 bits of stencil.\n");
//exit(1);
}
/* Register GLUT callbacks. */
glutDisplayFunc(redraw);
glutMotionFunc(motion);
glutVisibilityFunc(visible);
glutKeyboardFunc(key);
glutCreateMenu(controlLights);
glutAddMenuEntry("Toggle motion", M_MOTION);
glutAddMenuEntry("-----------------------", M_NONE);
glutAddMenuEntry("Toggle light", M_LIGHT);
glutAddMenuEntry("Toggle texture", M_TEXTURE);
glutAddMenuEntry("Toggle shadows", M_SHADOWS);
glutAddMenuEntry("Toggle reflection", M_REFLECTION);
glutAddMenuEntry("Toggle Polygons", M_Polygons);
glutAddMenuEntry("-----------------------", M_NONE);
glutAddMenuEntry("Toggle reflection stenciling", M_STENCIL_REFLECTION);
glutAddMenuEntry("Toggle shadow stenciling", M_STENCIL_SHADOW);
glutAddMenuEntry("Toggle shadow offset", M_OFFSET_SHADOW);
glutAddMenuEntry("----------------------", M_NONE);
glutAddMenuEntry("Positional light", M_POSITIONAL);
glutAddMenuEntry("Directional light", M_DIRECTIONAL);
glutAddMenuEntry("-----------------------", M_NONE);
glutAddMenuEntry("Toggle performance", M_PERFORMANCE);
glutAttachMenu(GLUT_RIGHT_BUTTON);
#ifdef GL_VERSION_1_1
if (supportsOneDotOne() && !forceExtension) {
polygonOffsetVersion = ONE_DOT_ONE;
glPolygonOffset(-2.0, -1.0);
} else
#endif
{
#ifdef GL_EXT_polygon_offset
/* check for the polygon offset extension */
if (glutExtensionSupported("GL_EXT_polygon_offset")) {
polygonOffsetVersion = EXTENSION;
glPolygonOffsetEXT(-0.1, -0.002);
} else
#endif
{
polygonOffsetVersion = MISSING;
printf("\ndinoshine: Missing polygon offset.\n");
printf(" Expect shadow depth aliasing artifacts.\n\n");
}
}
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glLineWidth(3.0);
glViewport (0, 0, windW, windH);
glMatrixMode(GL_PROJECTION);
gluPerspective( /* field of view in degree */ 36.0,
/* aspect ratio */ float(windW) / windH,
/* Z near */ 47.0, /* Z far */ 1000.0);
glMatrixMode(GL_MODELVIEW);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor);
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, (GLfloat)0.1);
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, (GLfloat)0.05);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glClearColor(0.515f, 0.515f, 0.515f, 1.0f); //(0.6f, 0.6f, 1.0f, 1.0f);
glutFullScreen();
glutSetCursor(GLUT_CURSOR_NONE);
makeCheckImage();
makeFloorTexture();
readTrialParams();
/* Setup floor plane for projected shadow calculations. */
findPlane(floorPlane, floorVertices[1], floorVertices[2], floorVertices[3]);
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}