vrheights

changeset 5:053a52f0cb64

console
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 26 Sep 2014 18:40:15 +0300
parents 690ef7fa791f
children 608e03b688f8
files src/console.cc src/console.h src/game.cc src/game.h src/main.cc src/opengl.h src/teapot.c vrheights.vcxproj vrheights.vcxproj.filters
diffstat 9 files changed, 677 insertions(+), 45 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/console.cc	Fri Sep 26 18:40:15 2014 +0300
     1.3 @@ -0,0 +1,434 @@
     1.4 +#include <stdio.h>
     1.5 +#include <stdlib.h>
     1.6 +#include <string.h>
     1.7 +#include <stdarg.h>
     1.8 +#include <assert.h>
     1.9 +#include <algorithm>
    1.10 +#include "opengl.h"
    1.11 +#include "console.h"
    1.12 +
    1.13 +Console::Console()
    1.14 +	: prompt("> ")
    1.15 +{
    1.16 +	visible = false;
    1.17 +	nlines = 16;
    1.18 +	ncolumns = 80;
    1.19 +	pos_x = pos_y = 0;
    1.20 +	anchor = TOP_LEFT;
    1.21 +
    1.22 +	inpq_front = inpq_back = 0;
    1.23 +
    1.24 +	max_hist_lines = 64;
    1.25 +	max_output_lines = 128;
    1.26 +
    1.27 +	hist_iter_valid = false;
    1.28 +
    1.29 +	echo = true;
    1.30 +	font = 0;
    1.31 +	font_size = 0;
    1.32 +
    1.33 +	cursor = 0;
    1.34 +	input_win = 0;
    1.35 +}
    1.36 +
    1.37 +void Console::set_cursor(int x)
    1.38 +{
    1.39 +	if(x < 0 || x > (int)input.size()) {
    1.40 +		return;
    1.41 +	}
    1.42 +	cursor = x;
    1.43 +
    1.44 +	int max_chars = ncolumns - (int)prompt.size() - 1;
    1.45 +
    1.46 +	if(cursor < input_win) {
    1.47 +		input_win = cursor;
    1.48 +	} else if(cursor > input_win + max_chars) {
    1.49 +		input_win = std::max(cursor - max_chars, 0);
    1.50 +	}
    1.51 +}
    1.52 +
    1.53 +int Console::get_cursor() const
    1.54 +{
    1.55 +	return cursor;
    1.56 +}
    1.57 +
    1.58 +void Console::set_font(dtx_font *font, int sz)
    1.59 +{
    1.60 +	this->font = font;
    1.61 +	font_size = sz;
    1.62 +}
    1.63 +
    1.64 +void Console::set_history_size(int hsz)
    1.65 +{
    1.66 +	max_hist_lines = hsz;
    1.67 +
    1.68 +	int drop = hist.size() - hsz;
    1.69 +	if(drop > 0) {
    1.70 +		auto it = hist.begin();
    1.71 +		for(int i=0; i<drop; i++) {
    1.72 +			++it;
    1.73 +		}
    1.74 +		hist.erase(hist.begin(), it);
    1.75 +	}
    1.76 +}
    1.77 +
    1.78 +void Console::set_output_buffer_size(int sz)
    1.79 +{
    1.80 +	max_output_lines = sz;
    1.81 +
    1.82 +	int drop = output.size() - sz;
    1.83 +	if(drop > 0) {
    1.84 +		output.erase(output.begin(), output.begin() + drop);
    1.85 +	}
    1.86 +}
    1.87 +
    1.88 +void Console::set_command_func(std::function<void (const char*)> func)
    1.89 +{
    1.90 +	cmd_handler = func;
    1.91 +}
    1.92 +
    1.93 +void Console::set_echo(bool echo)
    1.94 +{
    1.95 +	this->echo = echo;
    1.96 +}
    1.97 +
    1.98 +bool Console::get_echo() const
    1.99 +{
   1.100 +	return echo;
   1.101 +}
   1.102 +
   1.103 +void Console::set_visible(bool v)
   1.104 +{
   1.105 +	visible = v;
   1.106 +}
   1.107 +
   1.108 +bool Console::is_visible() const
   1.109 +{
   1.110 +	return visible;
   1.111 +}
   1.112 +
   1.113 +void Console::set_size(int lines, int columns)
   1.114 +{
   1.115 +	nlines = lines;
   1.116 +	ncolumns = columns;
   1.117 +}
   1.118 +
   1.119 +int Console::get_size_lines() const
   1.120 +{
   1.121 +	return nlines;
   1.122 +}
   1.123 +
   1.124 +int Console::get_size_columns() const
   1.125 +{
   1.126 +	return ncolumns;
   1.127 +}
   1.128 +
   1.129 +void Console::set_position(int x, int y, Anchor anchor)
   1.130 +{
   1.131 +	pos_x = x;
   1.132 +	pos_y = y;
   1.133 +	this->anchor = anchor;
   1.134 +}
   1.135 +
   1.136 +bool Console::update()
   1.137 +{
   1.138 +	bool must_redraw = false;
   1.139 +
   1.140 +	while(inpq_front != inpq_back) {
   1.141 +		int c = keybuf[inpq_front];
   1.142 +		inpq_front = (inpq_front + 1) % INPUTQ_SIZE;
   1.143 +
   1.144 +		switch(c) {
   1.145 +		case '\n':
   1.146 +		case '\r':
   1.147 +			if(echo) {
   1.148 +				puts(input.c_str());
   1.149 +				putchar('\n');
   1.150 +			}
   1.151 +			if(!input.empty() && cmd_handler) {
   1.152 +				cmd_handler(input.c_str());
   1.153 +			}
   1.154 +
   1.155 +			hist.push_back(std::move(input));	// move the input string into the history buffer
   1.156 +			if((int)hist.size() > max_hist_lines) {
   1.157 +				hist.pop_front();
   1.158 +			}
   1.159 +			hist_iter_valid = false;
   1.160 +
   1.161 +			set_cursor(0);
   1.162 +			must_redraw = true;
   1.163 +			break;
   1.164 +
   1.165 +		case '\t':
   1.166 +			// TODO: completion
   1.167 +			break;
   1.168 +
   1.169 +		case '\b':
   1.170 +			if(!input.empty()) {
   1.171 +				if(cursor == (int)input.size()) {
   1.172 +					input.pop_back();
   1.173 +					set_cursor(get_cursor() - 1);
   1.174 +					must_redraw = true;
   1.175 +				} else if(cursor > 0) {
   1.176 +					input.erase(cursor - 1, 1);
   1.177 +					set_cursor(get_cursor() - 1);
   1.178 +					must_redraw = true;
   1.179 +				}
   1.180 +			}
   1.181 +			break;
   1.182 +
   1.183 +		case KEY_UP:
   1.184 +			if(!hist.empty()) {
   1.185 +				if(!hist_iter_valid) {
   1.186 +					hist_iter = hist.rbegin();
   1.187 +					hist_iter_valid = true;
   1.188 +					input = *hist_iter;
   1.189 +				} else {
   1.190 +					if(++hist_iter == hist.rend()) {
   1.191 +						--hist_iter;
   1.192 +						break;
   1.193 +					}
   1.194 +					input = *hist_iter;
   1.195 +				}
   1.196 +				set_cursor(input.size());
   1.197 +			}
   1.198 +			break;
   1.199 +
   1.200 +		case KEY_DOWN:
   1.201 +			if(!hist.empty()) {
   1.202 +				if(!hist_iter_valid) {
   1.203 +					hist_iter = hist.rbegin();
   1.204 +					hist_iter_valid = true;
   1.205 +				}
   1.206 +				if(hist_iter != hist.rbegin()) {
   1.207 +					input = *--hist_iter;
   1.208 +					set_cursor(input.size());
   1.209 +				}
   1.210 +			}
   1.211 +			break;
   1.212 +
   1.213 +		case KEY_LEFT:
   1.214 +			if(cursor > 0) {
   1.215 +				set_cursor(get_cursor() - 1);
   1.216 +				must_redraw = true;
   1.217 +			}
   1.218 +			break;
   1.219 +
   1.220 +		case KEY_RIGHT:
   1.221 +			if(cursor < (int)input.size()) {
   1.222 +				set_cursor(get_cursor() + 1);
   1.223 +				must_redraw = true;
   1.224 +			}
   1.225 +			break;
   1.226 +
   1.227 +		case KEY_HOME:
   1.228 +			set_cursor(0);
   1.229 +			must_redraw = true;
   1.230 +			break;
   1.231 +
   1.232 +		case KEY_END:
   1.233 +			set_cursor(input.size());
   1.234 +			must_redraw = true;
   1.235 +			break;
   1.236 +
   1.237 +		case KEY_PGUP:
   1.238 +		case KEY_PGDOWN:
   1.239 +			// TODO scroll output buffer
   1.240 +			break;
   1.241 +
   1.242 +		default:
   1.243 +			if(c < 256 && isprint(c)) {
   1.244 +				if(cursor == (int)input.size()) {
   1.245 +					input.push_back(c);
   1.246 +				} else {
   1.247 +					input.insert(cursor, 1, c);
   1.248 +				}
   1.249 +				set_cursor(get_cursor() + 1);
   1.250 +				must_redraw = true;
   1.251 +			}
   1.252 +		}
   1.253 +	}
   1.254 +	return must_redraw;
   1.255 +}
   1.256 +
   1.257 +void Console::draw() const
   1.258 +{
   1.259 +	if(!font || !visible) return;
   1.260 +	dtx_use_font(font, font_size);
   1.261 +
   1.262 +	std::string buflines;
   1.263 +
   1.264 +	int num_lines = std::min(nlines, (int)output.size());
   1.265 +	auto it = output.cbegin() + (output.size() - num_lines);
   1.266 +
   1.267 +	float max_width = dtx_glyph_width('Q') * ncolumns;
   1.268 +
   1.269 +	while(it != output.cend()) {
   1.270 +		const std::string &line = *it++;
   1.271 +		buflines += line + std::string("\n");
   1.272 +
   1.273 +		//max_width = std::max(max_width, dtx_string_width(line.c_str()));
   1.274 +	}
   1.275 +
   1.276 +	// draw the output box
   1.277 +	float line_height = dtx_line_height();
   1.278 +	float outbox_height = nlines * line_height;
   1.279 +	float console_height = outbox_height + line_height * 1.5;
   1.280 +
   1.281 +	
   1.282 +	int vp[4];
   1.283 +	glGetIntegerv(GL_VIEWPORT, vp);
   1.284 +
   1.285 +	int px, py;
   1.286 +	switch(anchor) {
   1.287 +	case TOP_LEFT:
   1.288 +		px = pos_x;
   1.289 +		py = pos_y;
   1.290 +		break;
   1.291 +
   1.292 +	case BOTTOM_LEFT:
   1.293 +		px = pos_x;
   1.294 +		py = vp[3] - console_height - pos_y;
   1.295 +		break;
   1.296 +
   1.297 +	case CENTER:
   1.298 +		px = (vp[2] - max_width) / 2 + pos_x;
   1.299 +		py = (vp[3] - console_height) / 2 + pos_y;
   1.300 +		break;
   1.301 +	}
   1.302 +
   1.303 +	glMatrixMode(GL_PROJECTION);
   1.304 +	glPushMatrix();
   1.305 +	glLoadIdentity();
   1.306 +	glOrtho(0, vp[2], 0, vp[3], -1, 1);
   1.307 +
   1.308 +	glMatrixMode(GL_MODELVIEW);
   1.309 +	glPushMatrix();
   1.310 +	glLoadIdentity();
   1.311 +	glTranslatef(px, vp[3] - py, 0);
   1.312 +
   1.313 +
   1.314 +	glPushAttrib(GL_ENABLE_BIT);
   1.315 +	glDisable(GL_DEPTH_TEST);
   1.316 +	glDisable(GL_LIGHTING);
   1.317 +	glDisable(GL_STENCIL_TEST);
   1.318 +	glEnable(GL_BLEND);
   1.319 +	glDisable(GL_TEXTURE_2D);
   1.320 +	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   1.321 +
   1.322 +	glEnable(GL_SCISSOR_TEST);
   1.323 +	glScissor(vp[0] + px, vp[1] + (vp[3] - py) - console_height, max_width, console_height);
   1.324 +
   1.325 +	glBegin(GL_QUADS);
   1.326 +	glColor4f(0.1, 0.2, 0.5, 0.7);
   1.327 +	glVertex2f(0, -outbox_height);
   1.328 +	glVertex2f(max_width, -outbox_height);
   1.329 +	glVertex2f(max_width, 0);
   1.330 +	glVertex2f(0, 0);
   1.331 +
   1.332 +	glColor4f(0.5, 0.2, 0.1, 0.7);
   1.333 +	glVertex2f(0, -console_height);
   1.334 +	glVertex2f(max_width, -console_height);
   1.335 +	glVertex2f(max_width, -outbox_height);
   1.336 +	glVertex2f(0, -outbox_height);
   1.337 +	glEnd();
   1.338 +
   1.339 +	// draw the output text
   1.340 +	glPushMatrix();
   1.341 +	glTranslatef(0, -line_height, 0);
   1.342 +	glColor4f(1, 1, 1, 0.7);
   1.343 +	dtx_string(buflines.c_str());
   1.344 +	glPopMatrix();
   1.345 +
   1.346 +	// draw the input line
   1.347 +	glTranslatef(0, -outbox_height - line_height, 0);
   1.348 +
   1.349 +	std::string inpline = prompt + input.substr(input_win);
   1.350 +	dtx_string(inpline.c_str());
   1.351 +	glDisable(GL_TEXTURE_2D);
   1.352 +
   1.353 +	float cursor_x = dtx_char_pos(inpline.c_str(), cursor - input_win + prompt.size());
   1.354 +	glBegin(GL_QUADS);
   1.355 +	glColor4f(1, 1, 1, 0.7);
   1.356 +	glVertex2f(cursor_x, -2);
   1.357 +	glVertex2f(cursor_x + 2, -2);
   1.358 +	glVertex2f(cursor_x + 2, line_height - 2);
   1.359 +	glVertex2f(cursor_x, line_height - 2);
   1.360 +	glEnd();
   1.361 +
   1.362 +	glPopAttrib();
   1.363 +
   1.364 +	glMatrixMode(GL_PROJECTION);
   1.365 +	glPopMatrix();
   1.366 +	glMatrixMode(GL_MODELVIEW);
   1.367 +	glPopMatrix();
   1.368 +}
   1.369 +
   1.370 +void Console::input_key(int key)
   1.371 +{
   1.372 +	keybuf[inpq_back] = key;
   1.373 +	inpq_back = (inpq_back + 1) % INPUTQ_SIZE;
   1.374 +}
   1.375 +
   1.376 +void Console::putchar(char c)
   1.377 +{
   1.378 +	if(output.empty()) {
   1.379 +		output.push_back(std::string(""));
   1.380 +	}
   1.381 +
   1.382 +	if(c == '\n' || c == '\r') {
   1.383 +		output.push_back(std::string(""));
   1.384 +		if((int)output.size() > max_output_lines) {
   1.385 +			output.erase(output.begin());
   1.386 +		}
   1.387 +	} else {
   1.388 +		output.back().push_back(c);
   1.389 +	}
   1.390 +}
   1.391 +
   1.392 +void Console::puts(const char *str)
   1.393 +{
   1.394 +	while(*str) {
   1.395 +		putchar(*str++);
   1.396 +	}
   1.397 +}
   1.398 +
   1.399 +void Console::printf(const char *fmt, ...)
   1.400 +{
   1.401 +	static char buf[1024];
   1.402 +	va_list ap;
   1.403 +
   1.404 +	va_start(ap, fmt);
   1.405 +	vsnprintf(buf, sizeof buf, fmt, ap);
   1.406 +	va_end(ap);
   1.407 +
   1.408 +	puts(buf);
   1.409 +}
   1.410 +
   1.411 +void Console::debug()
   1.412 +{
   1.413 +	fprintf(stderr, "visible: %s\n", visible ? "true" : "false");
   1.414 +	fprintf(stderr, "size: %d lines x %d columns\n", nlines, ncolumns);
   1.415 +	fprintf(stderr, "cursor: %d\n", cursor);
   1.416 +
   1.417 +	int qsize = 0;
   1.418 +	int qidx = inpq_front;
   1.419 +	while(qidx != inpq_back) {
   1.420 +		qsize++;
   1.421 +		qidx = (qidx + 1) % INPUTQ_SIZE;
   1.422 +	}
   1.423 +
   1.424 +	fprintf(stderr, "input queue size: %d\n", qsize);
   1.425 +	fprintf(stderr, "current input line: \"%s\"\n", input.c_str());
   1.426 +	fprintf(stderr, "%d saved inputs in the history (max %d)\n", (int)hist.size(), max_hist_lines);
   1.427 +	auto it = hist.begin();
   1.428 +	int idx = 0;
   1.429 +	while(it != hist.end()) {
   1.430 +		fprintf(stderr, "  h(%d): \"%s\"\n", idx++, it++->c_str());
   1.431 +	}
   1.432 +
   1.433 +	fprintf(stderr, "output buffer (lines: %d/%d):\n", (int)output.size(), max_output_lines);
   1.434 +	for(size_t i=0; i<output.size(); i++) {
   1.435 +		fprintf(stderr, "o(%d): \"%s\"\n", (int)i, output[i].c_str());
   1.436 +	}
   1.437 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/console.h	Fri Sep 26 18:40:15 2014 +0300
     2.3 @@ -0,0 +1,96 @@
     2.4 +#ifndef CONSOLE_H_
     2.5 +#define CONSOLE_H_
     2.6 +
     2.7 +#include <vector>
     2.8 +#include <list>
     2.9 +#include <string>
    2.10 +#include <functional>
    2.11 +#include <drawtext.h>
    2.12 +
    2.13 +#define INPUTQ_SIZE		64
    2.14 +
    2.15 +class Console {
    2.16 +public:
    2.17 +	enum Anchor {TOP_LEFT, BOTTOM_LEFT, CENTER};
    2.18 +
    2.19 +private:
    2.20 +	bool visible;
    2.21 +	int nlines, ncolumns;
    2.22 +	int pos_x, pos_y;
    2.23 +	Anchor anchor;
    2.24 +
    2.25 +	int inpq_front, inpq_back;
    2.26 +	int keybuf[INPUTQ_SIZE];
    2.27 +
    2.28 +	std::string prompt;
    2.29 +	std::string input;	// current input line
    2.30 +	int cursor;
    2.31 +	int input_win;		// first character to show in the input "window"
    2.32 +
    2.33 +	// input history
    2.34 +	int max_hist_lines;
    2.35 +	std::list<std::string> hist;
    2.36 +	bool hist_iter_valid;
    2.37 +	std::list<std::string>::const_reverse_iterator hist_iter;
    2.38 +
    2.39 +	// console output
    2.40 +	int max_output_lines;
    2.41 +	std::vector<std::string> output;
    2.42 +	bool echo;
    2.43 +
    2.44 +	std::function<void (const char*)> cmd_handler;
    2.45 +
    2.46 +	int font_size;
    2.47 +	dtx_font *font;
    2.48 +
    2.49 +	void set_cursor(int x);
    2.50 +	int get_cursor() const;
    2.51 +
    2.52 +public:
    2.53 +	enum {
    2.54 +		KEY_LEFT = 256,
    2.55 +		KEY_RIGHT,
    2.56 +		KEY_UP, KEY_DOWN,
    2.57 +		KEY_INS,
    2.58 +		KEY_DEL,
    2.59 +		KEY_HOME,
    2.60 +		KEY_END,
    2.61 +		KEY_PGUP,
    2.62 +		KEY_PGDOWN
    2.63 +	};
    2.64 +
    2.65 +	Console();
    2.66 +
    2.67 +	void set_font(dtx_font *font, int sz);
    2.68 +	void set_history_size(int hsz);
    2.69 +	void set_output_buffer_size(int sz);
    2.70 +	void set_command_func(std::function<void (const char*)> func);
    2.71 +
    2.72 +	void set_echo(bool echo);
    2.73 +	bool get_echo() const;
    2.74 +
    2.75 +	void show() { set_visible(true); }
    2.76 +	void hide() { set_visible(false); }
    2.77 +	void set_visible(bool v);
    2.78 +	bool is_visible() const;
    2.79 +
    2.80 +	void set_size(int lines, int columns = 80);
    2.81 +	int get_size_lines() const;
    2.82 +	int get_size_columns() const;
    2.83 +
    2.84 +	void set_position(int x, int y, Anchor anchor = TOP_LEFT);
    2.85 +
    2.86 +	// update returns true if what it did makes a redraw necessary
    2.87 +	bool update();
    2.88 +	void draw() const;
    2.89 +
    2.90 +	void input_key(int key);	// send a keystroke to the console
    2.91 +
    2.92 +	void putchar(char c);
    2.93 +	void puts(const char *str);
    2.94 +	void printf(const char *fmt, ...);
    2.95 +
    2.96 +	void debug();
    2.97 +};
    2.98 +
    2.99 +#endif	// CONSOLE_H_
     3.1 --- a/src/game.cc	Fri Sep 26 13:19:22 2014 +0300
     3.2 +++ b/src/game.cc	Fri Sep 26 18:40:15 2014 +0300
     3.3 @@ -6,6 +6,8 @@
     3.4  #include "game.h"
     3.5  #include "goatvr.h"
     3.6  #include "teapot.h"
     3.7 +#include "console.h"
     3.8 +#include "drawtext.h"
     3.9  
    3.10  static void draw_scene();
    3.11  static void material(float r, float g, float b, float roughness);
    3.12 @@ -13,16 +15,23 @@
    3.13  static void create_rtarg(int x, int y);
    3.14  static int next_pow2(int x);
    3.15  
    3.16 +bool opt_separate_walk_look;
    3.17 +
    3.18  static int win_width, win_height;
    3.19  static unsigned int fb_tex;
    3.20  static unsigned int fbo, fb_depth;
    3.21  static int fb_xsz, fb_ysz;
    3.22  static int fb_tex_xsz, fb_tex_ysz;
    3.23  
    3.24 +static unsigned int chess_tex;
    3.25 +
    3.26  static float cam_theta, cam_phi;
    3.27  static Vector3 cam_pos;
    3.28  static bool keystate[256];
    3.29  
    3.30 +static Console con;
    3.31 +static dtx_font *con_font;
    3.32 +
    3.33  bool game_init()
    3.34  {
    3.35  	init_opengl();
    3.36 @@ -35,6 +44,24 @@
    3.37  	glEnable(GL_CULL_FACE);
    3.38  	glEnable(GL_LIGHTING);
    3.39  
    3.40 +	unsigned char chess_pixels[] = {
    3.41 +		0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff,
    3.42 +		0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff
    3.43 +	};
    3.44 +	glGenTextures(1, &chess_tex);
    3.45 +	glBindTexture(GL_TEXTURE_2D, chess_tex);
    3.46 +	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    3.47 +	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    3.48 +	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 4, 4, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, chess_pixels);
    3.49 +
    3.50 +	if(!(con_font = dtx_open_font_glyphmap("data/mono14.glyphmap"))) {
    3.51 +		fprintf(stderr, "failed to open console font\n");
    3.52 +		return false;
    3.53 +	}
    3.54 +	con.set_size(6, 40);
    3.55 +	con.set_font(con_font, 14);
    3.56 +	con.set_position(0, 0, Console::CENTER);
    3.57 +
    3.58  	return true;
    3.59  }
    3.60  
    3.61 @@ -49,7 +76,12 @@
    3.62  	float dt = (tm - prev_upd) / 1000.0;
    3.63  	prev_upd = tm;
    3.64  
    3.65 -	float offs = dt * 1.0;
    3.66 +	if(con.is_visible()) {
    3.67 +		con.update();
    3.68 +		return;
    3.69 +	}
    3.70 +
    3.71 +	float offs = dt * 5.0;
    3.72  	Vector3 dir;
    3.73  
    3.74  	if(keystate['d'] || keystate['D']) {
    3.75 @@ -65,8 +97,13 @@
    3.76  		dir += Vector3(0, 0, offs);
    3.77  	}
    3.78  
    3.79 -	cam_pos.x += dir.x * cos(cam_theta) - dir.y * sin(cam_theta);
    3.80 -	cam_pos.z += dir.x * sin(cam_theta) + dir.y * cos(cam_theta);
    3.81 +	float cos_theta = cos(DEG_TO_RAD(cam_theta));
    3.82 +	float sin_theta = sin(DEG_TO_RAD(cam_theta));
    3.83 +	cam_pos.x += dir.x * cos_theta - dir.z * sin_theta;
    3.84 +	cam_pos.z += dir.x * sin_theta + dir.z * cos_theta;
    3.85 +
    3.86 +	if(!opt_separate_walk_look) {
    3.87 +	}
    3.88  }
    3.89  
    3.90  void game_display()
    3.91 @@ -96,6 +133,7 @@
    3.92  		glTranslatef(-cam_pos.x, -cam_pos.y, -cam_pos.z);
    3.93  
    3.94  		draw_scene();
    3.95 +		con.draw();
    3.96  
    3.97  		vr_end();
    3.98  	}
    3.99 @@ -112,7 +150,7 @@
   3.100  	win_width = x;
   3.101  	win_height = y;
   3.102  
   3.103 -	create_rtarg(vr_geti_def(VR_RENDER_XRES, x), vr_geti_def(VR_RENDER_YRES, y));
   3.104 +	create_rtarg(vr_geti_def(VR_RENDER_XRES, x * 2), vr_geti_def(VR_RENDER_YRES, y));
   3.105  	vr_output_texture(fb_tex, 0, 0, (float)fb_xsz / (float)fb_tex_xsz, (float)fb_ysz / (float)fb_tex_ysz);
   3.106  
   3.107  	/* these might be overriden in VR mode (see game_display) */
   3.108 @@ -125,21 +163,33 @@
   3.109  void game_keyboard(int key, bool pressed)
   3.110  {
   3.111  	if(pressed) {
   3.112 -		switch(key) {
   3.113 -		case 27:
   3.114 -			exit_game();
   3.115 -			break;
   3.116 +		if(con.is_visible()) {
   3.117 +			if(key == 27 || key == '`') {
   3.118 +				con.hide();
   3.119 +			} else {
   3.120 +				con.input_key(key);
   3.121 +			}
   3.122 +		} else {
   3.123 +			switch(key) {
   3.124 +			case 27:
   3.125 +				exit_game();
   3.126 +				break;
   3.127  
   3.128 -		case 'f':
   3.129 -			toggle_hmd_fullscr();
   3.130 -			break;
   3.131 +			case 'f':
   3.132 +				toggle_hmd_fullscr();
   3.133 +				break;
   3.134  
   3.135 -		case 'r':
   3.136 -			vr_recenter();
   3.137 -			break;
   3.138 +			case 'r':
   3.139 +				vr_recenter();
   3.140 +				break;
   3.141  
   3.142 -		default:
   3.143 -			break;
   3.144 +			case '`':
   3.145 +				con.show();
   3.146 +				break;
   3.147 +
   3.148 +			default:
   3.149 +				break;
   3.150 +			}
   3.151  		}
   3.152  	}
   3.153  
   3.154 @@ -197,14 +247,17 @@
   3.155  
   3.156  	glMatrixMode(GL_MODELVIEW);
   3.157  
   3.158 +	glBindTexture(GL_TEXTURE_2D, chess_tex);
   3.159 +	glEnable(GL_TEXTURE_2D);
   3.160  	material(1, 1, 1, 1);
   3.161  	glBegin(GL_QUADS);
   3.162  	glNormal3f(0, 1, 0);
   3.163 -	glVertex3f(-10, 0, 10);
   3.164 -	glVertex3f(10, 0, 10);
   3.165 -	glVertex3f(10, 0, -10);
   3.166 -	glVertex3f(-10, 0, -10);
   3.167 +	glTexCoord2f(0, 0); glVertex3f(-10, 0, 10);
   3.168 +	glTexCoord2f(1, 0); glVertex3f(10, 0, 10);
   3.169 +	glTexCoord2f(1, 1); glVertex3f(10, 0, -10);
   3.170 +	glTexCoord2f(0, 1); glVertex3f(-10, 0, -10);
   3.171  	glEnd();
   3.172 +	glDisable(GL_TEXTURE_2D);
   3.173  
   3.174  	material(1, 1, 1, 0.4);
   3.175  	glPushMatrix();
   3.176 @@ -272,6 +325,8 @@
   3.177  	fb_tex_xsz = next_pow2(fb_xsz);
   3.178  	fb_tex_ysz = next_pow2(fb_ysz);
   3.179  
   3.180 +	printf("creating %dx%d render target (tex size: %dx%d)\n", fb_xsz, fb_ysz, fb_tex_xsz, fb_tex_ysz);
   3.181 +
   3.182  	if(!fbo) {
   3.183  		glGenFramebuffers(1, &fbo);
   3.184  
     4.1 --- a/src/game.h	Fri Sep 26 13:19:22 2014 +0300
     4.2 +++ b/src/game.h	Fri Sep 26 18:40:15 2014 +0300
     4.3 @@ -1,6 +1,8 @@
     4.4  #ifndef GAME_H_
     4.5  #define GAME_H_
     4.6  
     4.7 +extern bool opt_separate_walk_look;
     4.8 +
     4.9  bool game_init();
    4.10  void game_cleanup();
    4.11  
     5.1 --- a/src/main.cc	Fri Sep 26 13:19:22 2014 +0300
     5.2 +++ b/src/main.cc	Fri Sep 26 18:40:15 2014 +0300
     5.3 @@ -124,6 +124,10 @@
     5.4  		game_mouse_motion(ev->motion.x, ev->motion.y);
     5.5  		break;
     5.6  
     5.7 +	case SDL_QUIT:
     5.8 +		exit_game();
     5.9 +		break;
    5.10 +
    5.11  	default:
    5.12  		break;
    5.13  	}
     6.1 --- a/src/opengl.h	Fri Sep 26 13:19:22 2014 +0300
     6.2 +++ b/src/opengl.h	Fri Sep 26 18:40:15 2014 +0300
     6.3 @@ -3,6 +3,8 @@
     6.4  
     6.5  #include <GL/glew.h>
     6.6  
     6.7 +#ifdef __cplusplus
     6.8  bool init_opengl();
     6.9 +#endif
    6.10  
    6.11  #endif	/* OPENGL_H_ */
     7.1 --- a/src/teapot.c	Fri Sep 26 13:19:22 2014 +0300
     7.2 +++ b/src/teapot.c	Fri Sep 26 18:40:15 2014 +0300
     7.3 @@ -1,9 +1,4 @@
     7.4 -#ifndef __APPLE__
     7.5 -#include <GL/gl.h>
     7.6 -#else
     7.7 -#include <OpenGL/gl.h>
     7.8 -#endif
     7.9 -
    7.10 +#include "opengl.h"
    7.11  #include "teapot.h"
    7.12  #include "teapot_data.h"
    7.13  
    7.14 @@ -11,27 +6,41 @@
    7.15  
    7.16  int patch_subdivision = 6;
    7.17  
    7.18 +static int dlist_sub[32];
    7.19 +
    7.20  void bezier_teapot(float scale)
    7.21  {
    7.22  	int i;
    7.23  
    7.24 +	glMatrixMode(GL_MODELVIEW);
    7.25 +
    7.26 +	if(!dlist_sub[patch_subdivision]) {
    7.27 +		dlist_sub[patch_subdivision] = glGenLists(1);
    7.28 +		glNewList(dlist_sub[patch_subdivision], GL_COMPILE);
    7.29 +
    7.30 +		for(i=0; i<NUM_TEAPOT_PATCHES; i++) {
    7.31 +			float flip = teapot_part_flip[i];
    7.32 +			float rot = teapot_part_rot[i];
    7.33 +
    7.34 +			glPushMatrix();
    7.35 +			glTranslatef(0, -3.15 * 0.5, 0);
    7.36 +			glRotatef(rot, 0, 1, 0);
    7.37 +			glScalef(1, 1, flip);
    7.38 +			glRotatef(-90, 1, 0, 0);
    7.39 +
    7.40 +			draw_patch(teapot_verts, teapot_index + i * 16, flip < 0.0 ? 1 : 0, patch_subdivision, patch_subdivision, 1.0);
    7.41 +
    7.42 +			glPopMatrix();
    7.43 +		}
    7.44 +
    7.45 +		glEndList();
    7.46 +	}
    7.47 +
    7.48  	scale /= 2.0;
    7.49 -
    7.50 -	for(i=0; i<NUM_TEAPOT_PATCHES; i++) {
    7.51 -		float flip = teapot_part_flip[i];
    7.52 -		float rot = teapot_part_rot[i];
    7.53 -
    7.54 -		glMatrixMode(GL_MODELVIEW);
    7.55 -		glPushMatrix();
    7.56 -		glTranslatef(0, -3.15 * scale * 0.5, 0);
    7.57 -		glRotatef(rot, 0, 1, 0);
    7.58 -		glScalef(1, 1, flip);
    7.59 -		glRotatef(-90, 1, 0, 0);
    7.60 -
    7.61 -		draw_patch(teapot_verts, teapot_index + i * 16, flip < 0.0 ? 1 : 0, patch_subdivision, patch_subdivision, scale);
    7.62 -
    7.63 -		glPopMatrix();
    7.64 -	}
    7.65 +	glPushMatrix();
    7.66 +	glScalef(scale, scale, scale);
    7.67 +	glCallList(dlist_sub[patch_subdivision]);
    7.68 +	glPopMatrix();
    7.69  }
    7.70  
    7.71  static void draw_patch(struct vec3 *bez_cp, int *index, int flip, int useg, int vseg, float scale)
     8.1 --- a/vrheights.vcxproj	Fri Sep 26 13:19:22 2014 +0300
     8.2 +++ b/vrheights.vcxproj	Fri Sep 26 18:40:15 2014 +0300
     8.3 @@ -52,11 +52,12 @@
     8.4        <WarningLevel>Level3</WarningLevel>
     8.5        <Optimization>Disabled</Optimization>
     8.6        <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     8.7 +      <DisableSpecificWarnings>4244;4305;4996</DisableSpecificWarnings>
     8.8      </ClCompile>
     8.9      <Link>
    8.10 -      <SubSystem>Windows</SubSystem>
    8.11 +      <SubSystem>Console</SubSystem>
    8.12        <GenerateDebugInformation>true</GenerateDebugInformation>
    8.13 -      <AdditionalDependencies>SDL2.lib;SDL2main.lib;opengl32.lib;glew32.lib;libgoatvr.lib;goat3d.lib;%(AdditionalDependencies)</AdditionalDependencies>
    8.14 +      <AdditionalDependencies>SDL2.lib;SDL2main.lib;opengl32.lib;glu32.lib;glew32.lib;libgoatvr.lib;libvmath.lib;libdrawtext.lib;%(AdditionalDependencies)</AdditionalDependencies>
    8.15      </Link>
    8.16    </ItemDefinitionGroup>
    8.17    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    8.18 @@ -68,23 +69,31 @@
    8.19        <FunctionLevelLinking>true</FunctionLevelLinking>
    8.20        <IntrinsicFunctions>true</IntrinsicFunctions>
    8.21        <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    8.22 +      <DisableSpecificWarnings>4244;4305;4996</DisableSpecificWarnings>
    8.23      </ClCompile>
    8.24      <Link>
    8.25        <SubSystem>Windows</SubSystem>
    8.26        <GenerateDebugInformation>true</GenerateDebugInformation>
    8.27        <EnableCOMDATFolding>true</EnableCOMDATFolding>
    8.28        <OptimizeReferences>true</OptimizeReferences>
    8.29 -      <AdditionalDependencies>SDL2.lib;SDL2main.lib;opengl32.lib;glew32.lib;libgoatvr.lib;goat3d.lib;%(AdditionalDependencies)</AdditionalDependencies>
    8.30 +      <AdditionalDependencies>SDL2.lib;SDL2main.lib;opengl32.lib;glu32.lib;glew32.lib;libgoatvr.lib;libvmath.lib;libdrawtext.lib;%(AdditionalDependencies)</AdditionalDependencies>
    8.31      </Link>
    8.32    </ItemDefinitionGroup>
    8.33    <ItemGroup>
    8.34 +    <ClCompile Include="src\bezmath.c" />
    8.35 +    <ClCompile Include="src\console.cc" />
    8.36      <ClCompile Include="src\game.cc" />
    8.37      <ClCompile Include="src\main.cc" />
    8.38      <ClCompile Include="src\opengl.cc" />
    8.39 +    <ClCompile Include="src\teapot.c" />
    8.40    </ItemGroup>
    8.41    <ItemGroup>
    8.42 +    <ClInclude Include="src\bezmath.h" />
    8.43 +    <ClInclude Include="src\console.h" />
    8.44      <ClInclude Include="src\game.h" />
    8.45      <ClInclude Include="src\opengl.h" />
    8.46 +    <ClInclude Include="src\teapot.h" />
    8.47 +    <ClInclude Include="src\teapot_data.h" />
    8.48    </ItemGroup>
    8.49    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
    8.50    <ImportGroup Label="ExtensionTargets">
     9.1 --- a/vrheights.vcxproj.filters	Fri Sep 26 13:19:22 2014 +0300
     9.2 +++ b/vrheights.vcxproj.filters	Fri Sep 26 18:40:15 2014 +0300
     9.3 @@ -16,6 +16,15 @@
     9.4      <ClCompile Include="src\opengl.cc">
     9.5        <Filter>src</Filter>
     9.6      </ClCompile>
     9.7 +    <ClCompile Include="src\bezmath.c">
     9.8 +      <Filter>src</Filter>
     9.9 +    </ClCompile>
    9.10 +    <ClCompile Include="src\teapot.c">
    9.11 +      <Filter>src</Filter>
    9.12 +    </ClCompile>
    9.13 +    <ClCompile Include="src\console.cc">
    9.14 +      <Filter>src</Filter>
    9.15 +    </ClCompile>
    9.16    </ItemGroup>
    9.17    <ItemGroup>
    9.18      <ClInclude Include="src\game.h">
    9.19 @@ -24,5 +33,17 @@
    9.20      <ClInclude Include="src\opengl.h">
    9.21        <Filter>src</Filter>
    9.22      </ClInclude>
    9.23 +    <ClInclude Include="src\bezmath.h">
    9.24 +      <Filter>src</Filter>
    9.25 +    </ClInclude>
    9.26 +    <ClInclude Include="src\teapot.h">
    9.27 +      <Filter>src</Filter>
    9.28 +    </ClInclude>
    9.29 +    <ClInclude Include="src\teapot_data.h">
    9.30 +      <Filter>src</Filter>
    9.31 +    </ClInclude>
    9.32 +    <ClInclude Include="src\console.h">
    9.33 +      <Filter>src</Filter>
    9.34 +    </ClInclude>
    9.35    </ItemGroup>
    9.36  </Project>
    9.37 \ No newline at end of file