1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file. 4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <assert.h> 6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <math.h> 7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <ppapi/c/ppb_input_event.h> 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <ppapi/cpp/input_event.h> 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <ppapi/cpp/var.h> 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <ppapi/cpp/var_array.h> 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <ppapi/cpp/var_array_buffer.h> 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <ppapi/cpp/var_dictionary.h> 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <pthread.h> 14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <stdio.h> 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <stdlib.h> 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <string.h> 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <sys/time.h> 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <unistd.h> 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <algorithm> 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <string> 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ppapi_simple/ps.h" 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ppapi_simple/ps_context_2d.h" 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ppapi_simple/ps_event.h" 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ppapi_simple/ps_interface.h" 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ppapi_simple/ps_main.h" 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "sdk_util/macros.h" 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "sdk_util/thread_pool.h" 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)using namespace sdk_util; // For sdk_util::ThreadPool 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#define INLINE inline __attribute__((always_inline)) 34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// 128 bit SIMD vector types 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)typedef uint8_t u8x16_t __attribute__ ((vector_size (16))); 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)typedef int32_t i32x4_t __attribute__ ((vector_size (16))); 38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)typedef uint32_t u32x4_t __attribute__ ((vector_size (16))); 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)typedef float f32x4_t __attribute__ ((vector_size (16))); 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Global properties used to setup Earth demo. 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace { 43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const float kPI = M_PI; 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const float kTwoPI = kPI * 2.0f; 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const float kOneOverPI = 1.0f / kPI; 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const float kOneOver2PI = 1.0f / kTwoPI; 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const int kArcCosineTableSize = 4096; 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const int kFramesToBenchmark = 100; 49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const float kZoomMin = 1.0f; 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const float kZoomMax = 50.0f; 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const float kWheelSpeed = 2.0f; 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const float kLightMin = 0.0f; 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const float kLightMax = 2.0f; 54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Timer helper for benchmarking. Returns seconds elapsed since program start, 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// as a double. 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)timeval start_tv; 58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int start_tv_retv = gettimeofday(&start_tv, NULL); 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)inline double getseconds() { 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const double usec_to_sec = 0.000001; 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) timeval tv; 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if ((0 == start_tv_retv) && (0 == gettimeofday(&tv, NULL))) 64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return (tv.tv_sec - start_tv.tv_sec) + tv.tv_usec * usec_to_sec; 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 0.0; 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// SIMD Vector helper functions. 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Note that a compare between two vectors will return a signed integer vector 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// with the same number of elements, where each element will be all bits set 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// for true (-1), and all bits clear for false (0) This integer vector can be 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// useful as a mask. 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Also note that c-style casts do not mutate the bits of a vector - only the 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// type. Boolean operators can't operate on float vectors, but it is possible 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// to cast them temporarily to integer vector, perform the mask, and cast 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// them back to float. 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// To convert a float vector to an integer vector using trunction, or to 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// convert an integer vector to a float vector, use __builtin_convertvector(). 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)INLINE f32x4_t min(f32x4_t a, f32x4_t b) { 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) i32x4_t m = a < b; 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return (f32x4_t)(((i32x4_t)a & m) | ((i32x4_t)b & ~m)); 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)INLINE f32x4_t max(f32x4_t a, f32x4_t b) { 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) i32x4_t m = a > b; 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return (f32x4_t)(((i32x4_t)a & m) | ((i32x4_t)b & ~m)); 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)INLINE float dot3(f32x4_t a, f32x4_t b) { 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) f32x4_t c = a * b; 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return c[0] + c[1] + c[2]; 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)INLINE f32x4_t broadcast(float x) { 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) f32x4_t r = {x, x, x, x}; 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return r; 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// SIMD RGBA helper functions, used for extracting color from RGBA source image. 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)INLINE f32x4_t ExtractRGBA(uint32_t c) { 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const f32x4_t kOneOver255 = broadcast(1.0f / 255.0f); 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const i32x4_t kZero = {0, 0, 0, 0}; 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) i32x4_t v = {c, c, c, c}; 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // zero extend packed color into 32x4 integer vector 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) v = (i32x4_t)__builtin_shufflevector((u8x16_t)v, (u8x16_t)kZero, 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 0, 16, 16, 16, 1, 16, 16, 16, 2, 16, 16, 16, 3, 16, 16, 16); 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // convert color values to float, range 0..1 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) f32x4_t f = __builtin_convertvector(v, f32x4_t) * kOneOver255; 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return f; 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// SIMD BGRA helper function, for constructing a pixel for a BGRA buffer. 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)INLINE uint32_t PackBGRA(f32x4_t f) { 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const f32x4_t kZero = broadcast(0.0f); 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const f32x4_t kHalf = broadcast(0.5f); 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const f32x4_t k255 = broadcast(255.0f); 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) f = max(f, kZero); 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Add 0.5 to perform rounding instead of truncation. 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) f = f * k255 + kHalf; 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) f = min(f, k255); 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) i32x4_t i = __builtin_convertvector(f, i32x4_t); 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) u32x4_t p = (u32x4_t)__builtin_shufflevector((u8x16_t)i, (u8x16_t)i, 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 8, 4, 0, 12, 8, 4, 0, 12, 8, 4, 0, 12, 8, 4, 0, 12); 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return p[0]; 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// BGRA helper function, for constructing a pixel for a BGRA buffer. 132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)INLINE uint32_t MakeBGRA(uint32_t b, uint32_t g, uint32_t r, uint32_t a) { 133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)); 134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// simple container for earth texture 137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)struct Texture { 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int width, height; 139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t* pixels; 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Texture(int w, int h) : width(w), height(h) { 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pixels = new uint32_t[w * h]; 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) memset(pixels, 0, sizeof(uint32_t) * w * h); 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) explicit Texture(int w, int h, uint32_t* p) : width(w), height(h) { 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pixels = new uint32_t[w * h]; 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) memcpy(pixels, p, sizeof(uint32_t) * w * h); 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ~Texture() { delete[] pixels; } 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Texture); 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)struct ArcCosine { 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // slightly larger table so we can interpolate beyond table size 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float table[kArcCosineTableSize + 2]; 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float TableLerp(float x); 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ArcCosine(); 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ArcCosine::ArcCosine() { 163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // build a slightly larger table to allow for numeric imprecision 164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int i = 0; i < (kArcCosineTableSize + 2); ++i) { 165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float f = static_cast<float>(i) / kArcCosineTableSize; 166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) f = f * 2.0f - 1.0f; 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) table[i] = acos(f); 168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// looks up acos(f) using a table and lerping between entries 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// (it is expected that input f is between -1 and 1) 173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)INLINE float ArcCosine::TableLerp(float f) { 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float x = (f + 1.0f) * 0.5f; 175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) x = x * kArcCosineTableSize; 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int ix = static_cast<int>(x); 177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float fx = static_cast<float>(ix); 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float dx = x - fx; 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float af = table[ix]; 180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float af2 = table[ix + 1]; 181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return af + (af2 - af) * dx; 182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Helper functions for quick but approximate sqrt. 185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)union Convert { 186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float f; 187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int i; 188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Convert(int x) { i = x; } 189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Convert(float x) { f = x; } 190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int AsInt() { return i; } 191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float AsFloat() { return f; } 192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)INLINE const int AsInteger(const float f) { 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Convert u(f); 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return u.AsInt(); 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)INLINE const float AsFloat(const int i) { 200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Convert u(i); 201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return u.AsFloat(); 202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const long int kOneAsInteger = AsInteger(1.0f); 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)INLINE float inline_quick_sqrt(float x) { 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int i; 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) i = (AsInteger(x) >> 1) + (kOneAsInteger >> 1); 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return AsFloat(i); 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)INLINE float inline_sqrt(float x) { 213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float y; 214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) y = inline_quick_sqrt(x); 215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) y = (y * y + x) / (2.0f * y); 216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) y = (y * y + x) / (2.0f * y); 217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return y; 218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace 221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// The main object that runs the Earth demo. 224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class Planet { 225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Planet(); 227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual ~Planet(); 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Runs a tick of the simulations, update 2D output. 229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void Update(); 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Handle event from user, or message from JS. 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void HandleEvent(PSEvent* ps_event); 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private: 234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Methods prefixed with 'w' are run on worker threads. 235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t* wGetAddr(int x, int y); 236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void wRenderPixelSpan(int x0, int x1, int y); 237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void wMakeRect(int r, int *x, int *y, int *w, int *h); 238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void wRenderRect(int x0, int y0, int x1, int y1); 239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void wRenderRegion(int region); 240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static void wRenderRegionEntry(int region, void *thiz); 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // These methods are only called by the main thread. 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void CacheCalcs(); 244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void SetPlanetXYZR(float x, float y, float z, float r); 245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void SetPlanetPole(float x, float y, float z); 246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void SetPlanetEquator(float x, float y, float z); 247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void SetPlanetSpin(float x, float y); 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void SetEyeXYZ(float x, float y, float z); 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void SetLightXYZ(float x, float y, float z); 250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void SetAmbientRGB(float r, float g, float b); 251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void SetDiffuseRGB(float r, float g, float b); 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void SetZoom(float zoom); 253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void SetLight(float zoom); 254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void SetTexture(const std::string& name, int width, int height, 255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t* pixels); 256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void SpinPlanet(pp::Point new_point, pp::Point last_point); 257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void Reset(); 259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void RequestTextures(); 260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void UpdateSim(); 261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void Render(); 262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void Draw(); 263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void StartBenchmark(); 264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void EndBenchmark(); 265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Post a small key-value message to update JS. 266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void PostUpdateMessage(const char* message_name, double value); 267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // User Interface settings. These settings are controlled via html 269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // controls or via user input. 270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float ui_light_; 271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float ui_zoom_; 272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float ui_spin_x_; 273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float ui_spin_y_; 274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::Point ui_last_point_; 275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Various settings for position & orientation of planet. Do not change 277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // these variables, instead use SetPlanet*() functions. 278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float planet_radius_; 279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float planet_spin_x_; 280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float planet_spin_y_; 281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float planet_x_, planet_y_, planet_z_; 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float planet_pole_x_, planet_pole_y_, planet_pole_z_; 283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float planet_equator_x_, planet_equator_y_, planet_equator_z_; 284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Observer's eye. Do not change these variables, instead use SetEyeXYZ(). 286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float eye_x_, eye_y_, eye_z_; 287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Light position, ambient and diffuse settings. Do not change these 289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // variables, instead use SetLightXYZ(), SetAmbientRGB() and SetDiffuseRGB(). 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float light_x_, light_y_, light_z_; 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float diffuse_r_, diffuse_g_, diffuse_b_; 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float ambient_r_, ambient_g_, ambient_b_; 293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Cached calculations. Do not change these variables - they are updated by 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // CacheCalcs() function. 296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float planet_xyz_; 297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float planet_pole_x_equator_x_; 298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float planet_pole_x_equator_y_; 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float planet_pole_x_equator_z_; 300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float planet_radius2_; 301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float planet_one_over_radius_; 302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float eye_xyz_; 303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Source texture (earth map). 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Texture* base_tex_; 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Texture* night_tex_; 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int width_for_tex_; 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int height_for_tex_; 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Quick ArcCos helper. 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ArcCosine acos_; 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Misc. 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PSContext2D_t* ps_context_; 315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int num_threads_; 316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ThreadPool* workers_; 317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool benchmarking_; 318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int benchmark_frame_counter_; 319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) double benchmark_start_time_; 320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) double benchmark_end_time_; 321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::RequestTextures() { 325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Request a set of images from JS. After images are loaded by JS, a 326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // message from JS -> NaCl will arrive containing the pixel data. See 327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // HandleMessage() method in this file. 328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::VarDictionary message; 329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) message.Set("message", "request_textures"); 330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::VarArray names; 331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) names.Set(0, "earth.jpg"); 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) names.Set(1, "earthnight.jpg"); 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) message.Set("names", names); 334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PSInterfaceMessaging()->PostMessage(PSGetInstanceId(), message.pp_var()); 335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::Reset() { 338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Reset has to first fill in all variables with valid floats, so 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // CacheCalcs() doesn't potentially propagate NaNs when calling Set*() 340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // functions further below. 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_radius_ = 1.0f; 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_spin_x_ = 0.0f; 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_spin_y_ = 0.0f; 344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_x_ = 0.0f; 345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_y_ = 0.0f; 346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_z_ = 0.0f; 347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_pole_x_ = 0.0f; 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_pole_y_ = 0.0f; 349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_pole_z_ = 0.0f; 350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_equator_x_ = 0.0f; 351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_equator_y_ = 0.0f; 352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_equator_z_ = 0.0f; 353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) eye_x_ = 0.0f; 354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) eye_y_ = 0.0f; 355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) eye_z_ = 0.0f; 356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) light_x_ = 0.0f; 357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) light_y_ = 0.0f; 358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) light_z_ = 0.0f; 359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) diffuse_r_ = 0.0f; 360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) diffuse_g_ = 0.0f; 361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) diffuse_b_ = 0.0f; 362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ambient_r_ = 0.0f; 363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ambient_g_ = 0.0f; 364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ambient_b_ = 0.0f; 365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_xyz_ = 0.0f; 366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_pole_x_equator_x_ = 0.0f; 367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_pole_x_equator_y_ = 0.0f; 368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_pole_x_equator_z_ = 0.0f; 369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_radius2_ = 0.0f; 370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_one_over_radius_ = 0.0f; 371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) eye_xyz_ = 0.0f; 372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui_zoom_ = 14.0f; 373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui_light_ = 1.0f; 374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui_spin_x_ = 0.01f; 375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui_spin_y_ = 0.0f; 376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui_last_point_ = pp::Point(0, 0); 377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Set up reasonable default values. 379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetPlanetXYZR(0.0f, 0.0f, 48.0f, 4.0f); 380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetEyeXYZ(0.0f, 0.0f, -ui_zoom_); 381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetLightXYZ(-60.0f, -30.0f, 0.0f); 382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetAmbientRGB(0.05f, 0.05f, 0.05f); 383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetDiffuseRGB(0.8f, 0.8f, 0.8f); 384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetPlanetPole(0.0f, 1.0f, 0.0f); 385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetPlanetEquator(1.0f, 0.0f, 0.0f); 386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetPlanetSpin(kPI / 2.0f, kPI / 2.0f); 387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetZoom(ui_zoom_); 388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetLight(ui_light_); 389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Send UI values to JS to reset html sliders. 391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PostUpdateMessage("set_zoom", ui_zoom_); 392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PostUpdateMessage("set_light", ui_light_); 393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Planet::Planet() : base_tex_(NULL), night_tex_(NULL), num_threads_(0), 397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) benchmarking_(false), benchmark_frame_counter_(0) { 398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Reset(); 400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) RequestTextures(); 401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // By default, render from the dispatch thread. 402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) workers_ = new ThreadPool(num_threads_); 403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PSEventSetFilter(PSE_ALL); 404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ps_context_ = PSContext2DAllocate(PP_IMAGEDATAFORMAT_BGRA_PREMUL); 405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Planet::~Planet() { 408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) delete workers_; 409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PSContext2DFree(ps_context_); 410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Given a region r, derive a rectangle. 413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This rectangle shouldn't overlap with work being done by other workers. 414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// If multithreading, this function is only called by the worker threads. 415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::wMakeRect(int r, int *x, int *y, int *w, int *h) { 416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *x = 0; 417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *w = ps_context_->width; 418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *y = r; 419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *h = 1; 420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 422cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 423cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)inline uint32_t* Planet::wGetAddr(int x, int y) { 424cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return ps_context_->data + x + y * ps_context_->stride / sizeof(uint32_t); 425cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 426cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 427cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This is the inner loop of the ray tracer. Given a pixel span (x0, x1) on 428cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// scanline y, shoot rays into the scene and render what they hit. Use 429cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// scanline coherence to do a few optimizations. 430cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This version uses portable SIMD 4 element single precision floating point 431cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// vectors to perform many of the calculations, and builds only on PNaCl. 432cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::wRenderPixelSpan(int x0, int x1, int y) { 433cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!base_tex_ || !night_tex_) 434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 435cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const uint32_t kColorBlack = MakeBGRA(0, 0, 0, 0xFF); 436cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const uint32_t kSolidAlpha = MakeBGRA(0, 0, 0, 0xFF); 437cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const f32x4_t kOne = {1.0f, 1.0f, 1.0f, 1.0f}; 438cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const f32x4_t diffuse = {diffuse_r_, diffuse_g_, diffuse_b_, 0.0f}; 439cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const f32x4_t ambient = {ambient_r_, ambient_g_, ambient_b_, 0.0f}; 440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const f32x4_t light_pos = {light_x_, light_y_, light_z_, 1.0f}; 441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const f32x4_t planet_pos = {planet_x_, planet_y_, planet_z_, 1.0f}; 442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const f32x4_t planet_one_over_radius = broadcast(planet_one_over_radius_); 443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const f32x4_t planet_equator = { 444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_equator_x_, planet_equator_y_, planet_equator_z_, 0.0f}; 445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const f32x4_t planet_pole = { 446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_pole_x_, planet_pole_y_, planet_pole_z_, 1.0f}; 447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const f32x4_t planet_pole_x_equator = { 448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_pole_x_equator_x_, planet_pole_x_equator_y_, 449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_pole_x_equator_z_, 0.0f}; 450cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 451cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float width = ps_context_->width; 452cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float height = ps_context_->height; 453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float min_dim = width < height ? width : height; 454cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float offset_x = width < height ? 0 : (width - min_dim) * 0.5f; 455cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float offset_y = width < height ? (height - min_dim) * 0.5f : 0; 456cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float y0 = eye_y_; 457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float z0 = eye_z_; 458cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float y1 = (static_cast<float>(y - offset_y) / min_dim) * 2.0f - 1.0f; 459cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float z1 = 0.0f; 460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float dy = (y1 - y0); 461cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float dz = (z1 - z0); 462cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float dy_dy_dz_dz = dy * dy + dz * dz; 463cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float two_dy_y0_y_two_dz_z0_z = 2.0f * dy * (y0 - planet_y_) + 464cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2.0f * dz * (z0 - planet_z_); 465cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float planet_xyz_eye_xyz = planet_xyz_ + eye_xyz_; 466cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float y_y0_z_z0 = planet_y_ * y0 + planet_z_ * z0; 467cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float oowidth = 1.0f / min_dim; 468cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t* pixels = this->wGetAddr(x0, y); 469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int x = x0; x <= x1; ++x) { 470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // scan normalized screen -1..1 471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float x1 = (static_cast<float>(x - offset_x) * oowidth) * 2.0f - 1.0f; 472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // eye 473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float x0 = eye_x_; 474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // delta from screen to eye 475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float dx = (x1 - x0); 476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // build a, b, c 477cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float a = dx * dx + dy_dy_dz_dz; 478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float b = 2.0f * dx * (x0 - planet_x_) + two_dy_y0_y_two_dz_z0_z; 479cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float c = planet_xyz_eye_xyz + 480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) -2.0f * (planet_x_ * x0 + y_y0_z_z0) - (planet_radius2_); 481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // calculate discriminant 482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float disc = b * b - 4.0f * a * c; 483cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Did ray hit the sphere? 485cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (disc < 0.0f) { 486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *pixels = kColorBlack; 487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ++pixels; 488cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 489cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 490cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 491cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) f32x4_t delta = {dx, dy, dz, 1.0f}; 492cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) f32x4_t base = {x0, y0, z0, 1.0f}; 493cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 494cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Calc parametric t value. 495cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float t = (-b - inline_sqrt(disc)) / (2.0f * a); 496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 497cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) f32x4_t pos = base + broadcast(t) * delta; 498cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) f32x4_t normal = (pos - planet_pos) * planet_one_over_radius; 499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 500cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Misc raytrace calculations. 501cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) f32x4_t L = light_pos - pos; 502cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float Lq = 1.0f / inline_quick_sqrt(dot3(L, L)); 503cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) L = L * broadcast(Lq); 504cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float d = dot3(L, normal); 505cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) f32x4_t p = diffuse * broadcast(d) + ambient; 506cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float ds = -dot3(normal, planet_pole); 507cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float ang = acos_.TableLerp(ds); 508cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float v = ang * kOneOverPI; 509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float dp = dot3(planet_equator, normal); 510cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float w = dp / sinf(ang); 511cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (w > 1.0f) w = 1.0f; 512cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (w < -1.0f) w = -1.0f; 513cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float th = acos_.TableLerp(w) * kOneOver2PI; 514cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float dps = dot3(planet_pole_x_equator, normal); 515cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float u; 516cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (dps < 0.0f) 517cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) u = th; 518cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else 519cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) u = 1.0f - th; 520cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 521cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Look up daylight texel. 522cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int tx = static_cast<int>(u * base_tex_->width); 523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int ty = static_cast<int>(v * base_tex_->height); 524cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int offset = tx + ty * base_tex_->width; 525cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t base_texel = base_tex_->pixels[offset]; 526cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) f32x4_t dc = ExtractRGBA(base_texel); 527cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 528cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Look up night texel. 529cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int nix = static_cast<int>(u * night_tex_->width); 530cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int niy = static_cast<int>(v * night_tex_->height); 531cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int noffset = nix + niy * night_tex_->width; 532cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t night_texel = night_tex_->pixels[noffset]; 533cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) f32x4_t nc = ExtractRGBA(night_texel); 534cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 535cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Blend between daylight (dc) and nighttime (nc) color. 536cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) f32x4_t pc = min(p, kOne); 537cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) f32x4_t fc = dc * p + nc * (kOne - pc); 538cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t color = PackBGRA(fc); 539cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 540cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *pixels = color | kSolidAlpha; 541cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ++pixels; 542cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 543cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 544cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 545cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Renders a rectangular area of the screen, scan line at a time 546cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::wRenderRect(int x, int y, int w, int h) { 547cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int j = y; j < (y + h); ++j) { 548cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this->wRenderPixelSpan(x, x + w - 1, j); 549cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 550cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 551cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 552cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// If multithreading, this function is only called by the worker threads. 553cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::wRenderRegion(int region) { 554cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // convert region # into x0, y0, x1, y1 rectangle 555cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int x, y, w, h; 556cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) wMakeRect(region, &x, &y, &w, &h); 557cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // render this rectangle 558cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) wRenderRect(x, y, w, h); 559cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 560cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 561cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Entry point for worker thread. Can't pass a member function around, so we 562cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// have to do this little round-about. 563cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::wRenderRegionEntry(int region, void* thiz) { 564cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static_cast<Planet*>(thiz)->wRenderRegion(region); 565cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 566cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 567cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Renders the planet, dispatching the work to multiple threads. 568cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::Render() { 569cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) workers_->Dispatch(ps_context_->height, wRenderRegionEntry, this); 570cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 571cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 572cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Pre-calculations to make inner loops faster. 573cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::CacheCalcs() { 574cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_xyz_ = planet_x_ * planet_x_ + 575cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_y_ * planet_y_ + 576cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_z_ * planet_z_; 577cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_radius2_ = planet_radius_ * planet_radius_; 578cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_one_over_radius_ = 1.0f / planet_radius_; 579cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) eye_xyz_ = eye_x_ * eye_x_ + eye_y_ * eye_y_ + eye_z_ * eye_z_; 580cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // spin vector from center->equator 581cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_equator_x_ = cos(planet_spin_x_); 582cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_equator_y_ = 0.0f; 583cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_equator_z_ = sin(planet_spin_x_); 584cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 585cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // cache cross product of pole & equator 586cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_pole_x_equator_x_ = planet_pole_y_ * planet_equator_z_ - 587cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_pole_z_ * planet_equator_y_; 588cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_pole_x_equator_y_ = planet_pole_z_ * planet_equator_x_ - 589cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_pole_x_ * planet_equator_z_; 590cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_pole_x_equator_z_ = planet_pole_x_ * planet_equator_y_ - 591cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_pole_y_ * planet_equator_x_; 592cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 593cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 594cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::SetPlanetXYZR(float x, float y, float z, float r) { 595cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_x_ = x; 596cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_y_ = y; 597cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_z_ = z; 598cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_radius_ = r; 599cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CacheCalcs(); 600cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 601cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 602cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::SetEyeXYZ(float x, float y, float z) { 603cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) eye_x_ = x; 604cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) eye_y_ = y; 605cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) eye_z_ = z; 606cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CacheCalcs(); 607cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 608cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 609cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::SetLightXYZ(float x, float y, float z) { 610cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) light_x_ = x; 611cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) light_y_ = y; 612cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) light_z_ = z; 613cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CacheCalcs(); 614cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 615cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 616cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::SetAmbientRGB(float r, float g, float b) { 617cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ambient_r_ = r; 618cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ambient_g_ = g; 619cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ambient_b_ = b; 620cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CacheCalcs(); 621cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 622cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 623cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::SetDiffuseRGB(float r, float g, float b) { 624cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) diffuse_r_ = r; 625cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) diffuse_g_ = g; 626cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) diffuse_b_ = b; 627cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CacheCalcs(); 628cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 629cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 630cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::SetPlanetPole(float x, float y, float z) { 631cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_pole_x_ = x; 632cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_pole_y_ = y; 633cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_pole_z_ = z; 634cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CacheCalcs(); 635cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 636cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 637cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::SetPlanetEquator(float x, float y, float z) { 638cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // This is really over-ridden by spin at the momenent. 639cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_equator_x_ = x; 640cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_equator_y_ = y; 641cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_equator_z_ = z; 642cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CacheCalcs(); 643cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 644cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 645cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::SetPlanetSpin(float x, float y) { 646cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_spin_x_ = x; 647cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) planet_spin_y_ = y; 648cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CacheCalcs(); 649cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 650cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 651cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Run a simple sim to spin the planet. Update loop is run once per frame. 652cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Called from the main thread only and only when the worker threads are idle. 653cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::UpdateSim() { 654cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float x = planet_spin_x_ + ui_spin_x_; 655cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float y = planet_spin_y_ + ui_spin_y_; 656cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // keep in nice range 657cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (x > (kPI * 2.0f)) 658cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) x = x - kPI * 2.0f; 659cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else if (x < (-kPI * 2.0f)) 660cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) x = x + kPI * 2.0f; 661cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (y > (kPI * 2.0f)) 662cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) y = y - kPI * 2.0f; 663cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else if (y < (-kPI * 2.0f)) 664cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) y = y + kPI * 2.0f; 665cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetPlanetSpin(x, y); 666cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 667cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 668cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::StartBenchmark() { 669cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // For more consistent benchmark numbers, reset to default state. 670cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Reset(); 671cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) printf("Benchmark started...\n"); 672cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) benchmark_frame_counter_ = kFramesToBenchmark; 673cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) benchmarking_ = true; 674cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) benchmark_start_time_ = getseconds(); 675cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 676cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 677cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::EndBenchmark() { 678cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) benchmark_end_time_ = getseconds(); 679cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) printf("Benchmark ended... time: %2.5f\n", 680cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) benchmark_end_time_ - benchmark_start_time_); 681cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) benchmarking_ = false; 682cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) benchmark_frame_counter_ = 0; 683cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) double total_time = benchmark_end_time_ - benchmark_start_time_; 684cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Send benchmark result to JS. 685cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PostUpdateMessage("benchmark_result", total_time); 686cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 687cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 688cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::SetZoom(float zoom) { 689cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui_zoom_ = std::min(kZoomMax, std::max(kZoomMin, zoom)); 690cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetEyeXYZ(0.0f, 0.0f, -ui_zoom_); 691cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 692cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 693cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::SetLight(float light) { 694cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui_light_ = std::min(kLightMax, std::max(kLightMin, light)); 695cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetDiffuseRGB(0.8f * ui_light_, 0.8f * ui_light_, 0.8f * ui_light_); 696cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetAmbientRGB(0.4f * ui_light_, 0.4f * ui_light_, 0.4f * ui_light_); 697cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 698cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 699cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::SetTexture(const std::string& name, int width, int height, 700cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t* pixels) { 701cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (pixels) { 702cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (name == "earth.jpg") { 703cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) delete base_tex_; 704cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base_tex_ = new Texture(width, height, pixels); 705cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (name == "earthnight.jpg") { 706cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) delete night_tex_; 707cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) night_tex_ = new Texture(width, height, pixels); 708cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 709cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 710cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 711cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 712cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::SpinPlanet(pp::Point new_point, pp::Point last_point) { 713cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float delta_x = static_cast<float>(new_point.x() - last_point.x()); 714cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float delta_y = static_cast<float>(new_point.y() - last_point.y()); 715cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float spin_x = std::min(10.0f, std::max(-10.0f, delta_x * 0.5f)); 716cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float spin_y = std::min(10.0f, std::max(-10.0f, delta_y * 0.5f)); 717cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui_spin_x_ = spin_x / 100.0f; 718cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui_spin_y_ = spin_y / 100.0f; 719cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui_last_point_ = new_point; 720cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 721cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 722cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Handle input events from the user and messages from JS. 723cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::HandleEvent(PSEvent* ps_event) { 724cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Give the 2D context a chance to process the event. 725cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (0 != PSContext2DHandleEvent(ps_context_, ps_event)) 726cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 727cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (ps_event->type == PSE_INSTANCE_HANDLEINPUT) { 728cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Convert Pepper Simple event to a PPAPI C++ event 729cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::InputEvent event(ps_event->as_resource); 730cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) switch (event.GetType()) { 731cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case PP_INPUTEVENT_TYPE_KEYDOWN: { 732cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::KeyboardInputEvent key(event); 733cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t key_code = key.GetKeyCode(); 734cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (key_code == 84) // 't' key 735cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!benchmarking_) 736cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) StartBenchmark(); 737cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 738cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 739cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case PP_INPUTEVENT_TYPE_MOUSEDOWN: 740cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case PP_INPUTEVENT_TYPE_MOUSEMOVE: { 741cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::MouseInputEvent mouse = pp::MouseInputEvent(event); 742cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (mouse.GetModifiers() & PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) { 743cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (event.GetType() == PP_INPUTEVENT_TYPE_MOUSEDOWN) 744cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SpinPlanet(mouse.GetPosition(), mouse.GetPosition()); 745cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else 746cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SpinPlanet(mouse.GetPosition(), ui_last_point_); 747cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 748cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 749cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 750cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case PP_INPUTEVENT_TYPE_WHEEL: { 751cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::WheelInputEvent wheel = pp::WheelInputEvent(event); 752cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PP_FloatPoint ticks = wheel.GetTicks(); 753cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetZoom(ui_zoom_ + (ticks.x + ticks.y) * kWheelSpeed); 754cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Update html slider by sending update message to JS. 755cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PostUpdateMessage("set_zoom", ui_zoom_); 756cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 757cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 758cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case PP_INPUTEVENT_TYPE_TOUCHSTART: 759cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case PP_INPUTEVENT_TYPE_TOUCHMOVE: { 760cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::TouchInputEvent touches = pp::TouchInputEvent(event); 761cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t count = touches.GetTouchCount(PP_TOUCHLIST_TYPE_TOUCHES); 762cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (count > 0) { 763cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Use first touch point to spin planet. 764cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::TouchPoint touch = 765cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) touches.GetTouchByIndex(PP_TOUCHLIST_TYPE_TOUCHES, 0); 766cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::Point screen_point(touch.position().x(), 767cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) touch.position().y()); 768cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (event.GetType() == PP_INPUTEVENT_TYPE_TOUCHSTART) 769cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SpinPlanet(screen_point, screen_point); 770cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else 771cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SpinPlanet(screen_point, ui_last_point_); 772cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 773cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 774cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 775cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) default: 776cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 777cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 778cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (ps_event->type == PSE_INSTANCE_HANDLEMESSAGE) { 779cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Convert Pepper Simple message to PPAPI C++ vars 780cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::Var var(ps_event->as_var); 781cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (var.is_dictionary()) { 782cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::VarDictionary dictionary(var); 783cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string message = dictionary.Get("message").AsString(); 784cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (message == "run benchmark" && !benchmarking_) { 785cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) StartBenchmark(); 786cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (message == "set_light") { 787cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetLight(static_cast<float>(dictionary.Get("value").AsDouble())); 788cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (message == "set_zoom") { 789cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetZoom(static_cast<float>(dictionary.Get("value").AsDouble())); 790cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (message == "set_threads") { 791cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int threads = dictionary.Get("value").AsInt(); 792cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) delete workers_; 793cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) workers_ = new ThreadPool(threads); 794cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (message == "texture") { 795cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string name = dictionary.Get("name").AsString(); 796cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int width = dictionary.Get("width").AsInt(); 797cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int height = dictionary.Get("height").AsInt(); 798cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::VarArrayBuffer array_buffer(dictionary.Get("data")); 799cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!name.empty() && !array_buffer.is_null()) { 800cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (width > 0 && height > 0) { 801cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t* pixels = static_cast<uint32_t*>(array_buffer.Map()); 802cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetTexture(name, width, height, pixels); 803cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) array_buffer.Unmap(); 804cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 805cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 806cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 807cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 808cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) printf("Handle message unknown type: %s\n", var.DebugString().c_str()); 809cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 810cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 811cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 812cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 813cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// PostUpdateMessage() helper function for sending small messages to JS. 814cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::PostUpdateMessage(const char* message_name, double value) { 815cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::VarDictionary message; 816cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) message.Set("message", message_name); 817cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) message.Set("value", value); 818cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PSInterfaceMessaging()->PostMessage(PSGetInstanceId(), message.pp_var()); 819cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 820cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 821cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Planet::Update() { 822cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // When benchmarking is running, don't update display via 823cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // PSContext2DSwapBuffer() - vsync is enabled by default, and will throttle 824cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // the benchmark results. 825cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PSContext2DGetBuffer(ps_context_); 826cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (NULL == ps_context_->data) 827cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 828cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 829cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) do { 830cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UpdateSim(); 831cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Render(); 832cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!benchmarking_) break; 833cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) --benchmark_frame_counter_; 834cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } while (benchmark_frame_counter_ > 0); 835cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (benchmarking_) 836cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EndBenchmark(); 837cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 838cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PSContext2DSwapBuffer(ps_context_); 839cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 840cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 841cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 842cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Starting point for the module. We do not use main since it would 843cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// collide with main in libppapi_cpp. 844cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int example_main(int argc, char* argv[]) { 845cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Planet earth; 846cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) while (true) { 847cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PSEvent* ps_event; 848cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Consume all available events 849cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) while ((ps_event = PSEventTryAcquire()) != NULL) { 850cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) earth.HandleEvent(ps_event); 851cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PSEventRelease(ps_event); 852cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 853cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Do simulation, render and present. 854cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) earth.Update(); 855cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 856cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 857cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 0; 858cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 859cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 860cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Register the function to call once the Instance Object is initialized. 861cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// see: pappi_simple/ps_main.h 862cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PPAPI_SIMPLE_REGISTER_MAIN(example_main); 863