1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file. 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <assert.h> 6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <math.h> 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <ppapi/c/ppb_input_event.h> 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <ppapi/cpp/input_event.h> 9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <ppapi/cpp/var.h> 10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <ppapi/cpp/var_array.h> 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <ppapi/cpp/var_array_buffer.h> 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <ppapi/cpp/var_dictionary.h> 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <pthread.h> 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <stdio.h> 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <stdlib.h> 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <string.h> 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <sys/time.h> 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <unistd.h> 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <algorithm> 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <string> 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "ppapi_simple/ps.h" 243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "ppapi_simple/ps_context_2d.h" 253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "ppapi_simple/ps_event.h" 263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "ppapi_simple/ps_interface.h" 273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "ppapi_simple/ps_main.h" 28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "sdk_util/macros.h" 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "sdk_util/thread_pool.h" 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 31ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochusing namespace sdk_util; // For sdk_util::ThreadPool 32ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Global properties used to setup Earth demo. 34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace { 35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst float kPI = M_PI; 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst float kTwoPI = kPI * 2.0f; 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst float kOneOverPI = 1.0f / kPI; 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst float kOneOver2PI = 1.0f / kTwoPI; 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst float kOneOver255 = 1.0f / 255.0f; 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kArcCosineTableSize = 4096; 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kFramesToBenchmark = 100; 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst float kZoomMin = 1.0f; 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst float kZoomMax = 50.0f; 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst float kWheelSpeed = 2.0f; 45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst float kLightMin = 0.0f; 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst float kLightMax = 2.0f; 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Timer helper for benchmarking. Returns seconds elapsed since program start, 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// as a double. 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochtimeval start_tv; 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint start_tv_retv = gettimeofday(&start_tv, NULL); 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochinline double getseconds() { 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const double usec_to_sec = 0.000001; 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch timeval tv; 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if ((0 == start_tv_retv) && (0 == gettimeofday(&tv, NULL))) 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (tv.tv_sec - start_tv.tv_sec) + tv.tv_usec * usec_to_sec; 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return 0.0; 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// RGBA helper functions, used for extracting color from RGBA source image. 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochinline float ExtractR(uint32_t c) { 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return static_cast<float>(c & 0xFF) * kOneOver255; 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochinline float ExtractG(uint32_t c) { 67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return static_cast<float>((c & 0xFF00) >> 8) * kOneOver255; 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochinline float ExtractB(uint32_t c) { 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return static_cast<float>((c & 0xFF0000) >> 16) * kOneOver255; 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// BGRA helper function, for constructing a pixel for a BGRA buffer. 753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)inline uint32_t MakeBGRA(uint32_t b, uint32_t g, uint32_t r, uint32_t a) { 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)); 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// simple container for earth texture 80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstruct Texture { 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int width, height; 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch uint32_t* pixels; 83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Texture(int w, int h) : width(w), height(h) { 84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pixels = new uint32_t[w * h]; 85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch memset(pixels, 0, sizeof(uint32_t) * w * h); 86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch explicit Texture(int w, int h, uint32_t* p) : width(w), height(h) { 88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pixels = new uint32_t[w * h]; 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch memcpy(pixels, p, sizeof(uint32_t) * w * h); 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ~Texture() { delete[] pixels; } 92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DISALLOW_COPY_AND_ASSIGN(Texture); 94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstruct ArcCosine { 99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // slightly larger table so we can interpolate beyond table size 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float table[kArcCosineTableSize + 2]; 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float TableLerp(float x); 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ArcCosine(); 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochArcCosine::ArcCosine() { 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // build a slightly larger table to allow for numeric imprecision 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (int i = 0; i < (kArcCosineTableSize + 2); ++i) { 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float f = static_cast<float>(i) / kArcCosineTableSize; 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch f = f * 2.0f - 1.0f; 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch table[i] = acos(f); 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// looks up acos(f) using a table and lerping between entries 115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// (it is expected that input f is between -1 and 1) 116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochfloat ArcCosine::TableLerp(float f) { 117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float x = (f + 1.0f) * 0.5f; 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch x = x * kArcCosineTableSize; 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int ix = static_cast<int>(x); 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float fx = static_cast<float>(ix); 121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float dx = x - fx; 122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float af = table[ix]; 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float af2 = table[ix + 1]; 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return af + (af2 - af) * dx; 125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Helper functions for quick but approximate sqrt. 128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochunion Convert { 129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float f; 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int i; 131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Convert(int x) { i = x; } 132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Convert(float x) { f = x; } 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int AsInt() { return i; } 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float AsFloat() { return f; } 135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochinline const int AsInteger(const float f) { 138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Convert u(f); 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return u.AsInt(); 140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochinline const float AsFloat(const int i) { 143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Convert u(i); 144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return u.AsFloat(); 145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst long int kOneAsInteger = AsInteger(1.0f); 148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochinline float inline_quick_sqrt(float x) { 150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int i; 151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch i = (AsInteger(x) >> 1) + (kOneAsInteger >> 1); 152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return AsFloat(i); 153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochinline float inline_sqrt(float x) { 156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float y; 157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch y = inline_quick_sqrt(x); 158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch y = (y * y + x) / (2.0f * y); 159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch y = (y * y + x) / (2.0f * y); 160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return y; 161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// takes a -0..1+ color, clamps it to 0..1 and maps it to 0..255 integer 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochinline uint32_t Clamp255(float x) { 165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (x < 0.0f) { 166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch x = 0.0f; 167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else if (x > 1.0f) { 168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch x = 1.0f; 169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return static_cast<uint32_t>(x * 255.0f); 171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace 173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The main object that runs the Earth demo. 1763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochclass Planet { 177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public: 1783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch Planet(); 179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual ~Planet(); 1803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Runs a tick of the simulations, update 2D output. 1813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch void Update(); 1823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Handle event from user, or message from JS. 1833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch void HandleEvent(PSEvent* ps_event); 184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private: 186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Methods prefixed with 'w' are run on worker threads. 187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch uint32_t* wGetAddr(int x, int y); 188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void wRenderPixelSpan(int x0, int x1, int y); 189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void wMakeRect(int r, int *x, int *y, int *w, int *h); 190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void wRenderRect(int x0, int y0, int x1, int y1); 191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void wRenderRegion(int region); 192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch static void wRenderRegionEntry(int region, void *thiz); 193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // These methods are only called by the main thread. 195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void CacheCalcs(); 196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void SetPlanetXYZR(float x, float y, float z, float r); 197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void SetPlanetPole(float x, float y, float z); 198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void SetPlanetEquator(float x, float y, float z); 199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void SetPlanetSpin(float x, float y); 200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void SetEyeXYZ(float x, float y, float z); 201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void SetLightXYZ(float x, float y, float z); 202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void SetAmbientRGB(float r, float g, float b); 203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void SetDiffuseRGB(float r, float g, float b); 204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void SetZoom(float zoom); 205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void SetLight(float zoom); 206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void SetTexture(const std::string& name, int width, int height, 207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch uint32_t* pixels); 2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) void SpinPlanet(pp::Point new_point, pp::Point last_point); 209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void Reset(); 2113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch void RequestTextures(); 212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void UpdateSim(); 213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void Render(); 214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void Draw(); 215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void StartBenchmark(); 216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void EndBenchmark(); 217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Post a small key-value message to update JS. 218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void PostUpdateMessage(const char* message_name, double value); 219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // User Interface settings. These settings are controlled via html 221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // controls or via user input. 222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float ui_light_; 223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float ui_zoom_; 224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float ui_spin_x_; 225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float ui_spin_y_; 2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pp::Point ui_last_point_; 227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Various settings for position & orientation of planet. Do not change 229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // these variables, instead use SetPlanet*() functions. 230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float planet_radius_; 231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float planet_spin_x_; 232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float planet_spin_y_; 233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float planet_x_, planet_y_, planet_z_; 234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float planet_pole_x_, planet_pole_y_, planet_pole_z_; 235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float planet_equator_x_, planet_equator_y_, planet_equator_z_; 236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Observer's eye. Do not change these variables, instead use SetEyeXYZ(). 238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float eye_x_, eye_y_, eye_z_; 239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Light position, ambient and diffuse settings. Do not change these 241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // variables, instead use SetLightXYZ(), SetAmbientRGB() and SetDiffuseRGB(). 242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float light_x_, light_y_, light_z_; 243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float diffuse_r_, diffuse_g_, diffuse_b_; 244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float ambient_r_, ambient_g_, ambient_b_; 245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Cached calculations. Do not change these variables - they are updated by 247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // CacheCalcs() function. 248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float planet_xyz_; 249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float planet_pole_x_equator_x_; 250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float planet_pole_x_equator_y_; 251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float planet_pole_x_equator_z_; 252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float planet_radius2_; 253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float planet_one_over_radius_; 254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float eye_xyz_; 255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Source texture (earth map). 257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Texture* base_tex_; 258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Texture* night_tex_; 259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int width_for_tex_; 260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int height_for_tex_; 261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Quick ArcCos helper. 263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ArcCosine acos_; 264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Misc. 2663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch PSContext2D_t* ps_context_; 267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int num_threads_; 268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ThreadPool* workers_; 269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool benchmarking_; 2703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch int benchmark_frame_counter_; 271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch double benchmark_start_time_; 272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch double benchmark_end_time_; 273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid Planet::RequestTextures() { 277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Request a set of images from JS. After images are loaded by JS, a 278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // message from JS -> NaCl will arrive containing the pixel data. See 279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // HandleMessage() method in this file. 280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pp::VarDictionary message; 281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch message.Set("message", "request_textures"); 282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pp::VarArray names; 283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch names.Set(0, "earth.jpg"); 284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch names.Set(1, "earthnight.jpg"); 285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch message.Set("names", names); 2863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch PSInterfaceMessaging()->PostMessage(PSGetInstanceId(), message.pp_var()); 287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::Reset() { 290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Reset has to first fill in all variables with valid floats, so 291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // CacheCalcs() doesn't potentially propagate NaNs when calling Set*() 292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // functions further below. 293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_radius_ = 1.0f; 294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_spin_x_ = 0.0f; 295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_spin_y_ = 0.0f; 296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_x_ = 0.0f; 297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_y_ = 0.0f; 298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_z_ = 0.0f; 299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_pole_x_ = 0.0f; 300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_pole_y_ = 0.0f; 301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_pole_z_ = 0.0f; 302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_equator_x_ = 0.0f; 303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_equator_y_ = 0.0f; 304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_equator_z_ = 0.0f; 305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch eye_x_ = 0.0f; 306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch eye_y_ = 0.0f; 307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch eye_z_ = 0.0f; 308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch light_x_ = 0.0f; 309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch light_y_ = 0.0f; 310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch light_z_ = 0.0f; 311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch diffuse_r_ = 0.0f; 312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch diffuse_g_ = 0.0f; 313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch diffuse_b_ = 0.0f; 314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ambient_r_ = 0.0f; 315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ambient_g_ = 0.0f; 316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ambient_b_ = 0.0f; 317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_xyz_ = 0.0f; 318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_pole_x_equator_x_ = 0.0f; 319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_pole_x_equator_y_ = 0.0f; 320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_pole_x_equator_z_ = 0.0f; 321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_radius2_ = 0.0f; 322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_one_over_radius_ = 0.0f; 323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch eye_xyz_ = 0.0f; 324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ui_zoom_ = 14.0f; 325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ui_light_ = 1.0f; 326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ui_spin_x_ = 0.01f; 327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ui_spin_y_ = 0.0f; 3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ui_last_point_ = pp::Point(0, 0); 329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Set up reasonable default values. 331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetPlanetXYZR(0.0f, 0.0f, 48.0f, 4.0f); 332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetEyeXYZ(0.0f, 0.0f, -ui_zoom_); 333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetLightXYZ(-60.0f, -30.0f, 0.0f); 334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetAmbientRGB(0.05f, 0.05f, 0.05f); 335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetDiffuseRGB(0.8f, 0.8f, 0.8f); 336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetPlanetPole(0.0f, 1.0f, 0.0f); 337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetPlanetEquator(1.0f, 0.0f, 0.0f); 338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetPlanetSpin(kPI / 2.0f, kPI / 2.0f); 339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetZoom(ui_zoom_); 340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetLight(ui_light_); 341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Send UI values to JS to reset html sliders. 343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch PostUpdateMessage("set_zoom", ui_zoom_); 344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch PostUpdateMessage("set_light", ui_light_); 345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochPlanet::Planet() : base_tex_(NULL), night_tex_(NULL), num_threads_(0), 3493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch benchmarking_(false), benchmark_frame_counter_(0) { 350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Reset(); 3523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch RequestTextures(); 353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // By default, render from the dispatch thread. 354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch workers_ = new ThreadPool(num_threads_); 3553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch PSEventSetFilter(PSE_ALL); 3563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ps_context_ = PSContext2DAllocate(PP_IMAGEDATAFORMAT_BGRA_PREMUL); 357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochPlanet::~Planet() { 360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delete workers_; 3613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch PSContext2DFree(ps_context_); 362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Given a region r, derive a rectangle. 365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// This rectangle shouldn't overlap with work being done by other workers. 366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// If multithreading, this function is only called by the worker threads. 367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::wMakeRect(int r, int *x, int *y, int *w, int *h) { 368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *x = 0; 3693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch *w = ps_context_->width; 3703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch *y = r; 3713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch *h = 1; 372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochinline uint32_t* Planet::wGetAddr(int x, int y) { 3763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return ps_context_->data + x + y * ps_context_->stride / sizeof(uint32_t); 377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// This is the meat of the ray tracer. Given a pixel span (x0, x1) on 380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// scanline y, shoot rays into the scene and render what they hit. Use 381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// scanline coherence to do a few optimizations 382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::wRenderPixelSpan(int x0, int x1, int y) { 383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!base_tex_ || !night_tex_) 384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 3853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const int kColorBlack = MakeBGRA(0, 0, 0, 0xFF); 386ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch float width = ps_context_->width; 387ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch float height = ps_context_->height; 388ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch float min_dim = width < height ? width : height; 389ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch float offset_x = width < height ? 0 : (width - min_dim) * 0.5f; 390ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch float offset_y = width < height ? (height - min_dim) * 0.5f : 0; 391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float y0 = eye_y_; 392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float z0 = eye_z_; 393ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch float y1 = (static_cast<float>(y - offset_y) / min_dim) * 2.0f - 1.0f; 394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float z1 = 0.0f; 395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float dy = (y1 - y0); 396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float dz = (z1 - z0); 397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float dy_dy_dz_dz = dy * dy + dz * dz; 398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float two_dy_y0_y_two_dz_z0_z = 2.0f * dy * (y0 - planet_y_) + 399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2.0f * dz * (z0 - planet_z_); 400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float planet_xyz_eye_xyz = planet_xyz_ + eye_xyz_; 401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float y_y0_z_z0 = planet_y_ * y0 + planet_z_ * z0; 402ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch float oowidth = 1.0f / min_dim; 403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch uint32_t* pixels = this->wGetAddr(x0, y); 404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (int x = x0; x <= x1; ++x) { 405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // scan normalized screen -1..1 406ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch float x1 = (static_cast<float>(x - offset_x) * oowidth) * 2.0f - 1.0f; 407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // eye 408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float x0 = eye_x_; 409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // delta from screen to eye 410eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float dx = (x1 - x0); 411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // build a, b, c 412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float a = dx * dx + dy_dy_dz_dz; 413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float b = 2.0f * dx * (x0 - planet_x_) + two_dy_y0_y_two_dz_z0_z; 414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float c = planet_xyz_eye_xyz + 415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch -2.0f * (planet_x_ * x0 + y_y0_z_z0) - (planet_radius2_); 416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // calculate discriminant 417eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float disc = b * b - 4.0f * a * c; 418eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Did ray hit the sphere? 420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (disc < 0.0f) { 421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *pixels = kColorBlack; 422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ++pixels; 423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch continue; 424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // calc parametric t value 427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float t = (-b - inline_sqrt(disc)) / (2.0f * a); 428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float px = x0 + t * dx; 429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float py = y0 + t * dy; 430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float pz = z0 + t * dz; 431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float nx = (px - planet_x_) * planet_one_over_radius_; 432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float ny = (py - planet_y_) * planet_one_over_radius_; 433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float nz = (pz - planet_z_) * planet_one_over_radius_; 434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Misc raytrace calculations. 436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float Lx = (light_x_ - px); 437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float Ly = (light_y_ - py); 438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float Lz = (light_z_ - pz); 439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float Lq = 1.0f / inline_quick_sqrt(Lx * Lx + Ly * Ly + Lz * Lz); 440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Lx *= Lq; 441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Ly *= Lq; 442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Lz *= Lq; 443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float d = (Lx * nx + Ly * ny + Lz * nz); 444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float pr = (diffuse_r_ * d) + ambient_r_; 445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float pg = (diffuse_g_ * d) + ambient_g_; 446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float pb = (diffuse_b_ * d) + ambient_b_; 447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float ds = -(nx * planet_pole_x_ + 448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ny * planet_pole_y_ + 449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch nz * planet_pole_z_); 450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float ang = acos_.TableLerp(ds); 451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float v = ang * kOneOverPI; 452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float dp = planet_equator_x_ * nx + 453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_equator_y_ * ny + 454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_equator_z_ * nz; 455cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float w = dp / sinf(ang); 456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (w > 1.0f) w = 1.0f; 457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (w < -1.0f) w = -1.0f; 458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float th = acos_.TableLerp(w) * kOneOver2PI; 459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float dps = planet_pole_x_equator_x_ * nx + 460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_pole_x_equator_y_ * ny + 461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_pole_x_equator_z_ * nz; 462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float u; 463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (dps < 0.0f) 464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch u = th; 465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch else 466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch u = 1.0f - th; 467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 468eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Look up daylight texel. 469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int tx = static_cast<int>(u * base_tex_->width); 470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int ty = static_cast<int>(v * base_tex_->height); 471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int offset = tx + ty * base_tex_->width; 472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch uint32_t base_texel = base_tex_->pixels[offset]; 473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float tr = ExtractR(base_texel); 474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float tg = ExtractG(base_texel); 475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float tb = ExtractB(base_texel); 476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float ipr = 1.0f - pr; 478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (ipr < 0.0f) ipr = 0.0f; 479eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float ipg = 1.0f - pg; 480eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (ipg < 0.0f) ipg = 0.0f; 481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float ipb = 1.0f - pb; 482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (ipb < 0.0f) ipb = 0.0f; 483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Look up night texel. 485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int nix = static_cast<int>(u * night_tex_->width); 486eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int niy = static_cast<int>(v * night_tex_->height); 487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int noffset = nix + niy * night_tex_->width; 488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch uint32_t night_texel = night_tex_->pixels[noffset]; 489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float nr = ExtractR(night_texel); 490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float ng = ExtractG(night_texel); 491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float nb = ExtractB(night_texel); 492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Final color value is lerp between day and night texels. 494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch unsigned int ir = Clamp255(pr * tr + nr * ipr); 495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch unsigned int ig = Clamp255(pg * tg + ng * ipg); 496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch unsigned int ib = Clamp255(pb * tb + nb * ipb); 497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 4983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) unsigned int color = MakeBGRA(ib, ig, ir, 0xFF); 499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *pixels = color; 501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ++pixels; 502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Renders a rectangular area of the screen, scan line at a time 506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::wRenderRect(int x, int y, int w, int h) { 507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (int j = y; j < (y + h); ++j) { 508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this->wRenderPixelSpan(x, x + w - 1, j); 509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// If multithreading, this function is only called by the worker threads. 513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::wRenderRegion(int region) { 514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // convert region # into x0, y0, x1, y1 rectangle 515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int x, y, w, h; 516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch wMakeRect(region, &x, &y, &w, &h); 517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // render this rectangle 518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch wRenderRect(x, y, w, h); 519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Entry point for worker thread. Can't pass a member function around, so we 522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// have to do this little round-about. 523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::wRenderRegionEntry(int region, void* thiz) { 524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch static_cast<Planet*>(thiz)->wRenderRegion(region); 525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Renders the planet, dispatching the work to multiple threads. 528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::Render() { 5293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch workers_->Dispatch(ps_context_->height, wRenderRegionEntry, this); 530eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 531eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Pre-calculations to make inner loops faster. 533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::CacheCalcs() { 534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_xyz_ = planet_x_ * planet_x_ + 535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_y_ * planet_y_ + 536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_z_ * planet_z_; 537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_radius2_ = planet_radius_ * planet_radius_; 538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_one_over_radius_ = 1.0f / planet_radius_; 539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch eye_xyz_ = eye_x_ * eye_x_ + eye_y_ * eye_y_ + eye_z_ * eye_z_; 540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // spin vector from center->equator 541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_equator_x_ = cos(planet_spin_x_); 542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_equator_y_ = 0.0f; 543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_equator_z_ = sin(planet_spin_x_); 544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // cache cross product of pole & equator 546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_pole_x_equator_x_ = planet_pole_y_ * planet_equator_z_ - 547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_pole_z_ * planet_equator_y_; 548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_pole_x_equator_y_ = planet_pole_z_ * planet_equator_x_ - 549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_pole_x_ * planet_equator_z_; 550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_pole_x_equator_z_ = planet_pole_x_ * planet_equator_y_ - 551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_pole_y_ * planet_equator_x_; 552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::SetPlanetXYZR(float x, float y, float z, float r) { 555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_x_ = x; 556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_y_ = y; 557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_z_ = z; 558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_radius_ = r; 559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CacheCalcs(); 560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::SetEyeXYZ(float x, float y, float z) { 563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch eye_x_ = x; 564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch eye_y_ = y; 565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch eye_z_ = z; 566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CacheCalcs(); 567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::SetLightXYZ(float x, float y, float z) { 570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch light_x_ = x; 571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch light_y_ = y; 572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch light_z_ = z; 573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CacheCalcs(); 574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 576eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::SetAmbientRGB(float r, float g, float b) { 577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ambient_r_ = r; 578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ambient_g_ = g; 579eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ambient_b_ = b; 580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CacheCalcs(); 581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 582eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::SetDiffuseRGB(float r, float g, float b) { 584eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch diffuse_r_ = r; 585eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch diffuse_g_ = g; 586eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch diffuse_b_ = b; 587eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CacheCalcs(); 588eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 589eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::SetPlanetPole(float x, float y, float z) { 591eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_pole_x_ = x; 592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_pole_y_ = y; 593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_pole_z_ = z; 594eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CacheCalcs(); 595eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 596eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::SetPlanetEquator(float x, float y, float z) { 598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // This is really over-ridden by spin at the momenent. 599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_equator_x_ = x; 600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_equator_y_ = y; 601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_equator_z_ = z; 602eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CacheCalcs(); 603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::SetPlanetSpin(float x, float y) { 606eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_spin_x_ = x; 607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch planet_spin_y_ = y; 608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CacheCalcs(); 609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 610eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 611eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Run a simple sim to spin the planet. Update loop is run once per frame. 612eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Called from the main thread only and only when the worker threads are idle. 613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::UpdateSim() { 614eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float x = planet_spin_x_ + ui_spin_x_; 615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float y = planet_spin_y_ + ui_spin_y_; 616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // keep in nice range 617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (x > (kPI * 2.0f)) 618eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch x = x - kPI * 2.0f; 619eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch else if (x < (-kPI * 2.0f)) 620eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch x = x + kPI * 2.0f; 621eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (y > (kPI * 2.0f)) 622eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch y = y - kPI * 2.0f; 623eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch else if (y < (-kPI * 2.0f)) 624eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch y = y + kPI * 2.0f; 625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetPlanetSpin(x, y); 626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 627eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 628eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::StartBenchmark() { 629eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // For more consistent benchmark numbers, reset to default state. 630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Reset(); 631eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch printf("Benchmark started...\n"); 632eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch benchmark_frame_counter_ = kFramesToBenchmark; 633eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch benchmarking_ = true; 634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch benchmark_start_time_ = getseconds(); 635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 636eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::EndBenchmark() { 638eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch benchmark_end_time_ = getseconds(); 639eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch printf("Benchmark ended... time: %2.5f\n", 640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch benchmark_end_time_ - benchmark_start_time_); 641eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch benchmarking_ = false; 642eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch benchmark_frame_counter_ = 0; 643eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch double total_time = benchmark_end_time_ - benchmark_start_time_; 644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Send benchmark result to JS. 645eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch PostUpdateMessage("benchmark_result", total_time); 646eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 647eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::SetZoom(float zoom) { 649eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ui_zoom_ = std::min(kZoomMax, std::max(kZoomMin, zoom)); 650eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetEyeXYZ(0.0f, 0.0f, -ui_zoom_); 651eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 653eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::SetLight(float light) { 654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ui_light_ = std::min(kLightMax, std::max(kLightMin, light)); 655eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetDiffuseRGB(0.8f * ui_light_, 0.8f * ui_light_, 0.8f * ui_light_); 656eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetAmbientRGB(0.4f * ui_light_, 0.4f * ui_light_, 0.4f * ui_light_); 657eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 658eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 659eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::SetTexture(const std::string& name, int width, int height, 660eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch uint32_t* pixels) { 661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (pixels) { 662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (name == "earth.jpg") { 663eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delete base_tex_; 664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base_tex_ = new Texture(width, height, pixels); 665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else if (name == "earthnight.jpg") { 666eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delete night_tex_; 667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch night_tex_ = new Texture(width, height, pixels); 668eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 6724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Planet::SpinPlanet(pp::Point new_point, pp::Point last_point) { 6734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) float delta_x = static_cast<float>(new_point.x() - last_point.x()); 6744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) float delta_y = static_cast<float>(new_point.y() - last_point.y()); 6754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) float spin_x = std::min(10.0f, std::max(-10.0f, delta_x * 0.5f)); 6764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) float spin_y = std::min(10.0f, std::max(-10.0f, delta_y * 0.5f)); 6774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ui_spin_x_ = spin_x / 100.0f; 6784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ui_spin_y_ = spin_y / 100.0f; 6794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ui_last_point_ = new_point; 6804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 6814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 6823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// Handle input events from the user and messages from JS. 6833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid Planet::HandleEvent(PSEvent* ps_event) { 6843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Give the 2D context a chance to process the event. 6853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (0 != PSContext2DHandleEvent(ps_context_, ps_event)) 6863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 6873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (ps_event->type == PSE_INSTANCE_HANDLEINPUT) { 6883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Convert Pepper Simple event to a PPAPI C++ event 6893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch pp::InputEvent event(ps_event->as_resource); 6903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch switch (event.GetType()) { 6913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch case PP_INPUTEVENT_TYPE_KEYDOWN: { 6923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch pp::KeyboardInputEvent key(event); 6933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch uint32_t key_code = key.GetKeyCode(); 6943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (key_code == 84) // 't' key 6953240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (!benchmarking_) 6963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch StartBenchmark(); 6973240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch break; 698eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 6994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case PP_INPUTEVENT_TYPE_MOUSEDOWN: 7004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case PP_INPUTEVENT_TYPE_MOUSEMOVE: { 7013240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch pp::MouseInputEvent mouse = pp::MouseInputEvent(event); 7023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (mouse.GetModifiers() & PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) { 7034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (event.GetType() == PP_INPUTEVENT_TYPE_MOUSEDOWN) 7044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SpinPlanet(mouse.GetPosition(), mouse.GetPosition()); 7054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) else 7064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SpinPlanet(mouse.GetPosition(), ui_last_point_); 7073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 7083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch break; 7093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 7103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch case PP_INPUTEVENT_TYPE_WHEEL: { 7113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch pp::WheelInputEvent wheel = pp::WheelInputEvent(event); 7123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch PP_FloatPoint ticks = wheel.GetTicks(); 7133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch SetZoom(ui_zoom_ + (ticks.x + ticks.y) * kWheelSpeed); 7143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Update html slider by sending update message to JS. 7153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch PostUpdateMessage("set_zoom", ui_zoom_); 7163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch break; 7173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 7184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case PP_INPUTEVENT_TYPE_TOUCHSTART: 7194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case PP_INPUTEVENT_TYPE_TOUCHMOVE: { 7204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pp::TouchInputEvent touches = pp::TouchInputEvent(event); 7214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uint32_t count = touches.GetTouchCount(PP_TOUCHLIST_TYPE_TOUCHES); 7224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (count > 0) { 7234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Use first touch point to spin planet. 7244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pp::TouchPoint touch = 7254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) touches.GetTouchByIndex(PP_TOUCHLIST_TYPE_TOUCHES, 0); 7264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pp::Point screen_point(touch.position().x(), 7274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) touch.position().y()); 7284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (event.GetType() == PP_INPUTEVENT_TYPE_TOUCHSTART) 7294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SpinPlanet(screen_point, screen_point); 7304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) else 7314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SpinPlanet(screen_point, ui_last_point_); 7324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 7334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 7344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 7353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch default: 7363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch break; 737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 7383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } else if (ps_event->type == PSE_INSTANCE_HANDLEMESSAGE) { 7393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Convert Pepper Simple message to PPAPI C++ vars 7403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch pp::Var var(ps_event->as_var); 7413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (var.is_dictionary()) { 7423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch pp::VarDictionary dictionary(var); 7433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch std::string message = dictionary.Get("message").AsString(); 7443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (message == "run benchmark" && !benchmarking_) { 7453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch StartBenchmark(); 7463240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } else if (message == "set_light") { 7473240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch SetLight(static_cast<float>(dictionary.Get("value").AsDouble())); 7483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } else if (message == "set_zoom") { 7493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch SetZoom(static_cast<float>(dictionary.Get("value").AsDouble())); 7503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } else if (message == "set_threads") { 7513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch int threads = dictionary.Get("value").AsInt(); 7523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch delete workers_; 7533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch workers_ = new ThreadPool(threads); 7543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } else if (message == "texture") { 7553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch std::string name = dictionary.Get("name").AsString(); 7563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch int width = dictionary.Get("width").AsInt(); 7573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch int height = dictionary.Get("height").AsInt(); 7583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch pp::VarArrayBuffer array_buffer(dictionary.Get("data")); 7593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (!name.empty() && !array_buffer.is_null()) { 7603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (width > 0 && height > 0) { 7613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch uint32_t* pixels = static_cast<uint32_t*>(array_buffer.Map()); 7623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch SetTexture(name, width, height, pixels); 7633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch array_buffer.Unmap(); 7643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 7653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 7663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 7673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } else { 7683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch printf("Handle message unknown type: %s\n", var.DebugString().c_str()); 769eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 770eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 771eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 772eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 773eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// PostUpdateMessage() helper function for sending small messages to JS. 774eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::PostUpdateMessage(const char* message_name, double value) { 775eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pp::VarDictionary message; 776eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch message.Set("message", message_name); 777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch message.Set("value", value); 7783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch PSInterfaceMessaging()->PostMessage(PSGetInstanceId(), message.pp_var()); 779eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 780eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 781eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Planet::Update() { 7823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // When benchmarking is running, don't update display via 7833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // PSContext2DSwapBuffer() - vsync is enabled by default, and will throttle 7843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // the benchmark results. 7853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch PSContext2DGetBuffer(ps_context_); 7863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (NULL == ps_context_->data) 7873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 7883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 789eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch do { 790eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UpdateSim(); 791eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Render(); 792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!benchmarking_) break; 793eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch --benchmark_frame_counter_; 794eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } while (benchmark_frame_counter_ > 0); 795eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (benchmarking_) 796eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EndBenchmark(); 797eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7983240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch PSContext2DSwapBuffer(ps_context_); 7993240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch} 8003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 801eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 8023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// Starting point for the module. We do not use main since it would 8033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// collide with main in libppapi_cpp. 8043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochint example_main(int argc, char* argv[]) { 8053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch Planet earth; 8063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch while (true) { 8073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch PSEvent* ps_event; 8083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Consume all available events 8093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch while ((ps_event = PSEventTryAcquire()) != NULL) { 8103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch earth.HandleEvent(ps_event); 8113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch PSEventRelease(ps_event); 8123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 8133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Do simulation, render and present. 8143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch earth.Update(); 815eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 816eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 8173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return 0; 818eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 819eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 8203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// Register the function to call once the Instance Object is initialized. 8213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// see: pappi_simple/ps_main.h 8223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochPPAPI_SIMPLE_REGISTER_MAIN(example_main); 823