1c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// found in the LICENSE file. 4c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 5c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <assert.h> 6c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <math.h> 7c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <ppapi/c/pp_point.h> 8c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <ppapi/c/ppb_input_event.h> 9c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <ppapi/cpp/completion_callback.h> 10c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <ppapi/cpp/graphics_2d.h> 11c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <ppapi/cpp/image_data.h> 12c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <ppapi/cpp/input_event.h> 13c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <ppapi/cpp/instance.h> 14c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <ppapi/cpp/module.h> 15c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <ppapi/cpp/rect.h> 16c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <ppapi/cpp/size.h> 17c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <ppapi/cpp/var.h> 18c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <ppapi/cpp/var_array.h> 19c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <ppapi/cpp/var_array_buffer.h> 20c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <ppapi/cpp/var_dictionary.h> 21c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <pthread.h> 22c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <stdio.h> 23c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <stdlib.h> 24c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <string.h> 25c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <unistd.h> 26c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 27c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <algorithm> 28c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include <string> 29c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "common/fps.h" 31c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include "sdk_util/macros.h" 32c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include "sdk_util/thread_pool.h" 33c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Chromium presubmit prevents checking in changes with calls to printf to 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// prevent spammy output. We'll work around that for this example. 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define logf printf 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 38c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochusing namespace sdk_util; // For sdk_util::ThreadPool 39c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 40c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// Global properties used to setup Earth demo. 41c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochnamespace { 42c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochconst float kPI = M_PI; 43c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochconst float kTwoPI = kPI * 2.0f; 44c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochconst float kOneOverPI = 1.0f / kPI; 45c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochconst float kOneOver2PI = 1.0f / kTwoPI; 46c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochconst float kOneOver255 = 1.0f / 255.0f; 47c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochconst int kArcCosineTableSize = 4096; 48c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochconst int kFramesToBenchmark = 100; 49c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochconst float kZoomMin = 1.0f; 50c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochconst float kZoomMax = 50.0f; 51c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochconst float kWheelSpeed = 2.0f; 52c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochconst float kLightMin = 0.0f; 53c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochconst float kLightMax = 2.0f; 54c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 55c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// RGBA helper functions. 56c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochinline float ExtractR(uint32_t c) { 57c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return static_cast<float>(c & 0xFF) * kOneOver255; 58c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 59c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 60c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochinline float ExtractG(uint32_t c) { 61c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return static_cast<float>((c & 0xFF00) >> 8) * kOneOver255; 62c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 63c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 64c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochinline float ExtractB(uint32_t c) { 65c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return static_cast<float>((c & 0xFF0000) >> 16) * kOneOver255; 66c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 67c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 68c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochinline uint32_t MakeRGBA(uint32_t r, uint32_t g, uint32_t b, uint32_t a) { 69c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)); 70c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 71c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 72c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// simple container for earth texture 73c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochstruct Texture { 74c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int width, height; 75c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch uint32_t* pixels; 76c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch Texture(int w, int h) : width(w), height(h) { 77c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch pixels = new uint32_t[w * h]; 78c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch memset(pixels, 0, sizeof(uint32_t) * w * h); 79c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 80c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch explicit Texture(int w, int h, uint32_t* p) : width(w), height(h) { 81c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch pixels = new uint32_t[w * h]; 82c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch memcpy(pixels, p, sizeof(uint32_t) * w * h); 83c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 84c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ~Texture() { delete[] pixels; } 85c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 86c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch DISALLOW_COPY_AND_ASSIGN(Texture); 87c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch}; 88c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 89c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 90c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 91c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochstruct ArcCosine { 92c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // slightly larger table so we can interpolate beyond table size 93c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float table[kArcCosineTableSize + 2]; 94c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float TableLerp(float x); 95c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ArcCosine(); 96c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch}; 97c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 98c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben MurdochArcCosine::ArcCosine() { 99c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // build a slightly larger table to allow for numeric imprecision 100c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch for (int i = 0; i < (kArcCosineTableSize + 2); ++i) { 101c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float f = static_cast<float>(i) / kArcCosineTableSize; 102c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch f = f * 2.0f - 1.0f; 103c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch table[i] = acos(f); 104c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 105c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 106c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 107c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// looks up acos(f) using a table and lerping between entries 108c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// (it is expected that input f is between -1 and 1) 109c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochfloat ArcCosine::TableLerp(float f) { 110c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float x = (f + 1.0f) * 0.5f; 111c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch x = x * kArcCosineTableSize; 112c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int ix = static_cast<int>(x); 113c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float fx = static_cast<float>(ix); 114c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float dx = x - fx; 115c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float af = table[ix]; 116c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float af2 = table[ix + 1]; 117c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return af + (af2 - af) * dx; 118c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 119c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 120c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// Helper functions for quick but approximate sqrt. 121c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochunion Convert { 122c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float f; 123c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int i; 124c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch Convert(int x) { i = x; } 125c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch Convert(float x) { f = x; } 126c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int AsInt() { return i; } 127c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float AsFloat() { return f; } 128c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch}; 129c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 130c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochinline const int AsInteger(const float f) { 131c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch Convert u(f); 132c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return u.AsInt(); 133c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 134c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 135c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochinline const float AsFloat(const int i) { 136c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch Convert u(i); 137c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return u.AsFloat(); 138c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 139c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 140c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochconst long int kOneAsInteger = AsInteger(1.0f); 141c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 142c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochinline float inline_quick_sqrt(float x) { 143c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int i; 144c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch i = (AsInteger(x) >> 1) + (kOneAsInteger >> 1); 145c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return AsFloat(i); 146c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 147c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 148c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochinline float inline_sqrt(float x) { 149c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float y; 150c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch y = inline_quick_sqrt(x); 151c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch y = (y * y + x) / (2.0f * y); 152c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch y = (y * y + x) / (2.0f * y); 153c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return y; 154c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 155c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 156c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// takes a -0..1+ color, clamps it to 0..1 and maps it to 0..255 integer 157c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochinline uint32_t Clamp255(float x) { 158c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (x < 0.0f) { 159c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch x = 0.0f; 160c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } else if (x > 1.0f) { 161c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch x = 1.0f; 162c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 163c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return static_cast<uint32_t>(x * 255.0f); 164c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 165c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} // namespace 166c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 167c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 168c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// The main object that runs the Earth demo. 169c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochclass Planet : public pp::Instance { 170c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch public: 171c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch explicit Planet(PP_Instance instance); 172c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch virtual ~Planet(); 173c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 174c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]); 175c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual void DidChangeView(const pp::View& view); 177c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 178c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Catch events. 179c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch virtual bool HandleInputEvent(const pp::InputEvent& event); 180c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 181c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Catch messages posted from Javascript. 182c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch virtual void HandleMessage(const pp::Var& message); 183c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 184c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch private: 185c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Methods prefixed with 'w' are run on worker threads. 186c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch uint32_t* wGetAddr(int x, int y); 187c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void wRenderPixelSpan(int x0, int x1, int y); 188c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void wMakeRect(int r, int *x, int *y, int *w, int *h); 189c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void wRenderRect(int x0, int y0, int x1, int y1); 190c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void wRenderRegion(int region); 191c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch static void wRenderRegionEntry(int region, void *thiz); 192c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 193c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // These methods are only called by the main thread. 194c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void CacheCalcs(); 195c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void SetPlanetXYZR(float x, float y, float z, float r); 196c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void SetPlanetPole(float x, float y, float z); 197c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void SetPlanetEquator(float x, float y, float z); 198c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void SetPlanetSpin(float x, float y); 199c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void SetEyeXYZ(float x, float y, float z); 200c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void SetLightXYZ(float x, float y, float z); 201c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void SetAmbientRGB(float r, float g, float b); 202c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void SetDiffuseRGB(float r, float g, float b); 203c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void SetZoom(float zoom); 204c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void SetLight(float zoom); 205c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void SetTexture(const std::string& name, int width, int height, 206c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch uint32_t* pixels); 207c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 208c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void Reset(); 209c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void PostInit(int32_t result); 210c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void UpdateSim(); 211c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void Render(); 212c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void Draw(); 213c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void StartBenchmark(); 214c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void EndBenchmark(); 215c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 216c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Runs a tick of the simulations, updating all buffers. Flushes the 217c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // contents of |image_data_| to the 2D graphics context. 218c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void Update(); 219c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 220c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Post a small key-value message to update JS. 221c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void PostUpdateMessage(const char* message_name, double value); 222c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Create and initialize the 2D context used for drawing. 223c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void CreateContext(const pp::Size& size); 224c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Destroy the 2D drawing context. 225c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void DestroyContext(); 226c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Push the pixels to the browser, then attempt to flush the 2D context. 227c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void FlushPixelBuffer(); 228c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch static void FlushCallback(void* data, int32_t result); 229c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 230c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // User Interface settings. These settings are controlled via html 231c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // controls or via user input. 232c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float ui_light_; 233c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float ui_zoom_; 234c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float ui_spin_x_; 235c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float ui_spin_y_; 236c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 237c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Various settings for position & orientation of planet. Do not change 238c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // these variables, instead use SetPlanet*() functions. 239c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float planet_radius_; 240c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float planet_spin_x_; 241c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float planet_spin_y_; 242c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float planet_x_, planet_y_, planet_z_; 243c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float planet_pole_x_, planet_pole_y_, planet_pole_z_; 244c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float planet_equator_x_, planet_equator_y_, planet_equator_z_; 245c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 246c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Observer's eye. Do not change these variables, instead use SetEyeXYZ(). 247c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float eye_x_, eye_y_, eye_z_; 248c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 249c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Light position, ambient and diffuse settings. Do not change these 250c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // variables, instead use SetLightXYZ(), SetAmbientRGB() and SetDiffuseRGB(). 251c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float light_x_, light_y_, light_z_; 252c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float diffuse_r_, diffuse_g_, diffuse_b_; 253c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float ambient_r_, ambient_g_, ambient_b_; 254c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 255c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Cached calculations. Do not change these variables - they are updated by 256c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // CacheCalcs() function. 257c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float planet_xyz_; 258c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float planet_pole_x_equator_x_; 259c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float planet_pole_x_equator_y_; 260c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float planet_pole_x_equator_z_; 261c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float planet_radius2_; 262c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float planet_one_over_radius_; 263c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float eye_xyz_; 264c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 265c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Source texture (earth map). 266c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch Texture* base_tex_; 267c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch Texture* night_tex_; 268c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int width_for_tex_; 269c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int height_for_tex_; 270c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch std::string name_for_tex_; 271c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 272c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Quick ArcCos helper. 273c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ArcCosine acos_; 274c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 275c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Misc. 276c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch pp::Graphics2D* graphics_2d_context_; 277c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch pp::ImageData* image_data_; 278c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch bool initial_did_change_view_; 279c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int num_threads_; 280c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int num_regions_; 281c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ThreadPool* workers_; 282c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int width_; 283c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int height_; 2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool hidden_; 2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) PP_Point last_mouse_pos_; 286c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch uint32_t stride_in_pixels_; 287c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch uint32_t* pixel_buffer_; 288c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int benchmark_frame_counter_; 289c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch bool benchmarking_; 290c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch double benchmark_start_time_; 291c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch double benchmark_end_time_; 292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) FpsState fps_state_; 293c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch}; 294c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 295c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 296c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochbool Planet::Init(uint32_t argc, const char* argn[], const char* argv[]) { 297c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Request PPAPI input events for mouse & keyboard. 298c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE); 299c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch RequestInputEvents(PP_INPUTEVENT_CLASS_WHEEL); 300c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch RequestInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD); 301c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Request a set of images from JS. After images are loaded by JS, a 302c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // message from JS -> NaCl will arrive containing the pixel data. See 303c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // HandleMessage() method in this file. 304c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch pp::VarDictionary message; 305c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch message.Set("message", "request_textures"); 306c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch pp::VarArray names; 307c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch names.Set(0, "earth.jpg"); 308c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch names.Set(1, "earthnight.jpg"); 309c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch message.Set("names", names); 310c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch PostMessage(message); 311c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return true; 312c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 313c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 314c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::Reset() { 315c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Reset has to first fill in all variables with valid floats, so 316c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // CacheCalcs() doesn't potentially propagate NaNs when calling Set*() 317c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // functions further below. 318c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_radius_ = 1.0f; 319c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_spin_x_ = 0.0f; 320c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_spin_y_ = 0.0f; 321c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_x_ = 0.0f; 322c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_y_ = 0.0f; 323c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_z_ = 0.0f; 324c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_pole_x_ = 0.0f; 325c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_pole_y_ = 0.0f; 326c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_pole_z_ = 0.0f; 327c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_equator_x_ = 0.0f; 328c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_equator_y_ = 0.0f; 329c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_equator_z_ = 0.0f; 330c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch eye_x_ = 0.0f; 331c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch eye_y_ = 0.0f; 332c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch eye_z_ = 0.0f; 333c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch light_x_ = 0.0f; 334c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch light_y_ = 0.0f; 335c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch light_z_ = 0.0f; 336c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch diffuse_r_ = 0.0f; 337c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch diffuse_g_ = 0.0f; 338c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch diffuse_b_ = 0.0f; 339c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ambient_r_ = 0.0f; 340c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ambient_g_ = 0.0f; 341c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ambient_b_ = 0.0f; 342c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_xyz_ = 0.0f; 343c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_pole_x_equator_x_ = 0.0f; 344c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_pole_x_equator_y_ = 0.0f; 345c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_pole_x_equator_z_ = 0.0f; 346c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_radius2_ = 0.0f; 347c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_one_over_radius_ = 0.0f; 348c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch eye_xyz_ = 0.0f; 349c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ui_zoom_ = 14.0f; 350c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ui_light_ = 1.0f; 351c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ui_spin_x_ = 0.01f; 352c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ui_spin_y_ = 0.0f; 353c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 354c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Set up reasonable default values. 355c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SetPlanetXYZR(0.0f, 0.0f, 48.0f, 4.0f); 356c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SetEyeXYZ(0.0f, 0.0f, -ui_zoom_); 357c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SetLightXYZ(-60.0f, -30.0f, 0.0f); 358c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SetAmbientRGB(0.05f, 0.05f, 0.05f); 359c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SetDiffuseRGB(0.8f, 0.8f, 0.8f); 360c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SetPlanetPole(0.0f, 1.0f, 0.0f); 361c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SetPlanetEquator(1.0f, 0.0f, 0.0f); 362c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SetPlanetSpin(kPI / 2.0f, kPI / 2.0f); 363c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SetZoom(ui_zoom_); 364c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SetLight(ui_light_); 365c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 366c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Send UI values to JS to reset html sliders. 367c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch PostUpdateMessage("set_zoom", ui_zoom_); 368c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch PostUpdateMessage("set_light", ui_light_); 369c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 370c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 371c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 372c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben MurdochPlanet::Planet(PP_Instance instance) : pp::Instance(instance), 373c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch graphics_2d_context_(NULL), 374c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch image_data_(NULL), 375c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch initial_did_change_view_(true), 376c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch num_regions_(256) { 377c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch width_ = 0; 378c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch height_ = 0; 3794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) hidden_ = false; 380c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch stride_in_pixels_ = 0; 381c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch pixel_buffer_ = NULL; 382c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch benchmark_frame_counter_ = 0; 383c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch benchmarking_ = false; 384c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch base_tex_ = NULL; 385c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch night_tex_ = NULL; 386c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch name_for_tex_ = ""; 3874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) last_mouse_pos_ = PP_MakePoint(0, 0); 388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) FpsInit(&fps_state_); 389c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 390c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch Reset(); 391c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 392c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // By default, render from the dispatch thread. 393c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch num_threads_ = 0; 394c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch workers_ = new ThreadPool(num_threads_); 395c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 396c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 397c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben MurdochPlanet::~Planet() { 398c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch delete workers_; 399c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch DestroyContext(); 400c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 401c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 402c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// Given a region r, derive a rectangle. 403c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// This rectangle shouldn't overlap with work being done by other workers. 404c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// If multithreading, this function is only called by the worker threads. 405c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::wMakeRect(int r, int *x, int *y, int *w, int *h) { 406c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int dy = height_ / num_regions_; 407c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch *x = 0; 408c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch *w = width_; 409c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch *y = r * dy; 410c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch *h = dy; 411c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 412c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 413c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 414c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochinline uint32_t* Planet::wGetAddr(int x, int y) { 415c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch assert(pixel_buffer_); 416c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return (pixel_buffer_ + y * stride_in_pixels_) + x; 417c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 418c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 419c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// This is the meat of the ray tracer. Given a pixel span (x0, x1) on 420c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// scanline y, shoot rays into the scene and render what they hit. Use 421c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// scanline coherence to do a few optimizations 422c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::wRenderPixelSpan(int x0, int x1, int y) { 423c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (!base_tex_ || !night_tex_) 424c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return; 425c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch const int kColorBlack = MakeRGBA(0, 0, 0, 0xFF); 426c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float min_dim = width_ < height_ ? width_ : height_; 427c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float offset_x = width_ < height_ ? 0 : (width_ - min_dim) * 0.5f; 428c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float offset_y = width_ < height_ ? (height_ - min_dim) * 0.5f : 0; 429c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float y0 = eye_y_; 430c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float z0 = eye_z_; 431c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float y1 = (static_cast<float>(y - offset_y) / min_dim) * 2.0f - 1.0f; 432c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float z1 = 0.0f; 433c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float dy = (y1 - y0); 434c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float dz = (z1 - z0); 435c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float dy_dy_dz_dz = dy * dy + dz * dz; 436c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float two_dy_y0_y_two_dz_z0_z = 2.0f * dy * (y0 - planet_y_) + 437c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 2.0f * dz * (z0 - planet_z_); 438c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float planet_xyz_eye_xyz = planet_xyz_ + eye_xyz_; 439c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float y_y0_z_z0 = planet_y_ * y0 + planet_z_ * z0; 440c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float oowidth = 1.0f / min_dim; 441c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch uint32_t* pixels = this->wGetAddr(x0, y); 442c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch for (int x = x0; x <= x1; ++x) { 443c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // scan normalized screen -1..1 444c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float x1 = (static_cast<float>(x - offset_x) * oowidth) * 2.0f - 1.0f; 445c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // eye 446c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float x0 = eye_x_; 447c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // delta from screen to eye 448c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float dx = (x1 - x0); 449c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // build a, b, c 450c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float a = dx * dx + dy_dy_dz_dz; 451c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float b = 2.0f * dx * (x0 - planet_x_) + two_dy_y0_y_two_dz_z0_z; 452c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float c = planet_xyz_eye_xyz + 453c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch -2.0f * (planet_x_ * x0 + y_y0_z_z0) - (planet_radius2_); 454c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // calculate discriminant 455c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float disc = b * b - 4.0f * a * c; 456c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 457c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Did ray hit the sphere? 458c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (disc < 0.0f) { 459c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch *pixels = kColorBlack; 460c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ++pixels; 461c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch continue; 462c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 463c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 464c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // calc parametric t value 465c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float t = (-b - inline_sqrt(disc)) / (2.0f * a); 466c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float px = x0 + t * dx; 467c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float py = y0 + t * dy; 468c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float pz = z0 + t * dz; 469c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float nx = (px - planet_x_) * planet_one_over_radius_; 470c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float ny = (py - planet_y_) * planet_one_over_radius_; 471c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float nz = (pz - planet_z_) * planet_one_over_radius_; 472c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 473c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Misc raytrace calculations. 474c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float Lx = (light_x_ - px); 475c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float Ly = (light_y_ - py); 476c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float Lz = (light_z_ - pz); 477c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float Lq = 1.0f / inline_quick_sqrt(Lx * Lx + Ly * Ly + Lz * Lz); 478c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch Lx *= Lq; 479c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch Ly *= Lq; 480c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch Lz *= Lq; 481c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float d = (Lx * nx + Ly * ny + Lz * nz); 482c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float pr = (diffuse_r_ * d) + ambient_r_; 483c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float pg = (diffuse_g_ * d) + ambient_g_; 484c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float pb = (diffuse_b_ * d) + ambient_b_; 485c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float ds = -(nx * planet_pole_x_ + 486c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ny * planet_pole_y_ + 487c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch nz * planet_pole_z_); 488c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float ang = acos_.TableLerp(ds); 489c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float v = ang * kOneOverPI; 490c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float dp = planet_equator_x_ * nx + 491c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_equator_y_ * ny + 492c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_equator_z_ * nz; 493c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float w = dp / sin(ang); 494c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (w > 1.0f) w = 1.0f; 495c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (w < -1.0f) w = -1.0f; 496c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float th = acos_.TableLerp(w) * kOneOver2PI; 497c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float dps = planet_pole_x_equator_x_ * nx + 498c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_pole_x_equator_y_ * ny + 499c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_pole_x_equator_z_ * nz; 500c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float u; 501c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (dps < 0.0f) 502c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch u = th; 503c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch else 504c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch u = 1.0f - th; 505c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 506c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Look up daylight texel. 507c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int tx = static_cast<int>(u * base_tex_->width); 508c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int ty = static_cast<int>(v * base_tex_->height); 509c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int offset = tx + ty * base_tex_->width; 510c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch uint32_t base_texel = base_tex_->pixels[offset]; 511c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float tr = ExtractR(base_texel); 512c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float tg = ExtractG(base_texel); 513c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float tb = ExtractB(base_texel); 514c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 515c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float ipr = 1.0f - pr; 516c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (ipr < 0.0f) ipr = 0.0f; 517c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float ipg = 1.0f - pg; 518c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (ipg < 0.0f) ipg = 0.0f; 519c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float ipb = 1.0f - pb; 520c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (ipb < 0.0f) ipb = 0.0f; 521c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 522c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Look up night texel. 523c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int nix = static_cast<int>(u * night_tex_->width); 524c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int niy = static_cast<int>(v * night_tex_->height); 525c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int noffset = nix + niy * night_tex_->width; 526c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch uint32_t night_texel = night_tex_->pixels[noffset]; 527c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float nr = ExtractR(night_texel); 528c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float ng = ExtractG(night_texel); 529c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float nb = ExtractB(night_texel); 530c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 531c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Final color value is lerp between day and night texels. 532c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch unsigned int ir = Clamp255(pr * tr + nr * ipr); 533c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch unsigned int ig = Clamp255(pg * tg + ng * ipg); 534c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch unsigned int ib = Clamp255(pb * tb + nb * ipb); 535c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 536c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch unsigned int color = MakeRGBA(ir, ig, ib, 0xFF); 537c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 538c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch *pixels = color; 539c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ++pixels; 540c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 541c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 542c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 543c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// Renders a rectangular area of the screen, scan line at a time 544c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::wRenderRect(int x, int y, int w, int h) { 545c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch for (int j = y; j < (y + h); ++j) { 546c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch this->wRenderPixelSpan(x, x + w - 1, j); 547c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 548c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 549c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 550c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// If multithreading, this function is only called by the worker threads. 551c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::wRenderRegion(int region) { 552c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // convert region # into x0, y0, x1, y1 rectangle 553c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int x, y, w, h; 554c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch wMakeRect(region, &x, &y, &w, &h); 555c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // render this rectangle 556c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch wRenderRect(x, y, w, h); 557c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 558c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 559c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// Entry point for worker thread. Can't pass a member function around, so we 560c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// have to do this little round-about. 561c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::wRenderRegionEntry(int region, void* thiz) { 562c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch static_cast<Planet*>(thiz)->wRenderRegion(region); 563c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 564c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 565c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// Renders the planet, dispatching the work to multiple threads. 566c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// Note: This Dispatch() is from the main PPAPI thread, so care must be taken 567c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// not to attempt PPAPI calls from the worker threads, since Dispatch() will 568c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// block here until all work is complete. The worker threads are compute only 569c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// and do not make any PPAPI calls. 570c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::Render() { 571c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch workers_->Dispatch(num_regions_, wRenderRegionEntry, this); 572c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 573c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 574c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// Pre-calculations to make inner loops faster. 575c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::CacheCalcs() { 576c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_xyz_ = planet_x_ * planet_x_ + 577c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_y_ * planet_y_ + 578c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_z_ * planet_z_; 579c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_radius2_ = planet_radius_ * planet_radius_; 580c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_one_over_radius_ = 1.0f / planet_radius_; 581c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch eye_xyz_ = eye_x_ * eye_x_ + eye_y_ * eye_y_ + eye_z_ * eye_z_; 582c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // spin vector from center->equator 583c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_equator_x_ = cos(planet_spin_x_); 584c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_equator_y_ = 0.0f; 585c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_equator_z_ = sin(planet_spin_x_); 586c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 587c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // cache cross product of pole & equator 588c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_pole_x_equator_x_ = planet_pole_y_ * planet_equator_z_ - 589c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_pole_z_ * planet_equator_y_; 590c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_pole_x_equator_y_ = planet_pole_z_ * planet_equator_x_ - 591c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_pole_x_ * planet_equator_z_; 592c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_pole_x_equator_z_ = planet_pole_x_ * planet_equator_y_ - 593c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_pole_y_ * planet_equator_x_; 594c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 595c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 596c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::SetPlanetXYZR(float x, float y, float z, float r) { 597c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_x_ = x; 598c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_y_ = y; 599c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_z_ = z; 600c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_radius_ = r; 601c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch CacheCalcs(); 602c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 603c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 604c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::SetEyeXYZ(float x, float y, float z) { 605c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch eye_x_ = x; 606c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch eye_y_ = y; 607c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch eye_z_ = z; 608c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch CacheCalcs(); 609c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 610c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 611c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::SetLightXYZ(float x, float y, float z) { 612c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch light_x_ = x; 613c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch light_y_ = y; 614c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch light_z_ = z; 615c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch CacheCalcs(); 616c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 617c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 618c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::SetAmbientRGB(float r, float g, float b) { 619c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ambient_r_ = r; 620c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ambient_g_ = g; 621c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ambient_b_ = b; 622c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch CacheCalcs(); 623c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 624c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 625c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::SetDiffuseRGB(float r, float g, float b) { 626c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch diffuse_r_ = r; 627c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch diffuse_g_ = g; 628c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch diffuse_b_ = b; 629c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch CacheCalcs(); 630c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 631c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 632c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::SetPlanetPole(float x, float y, float z) { 633c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_pole_x_ = x; 634c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_pole_y_ = y; 635c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_pole_z_ = z; 636c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch CacheCalcs(); 637c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 638c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 639c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::SetPlanetEquator(float x, float y, float z) { 640c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // This is really over-ridden by spin at the momenent. 641c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_equator_x_ = x; 642c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_equator_y_ = y; 643c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_equator_z_ = z; 644c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch CacheCalcs(); 645c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 646c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 647c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::SetPlanetSpin(float x, float y) { 648c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_spin_x_ = x; 649c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch planet_spin_y_ = y; 650c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch CacheCalcs(); 651c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 652c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 653c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// Run a simple sim to spin the planet. Update loop is run once per frame. 654c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// Called from the main thread only and only when the worker threads are idle. 655c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::UpdateSim() { 656c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float x = planet_spin_x_ + ui_spin_x_; 657c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch float y = planet_spin_y_ + ui_spin_y_; 658c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // keep in nice range 659c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (x > (kPI * 2.0f)) 660c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch x = x - kPI * 2.0f; 661c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch else if (x < (-kPI * 2.0f)) 662c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch x = x + kPI * 2.0f; 663c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (y > (kPI * 2.0f)) 664c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch y = y - kPI * 2.0f; 665c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch else if (y < (-kPI * 2.0f)) 666c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch y = y + kPI * 2.0f; 667c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SetPlanetSpin(x, y); 668c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 669c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 6704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Planet::DidChangeView(const pp::View& view) { 6714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pp::Rect position = view.GetRect(); 6724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Update hidden_ state 6734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) hidden_ = !view.IsVisible(); 674c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (position.size().width() == width_ && 675c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch position.size().height() == height_) 676c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return; // Size didn't change, no need to update anything. 677c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Create a new device context with the new size. 678c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch DestroyContext(); 679c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch CreateContext(position.size()); 680c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 681c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (initial_did_change_view_) { 682c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch initial_did_change_view_ = false; 683c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch Update(); 684c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 685c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 686c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 687c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::StartBenchmark() { 688c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // For more consistent benchmark numbers, reset to default state. 689c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch Reset(); 690a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) logf("Benchmark started...\n"); 691c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch benchmark_frame_counter_ = kFramesToBenchmark; 692c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch benchmarking_ = true; 693c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch benchmark_start_time_ = getseconds(); 694c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 695c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 696c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::EndBenchmark() { 697c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch benchmark_end_time_ = getseconds(); 698a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) logf("Benchmark ended... time: %2.5f\n", 699c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch benchmark_end_time_ - benchmark_start_time_); 700c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch benchmarking_ = false; 701c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch benchmark_frame_counter_ = 0; 702c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch double total_time = benchmark_end_time_ - benchmark_start_time_; 703c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Send benchmark result to JS. 704c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch PostUpdateMessage("benchmark_result", total_time); 705c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 706c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 707c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::SetZoom(float zoom) { 708c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ui_zoom_ = std::min(kZoomMax, std::max(kZoomMin, zoom)); 709c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SetEyeXYZ(0.0f, 0.0f, -ui_zoom_); 710c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 711c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 712c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::SetLight(float light) { 713c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ui_light_ = std::min(kLightMax, std::max(kLightMin, light)); 714c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SetDiffuseRGB(0.8f * ui_light_, 0.8f * ui_light_, 0.8f * ui_light_); 715c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SetAmbientRGB(0.4f * ui_light_, 0.4f * ui_light_, 0.4f * ui_light_); 716c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 717c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 718c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::SetTexture(const std::string& name, int width, int height, 719c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch uint32_t* pixels) { 720c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (pixels) { 721c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (name == "earth.jpg") { 722c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch delete base_tex_; 723c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch base_tex_ = new Texture(width, height, pixels); 724c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } else if (name == "earthnight.jpg") { 725c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch delete night_tex_; 726c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch night_tex_ = new Texture(width, height, pixels); 727c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 728c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 729c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 730c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 731c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// Handle input events from the user. 732c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochbool Planet::HandleInputEvent(const pp::InputEvent& event) { 733c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch switch (event.GetType()) { 734c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch case PP_INPUTEVENT_TYPE_KEYDOWN: { 735c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch pp::KeyboardInputEvent key(event); 736c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch uint32_t key_code = key.GetKeyCode(); 737c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (key_code == 84) // 't' key 738c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (!benchmarking_) 739c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch StartBenchmark(); 740c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch break; 741c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 742c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch case PP_INPUTEVENT_TYPE_MOUSEDOWN: { 743c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch pp::MouseInputEvent mouse = pp::MouseInputEvent(event); 7444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) last_mouse_pos_ = mouse.GetPosition(); 7454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ui_spin_x_ = 0.0f; 7464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ui_spin_y_ = 0.0f; 7474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 7484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 7494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case PP_INPUTEVENT_TYPE_MOUSEMOVE: { 7504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pp::MouseInputEvent mouse = pp::MouseInputEvent(event); 751c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (mouse.GetModifiers() & PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) { 7524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) PP_Point mouse_pos = mouse.GetPosition(); 7534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) float delta_x = static_cast<float>(mouse_pos.x - last_mouse_pos_.x); 7544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) float delta_y = static_cast<float>(mouse_pos.y - last_mouse_pos_.y); 7554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) float spin_x = std::min(10.0f, std::max(-10.0f, delta_x * 0.5f)); 7564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) float spin_y = std::min(10.0f, std::max(-10.0f, delta_y * 0.5f)); 757c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ui_spin_x_ = spin_x / 100.0f; 758c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ui_spin_y_ = spin_y / 100.0f; 7594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) last_mouse_pos_ = mouse_pos; 760c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 761c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch break; 762c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 763c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch case PP_INPUTEVENT_TYPE_WHEEL: { 764c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch pp::WheelInputEvent wheel = pp::WheelInputEvent(event); 765c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch PP_FloatPoint ticks = wheel.GetTicks(); 766c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SetZoom(ui_zoom_ + (ticks.x + ticks.y) * kWheelSpeed); 767c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Update html slider by sending update message to JS. 768c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch PostUpdateMessage("set_zoom", ui_zoom_); 769c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch break; 770c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 771c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch default: 772c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return false; 773c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 774c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return true; 775c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 776c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 777c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// PostUpdateMessage() helper function for sending small messages to JS. 778c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::PostUpdateMessage(const char* message_name, double value) { 779c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch pp::VarDictionary message; 780c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch message.Set("message", message_name); 781c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch message.Set("value", value); 782c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch PostMessage(message); 783c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 784c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 785c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// Handle message sent from Javascript. 786c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::HandleMessage(const pp::Var& var) { 787c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (var.is_dictionary()) { 788c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch pp::VarDictionary dictionary(var); 789c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch std::string message = dictionary.Get("message").AsString(); 790c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (message == "run benchmark" && !benchmarking_) { 791c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch StartBenchmark(); 792c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } else if (message == "set_light") { 793c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SetLight(static_cast<float>(dictionary.Get("value").AsDouble())); 794c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } else if (message == "set_zoom") { 795c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SetZoom(static_cast<float>(dictionary.Get("value").AsDouble())); 796c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } else if (message == "set_threads") { 797c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int threads = dictionary.Get("value").AsInt(); 798c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch delete workers_; 799c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch workers_ = new ThreadPool(threads); 800c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } else if (message == "texture") { 801c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch std::string name = dictionary.Get("name").AsString(); 802c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int width = dictionary.Get("width").AsInt(); 803c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int height = dictionary.Get("height").AsInt(); 804c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch pp::VarArrayBuffer array_buffer(dictionary.Get("data")); 805c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (!name.empty() && width > 0 && height > 0 && !array_buffer.is_null()) { 806c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch uint32_t* pixels = static_cast<uint32_t*>(array_buffer.Map()); 807c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SetTexture(name, width, height, pixels); 808c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch array_buffer.Unmap(); 809c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 810c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 811c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } else { 812a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) logf("Handle message unknown type: %s\n", var.DebugString().c_str()); 813c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 814c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 815c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 816c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::FlushCallback(void* thiz, int32_t result) { 817c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch static_cast<Planet*>(thiz)->Update(); 818c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 819c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 820c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// Update the 2d region and flush to make it visible on the page. 821c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::FlushPixelBuffer() { 822c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch graphics_2d_context_->PaintImageData(*image_data_, pp::Point(0, 0)); 823c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch graphics_2d_context_->Flush(pp::CompletionCallback(&FlushCallback, this)); 824c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 825c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 826c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::Update() { 8274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // If view is hidden, don't render, but periodically (every 33ms) chain w/ 8284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // CallOnMainThread(). 8294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (hidden_) { 8304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pp::Module::Get()->core()->CallOnMainThread(33, 8314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pp::CompletionCallback(&FlushCallback, this)); 8324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 8334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 834c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Don't call FlushPixelBuffer() when benchmarking - vsync is enabled by 835c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // default, and will throttle the benchmark results. 836c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch do { 837c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch UpdateSim(); 838c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch Render(); 839c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (!benchmarking_) break; 840c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch --benchmark_frame_counter_; 841c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } while (benchmark_frame_counter_ > 0); 842c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (benchmarking_) 843c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch EndBenchmark(); 844c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 845c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch FlushPixelBuffer(); 846f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 847f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) double fps; 848f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (FpsStep(&fps_state_, &fps)) 849f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PostUpdateMessage("fps", fps); 850c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 851c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 852c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::CreateContext(const pp::Size& size) { 853c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch graphics_2d_context_ = new pp::Graphics2D(this, size, false); 854c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (graphics_2d_context_->is_null()) 855a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) logf("Failed to create a 2D resource!\n"); 856c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (!BindGraphics(*graphics_2d_context_)) 857a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) logf("Couldn't bind the device context\n"); 858c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch image_data_ = new pp::ImageData(this, 859c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch PP_IMAGEDATAFORMAT_BGRA_PREMUL, 860c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch size, 861c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch false); 862c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch width_ = image_data_->size().width(); 863c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch height_ = image_data_->size().height(); 864c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch stride_in_pixels_ = static_cast<uint32_t>(image_data_->stride() / 4); 865c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch pixel_buffer_ = static_cast<uint32_t*>(image_data_->data()); 866c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch num_regions_ = height_; 867c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 868c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 869c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid Planet::DestroyContext() { 870c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch delete graphics_2d_context_; 871c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch delete image_data_; 872c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch graphics_2d_context_ = NULL; 873c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch image_data_ = NULL; 874c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch width_ = 0; 875c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch height_ = 0; 876c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch stride_in_pixels_ = 0; 877c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch pixel_buffer_ = NULL; 878c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 879c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 880c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochclass PlanetModule : public pp::Module { 881c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch public: 882c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch PlanetModule() : pp::Module() {} 883c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch virtual ~PlanetModule() {} 884c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 885c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Create and return a Planet instance. 886c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch virtual pp::Instance* CreateInstance(PP_Instance instance) { 887c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return new Planet(instance); 888c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 889c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch}; 890c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 891c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochnamespace pp { 892c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben MurdochModule* CreateModule() { 893c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return new PlanetModule(); 894c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 895c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} // namespace pp 896c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 897