11e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
21e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
31e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// found in the LICENSE file.
41e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
51e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <assert.h>
61e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <math.h>
71e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <ppapi/c/ppb_input_event.h>
81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <ppapi/cpp/input_event.h>
91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <ppapi/cpp/var.h>
101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <ppapi/cpp/var_array.h>
111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <ppapi/cpp/var_array_buffer.h>
121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <ppapi/cpp/var_dictionary.h>
131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <pthread.h>
141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <stdio.h>
151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <stdlib.h>
161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <string.h>
171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <unistd.h>
181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <algorithm>
201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <string>
211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "common/fps.h"
231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ppapi_simple/ps.h"
241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ppapi_simple/ps_context_2d.h"
251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ppapi_simple/ps_event.h"
261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ppapi_simple/ps_interface.h"
271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ppapi_simple/ps_main.h"
281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "sdk_util/thread_pool.h"
291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using namespace sdk_util;  // For sdk_util::ThreadPool
311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Global properties used to setup Voronoi demo.
331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace {
341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const int kMinRectSize = 4;
351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const int kStartRecurseSize = 32;  // must be power-of-two
361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const float kHugeZ = 1.0e38f;
371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const float kPI = M_PI;
381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const float kTwoPI = kPI * 2.0f;
391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const unsigned int kRandomStartSeed = 0xC0DE533D;
401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const int kMaxPointCount = 1024;
411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const int kStartPointCount = 48;
421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const int kDefaultNumRegions = 256;
431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)unsigned int g_rand_state = kRandomStartSeed;
451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// random number helper
471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)inline unsigned char rand255() {
481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return static_cast<unsigned char>(rand_r(&g_rand_state) & 255);
491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// random number helper
521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)inline float frand() {
531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return (static_cast<float>(rand_r(&g_rand_state)) /
541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      static_cast<float>(RAND_MAX));
551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// reset random seed
581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)inline void rand_reset(unsigned int seed) {
591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  g_rand_state = seed;
601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)inline uint32_t next_pow2(uint32_t x) {
631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Via Hacker's Delight, section 3.2 "Rounding Up/Down to the Next Power of 2"
641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  --x;
651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  x |= (x >> 1);
661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  x |= (x >> 2);
671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  x |= (x >> 4);
681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  x |= (x >> 8);
691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  x |= (x >> 16);
701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return x + 1;
711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// BGRA helper function, for constructing a pixel for a BGRA buffer.
741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)inline uint32_t MakeBGRA(uint32_t b, uint32_t g, uint32_t r, uint32_t a) {
751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return (((a) << 24) | ((r) << 16) | ((g) << 8) | (b));
761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}  // namespace
781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Vec2, simple 2D vector
801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)struct Vec2 {
811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  float x, y;
821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Vec2() {}
831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Vec2(float px, float py) {
841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    x = px;
851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    y = py;
861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void Set(float px, float py) {
881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    x = px;
891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    y = py;
901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)};
921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// The main object that runs Voronoi simulation.
941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)class Voronoi {
951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) public:
961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Voronoi();
971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual ~Voronoi();
981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Runs a tick of the simulations, update 2D output.
991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void Update();
1001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Handle event from user, or message from JS.
1011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void HandleEvent(PSEvent* ps_event);
1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) private:
1041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Methods prefixed with 'w' are run on worker threads.
1051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  uint32_t* wGetAddr(int x, int y);
1061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int wCell(float x, float y);
1071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  inline void wFillSpan(uint32_t *pixels, uint32_t color, int width);
1081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void wRenderTile(int x, int y, int w, int h);
1091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void wProcessTile(int x, int y, int w, int h);
1101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void wSubdivide(int x, int y, int w, int h);
1111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void wMakeRect(int region, int *x, int *y, int *w, int *h);
1121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bool wTestRect(int *m, int x, int y, int w, int h);
1131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void wFillRect(int x, int y, int w, int h, uint32_t color);
1141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void wRenderRect(int x0, int y0, int x1, int y1);
1151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void wRenderRegion(int region);
1161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  static void wRenderRegionEntry(int region, void *thiz);
1171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // These methods are only called by the main thread.
1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void Reset();
1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void UpdateSim();
1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void RenderDot(float x, float y, uint32_t color1, uint32_t color2);
1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void SuperimposePositions();
1231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void Render();
1241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void Draw();
1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Helper to post small update messages to JS.
1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void PostUpdateMessage(const char* message_name, double value);
1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  PSContext2D_t* ps_context_;
1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Vec2 positions_[kMaxPointCount];
1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Vec2 screen_positions_[kMaxPointCount];
1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Vec2 velocities_[kMaxPointCount];
1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  uint32_t colors_[kMaxPointCount];
1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  float ang_;
1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int num_regions_;
1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int num_threads_;
1361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int point_count_;
1371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bool draw_points_;
1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bool draw_interiors_;
1391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ThreadPool* workers_;
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  FpsState fps_state_;
1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)};
1421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Voronoi::Reset() {
1451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  rand_reset(kRandomStartSeed);
1461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ang_ = 0.0f;
1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (int i = 0; i < kMaxPointCount; i++) {
1481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // random initial start position
1491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const float x = frand();
1501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const float y = frand();
1511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    positions_[i].Set(x, y);
1521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // random directional velocity ( -1..1, -1..1 )
1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const float speed = 0.0005f;
1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const float u = (frand() * 2.0f - 1.0f) * speed;
1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const float v = (frand() * 2.0f - 1.0f) * speed;
1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    velocities_[i].Set(u, v);
1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // 'unique' color (well... unique enough for our purposes)
1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    colors_[i] = MakeBGRA(rand255(), rand255(), rand255(), 255);
1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)Voronoi::Voronoi() : num_regions_(kDefaultNumRegions), num_threads_(0),
1631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    point_count_(kStartPointCount), draw_points_(true), draw_interiors_(true) {
1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Reset();
1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // By default, render from the dispatch thread.
1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  workers_ = new ThreadPool(num_threads_);
1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  PSEventSetFilter(PSE_ALL);
1681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ps_context_ = PSContext2DAllocate(PP_IMAGEDATAFORMAT_BGRA_PREMUL);
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  FpsInit(&fps_state_);
1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)Voronoi::~Voronoi() {
1731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  delete workers_;
1741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  PSContext2DFree(ps_context_);
1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)inline uint32_t* Voronoi::wGetAddr(int x, int y) {
1781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return ps_context_->data + x + y * ps_context_->stride / sizeof(uint32_t);
1791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// This is the core of the Voronoi calculation.  At a given point on the
1821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// screen, iterate through all voronoi positions and render them as 3D cones.
1831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// We're looking for the voronoi cell that generates the closest z value.
1841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// (not really cones - since it is all relative, we avoid doing the
1851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// expensive sqrt and test against z*z instead)
1861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// If multithreading, this function is only called by the worker threads.
1871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)int Voronoi::wCell(float x, float y) {
1881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int closest_cell = 0;
1891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  float zz = kHugeZ;
1901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Vec2* pos = screen_positions_;
1911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (int i = 0; i < point_count_; ++i) {
1921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // measured 5.18 cycles per iteration on a core2
1931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    float dx = x - pos[i].x;
1941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    float dy = y - pos[i].y;
1951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    float dd = (dx * dx + dy * dy);
1961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (dd < zz) {
1971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      zz = dd;
1981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      closest_cell = i;
1991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
2001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return closest_cell;
2021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Given a region r, derive a non-overlapping rectangle for a thread to
2051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// work on.
2061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// If multithreading, this function is only called by the worker threads.
2071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Voronoi::wMakeRect(int r, int* x, int* y, int* w, int* h) {
2081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int parts = 16;
2091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  assert(parts * parts == num_regions_);
2101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Round up to the nearest power of two so we can divide by parts cleanly. We
2111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // could round up to the nearest 16 pixels, but it runs much faster when
2121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // subdividing power-of-two squares.
2131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  //
2141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Many of these squares are outside of the canvas, but they will be
2151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // trivially culled by wRenderRect.
2161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  *w = static_cast<int>(next_pow2(ps_context_->width)) / parts;
2171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  *h = static_cast<int>(next_pow2(ps_context_->height)) / parts;
2181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  *x = *w * (r % parts);
2191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  *y = *h * ((r / parts) % parts);
2201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Test 4 corners of a rectangle to see if they all belong to the same
2231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// voronoi cell.  Each test is expensive so bail asap.  Returns true
2241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// if all 4 corners match.
2251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// If multithreading, this function is only called by the worker threads.
2261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool Voronoi::wTestRect(int* m, int x, int y, int w, int h) {
2271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // each test is expensive, so exit ASAP
2281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int m0 = wCell(x, y);
2291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int m1 = wCell(x + w - 1, y);
2301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (m0 != m1) return false;
2311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int m2 = wCell(x, y + h - 1);
2321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (m0 != m2) return false;
2331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int m3 = wCell(x + w - 1, y + h - 1);
2341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (m0 != m3) return false;
2351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // all 4 corners belong to the same cell
2361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  *m = m0;
2371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return true;
2381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Quickly fill a span of pixels with a solid color.
2411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// If multithreading, this function is only called by the worker threads.
2421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)inline void Voronoi::wFillSpan(uint32_t* pixels, uint32_t color, int width) {
2431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!draw_interiors_) {
2441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const uint32_t gray = MakeBGRA(128, 128, 128, 255);
2451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    color = gray;
2461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (int i = 0; i < width; ++i)
2491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    *pixels++ = color;
2501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Quickly fill a rectangle with a solid color.
2531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// If multithreading, this function is only called by the worker threads.
2541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Voronoi::wFillRect(int x, int y, int w, int h, uint32_t color) {
2551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const uint32_t stride_in_pixels = ps_context_->stride / sizeof(uint32_t);
2561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  uint32_t* pixels = wGetAddr(x, y);
2571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (int j = 0; j < h; j++) {
2581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    wFillSpan(pixels, color, w);
2591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    pixels += stride_in_pixels;
2601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// When recursive subdivision reaches a certain minimum without finding a
2641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// rectangle that has four matching corners belonging to the same voronoi
2651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// cell, this function will break the retangular 'tile' into smaller scanlines
2661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)//  and look for opportunities to quick fill at the scanline level.  If the
2671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// scanline can't be quick filled, it will slow down even further and compute
2681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// voronoi membership per pixel.
2691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Voronoi::wRenderTile(int x, int y, int w, int h) {
2701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // rip through a tile
2711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const uint32_t stride_in_pixels = ps_context_->stride / sizeof(uint32_t);
2721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  uint32_t* pixels = wGetAddr(x, y);
2731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (int j = 0; j < h; j++) {
2741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // get start and end cell values
2751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    int ms = wCell(x + 0, y + j);
2761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    int me = wCell(x + w - 1, y + j);
2771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // if the end points are the same, quick fill the span
2781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (ms == me) {
2791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      wFillSpan(pixels, colors_[ms], w);
2801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    } else {
2811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // else compute each pixel in the span... this is the slow part!
2821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      uint32_t* p = pixels;
2831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      *p++ = colors_[ms];
2841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      for (int i = 1; i < (w - 1); i++) {
2851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        int m = wCell(x + i, y + j);
2861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        *p++ = colors_[m];
2871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      }
2881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      *p++ = colors_[me];
2891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
2901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    pixels += stride_in_pixels;
2911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Take a rectangular region and do one of -
2951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)//   If all four corners below to the same voronoi cell, stop recursion and
2961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// quick fill the rectangle.
2971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)//   If the minimum rectangle size has been reached, break out of recursion
2981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// and process the rectangle.  This small rectangle is called a tile.
2991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)//   Otherwise, keep recursively subdividing the rectangle into 4 equally
3001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// sized smaller rectangles.
3011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// If multithreading, this function is only called by the worker threads.
3021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Voronoi::wSubdivide(int x, int y, int w, int h) {
3031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int m;
3041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // if all 4 corners are equal, quick fill interior
3051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (wTestRect(&m, x, y, w, h)) {
3061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    wFillRect(x, y, w, h, colors_[m]);
3071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  } else {
3081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // did we reach the minimum rectangle size?
3091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if ((w <= kMinRectSize) || (h <= kMinRectSize)) {
3101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      wRenderTile(x, y, w, h);
3111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    } else {
3121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // else recurse into smaller rectangles
3131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      const int half_w = w / 2;
3141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      const int half_h = h / 2;
3151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      wSubdivide(x, y, half_w, half_h);
3161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      wSubdivide(x + half_w, y, w - half_w, half_h);
3171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      wSubdivide(x, y + half_h, half_w, h - half_h);
3181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      wSubdivide(x + half_w, y + half_h, w - half_w, h - half_h);
3191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
3201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// This function cuts up the rectangle into squares (preferably power-of-two).
3241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// If multithreading, this function is only called by the worker threads.
3251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Voronoi::wRenderRect(int x, int y, int w, int h) {
3261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (int iy = y; iy < (y + h); iy += kStartRecurseSize) {
3271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    for (int ix = x; ix < (x + w); ix += kStartRecurseSize) {
3281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      int iw = kStartRecurseSize;
3291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      int ih = kStartRecurseSize;
3301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // Clamp width + height.
3311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (ix + iw > ps_context_->width)
3321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        iw = ps_context_->width - ix;
3331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (iy + ih > ps_context_->height)
3341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        ih = ps_context_->height - iy;
3351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (iw <= 0 || ih <= 0)
3361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        continue;
3371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      wSubdivide(ix, iy, iw, ih);
3391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
3401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// If multithreading, this function is only called by the worker threads.
3441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Voronoi::wRenderRegion(int region) {
3451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // convert region # into x0, y0, x1, y1 rectangle
3461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int x, y, w, h;
3471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  wMakeRect(region, &x, &y, &w, &h);
3481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // render this rectangle
3491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  wRenderRect(x, y, w, h);
3501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Entry point for worker thread.  Can't pass a member function around, so we
3531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// have to do this little round-about.
3541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Voronoi::wRenderRegionEntry(int region, void* thiz) {
3551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  static_cast<Voronoi*>(thiz)->wRenderRegion(region);
3561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Function Voronoi::UpdateSim()
3591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Run a simple sim to move the voronoi positions.  This update loop
3601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// is run once per frame.  Called from the main thread only, and only
3611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// when the worker threads are idle.
3621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Voronoi::UpdateSim() {
3631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ang_ += 0.002f;
3641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (ang_ > kTwoPI) {
3651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    ang_ = ang_ - kTwoPI;
3661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  float z = cosf(ang_) * 3.0f;
3681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // push the points around on the screen for animation
3691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (int j = 0; j < kMaxPointCount; j++) {
3701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    positions_[j].x += (velocities_[j].x) * z;
3711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    positions_[j].y += (velocities_[j].y) * z;
3721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    screen_positions_[j].x = positions_[j].x * ps_context_->width;
3731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    screen_positions_[j].y = positions_[j].y * ps_context_->height;
3741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Renders a small diamond shaped dot at x, y clipped against the window
3781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Voronoi::RenderDot(float x, float y, uint32_t color1, uint32_t color2) {
3791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int ix = static_cast<int>(x);
3801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int iy = static_cast<int>(y);
3811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const uint32_t stride_in_pixels = ps_context_->stride / sizeof(uint32_t);
3821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // clip it against window
3831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (ix < 1) return;
3841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (ix >= (ps_context_->width - 1)) return;
3851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (iy < 1) return;
3861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (iy >= (ps_context_->height - 1)) return;
3871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  uint32_t* pixel = wGetAddr(ix, iy);
3881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // render dot as a small diamond
3891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  *pixel = color1;
3901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  *(pixel - 1) = color2;
3911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  *(pixel + 1) = color2;
3921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  *(pixel - stride_in_pixels) = color2;
3931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  *(pixel + stride_in_pixels) = color2;
3941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Superimposes dots on the positions.
3971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Voronoi::SuperimposePositions() {
3981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const uint32_t white = MakeBGRA(255, 255, 255, 255);
3991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const uint32_t gray = MakeBGRA(192, 192, 192, 255);
4001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (int i = 0; i < point_count_; i++) {
4011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    RenderDot(
4021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        screen_positions_[i].x, screen_positions_[i].y, white, gray);
4031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
4041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
4051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Renders the Voronoi diagram, dispatching the work to multiple threads.
4071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Voronoi::Render() {
4081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  workers_->Dispatch(num_regions_, wRenderRegionEntry, this);
4091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (draw_points_)
4101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    SuperimposePositions();
4111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
4121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Handle input events from the user and messages from JS.
4141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Voronoi::HandleEvent(PSEvent* ps_event) {
4151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Give the 2D context a chance to process the event.
4161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (0 != PSContext2DHandleEvent(ps_context_, ps_event))
4171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
4181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (ps_event->type == PSE_INSTANCE_HANDLEINPUT) {
4191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Convert Pepper Simple event to a PPAPI C++ event
4201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    pp::InputEvent event(ps_event->as_resource);
4211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    switch (event.GetType()) {
4221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      case PP_INPUTEVENT_TYPE_TOUCHSTART:
4231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      case PP_INPUTEVENT_TYPE_TOUCHMOVE: {
4241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        pp::TouchInputEvent touches = pp::TouchInputEvent(event);
4251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        uint32_t count = touches.GetTouchCount(PP_TOUCHLIST_TYPE_TOUCHES);
4261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        // Touch points 0..n directly set position of points 0..n in
4271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        // Voronoi diagram.
4281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        for (uint32_t i = 0; i < count; i++) {
4291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          pp::TouchPoint touch =
4301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)              touches.GetTouchByIndex(PP_TOUCHLIST_TYPE_TOUCHES, i);
4311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          pp::FloatPoint point = touch.position();
4321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          positions_[i].Set(point.x() / ps_context_->width,
4331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                            point.y() / ps_context_->height);
4341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        }
4351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        break;
4361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      }
4371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      default:
4381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        break;
4391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
4401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  } else if (ps_event->type == PSE_INSTANCE_HANDLEMESSAGE) {
4411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Convert Pepper Simple message to PPAPI C++ var
4421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    pp::Var var(ps_event->as_var);
4431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (var.is_dictionary()) {
4441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      pp::VarDictionary dictionary(var);
4451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      std::string message = dictionary.Get("message").AsString();
4461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (message == "draw_points")
4471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        draw_points_ = dictionary.Get("value").AsBool();
4481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      else if (message == "draw_interiors")
4491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        draw_interiors_ = dictionary.Get("value").AsBool();
4501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      else if (message == "set_points") {
4511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        int num_points = dictionary.Get("value").AsInt();
4521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        point_count_ = std::min(kMaxPointCount, std::max(0, num_points));
4531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      } else if (message == "set_threads") {
4541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        int thread_count = dictionary.Get("value").AsInt();
4551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        delete workers_;
4561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        workers_ = new ThreadPool(thread_count);
4571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      }
4581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
4591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
4601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
4611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// PostUpdateMessage() helper function for sendimg small messages to JS.
4631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Voronoi::PostUpdateMessage(const char* message_name, double value) {
4641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  pp::VarDictionary message;
4651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  message.Set("message", message_name);
4661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  message.Set("value", value);
4671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  PSInterfaceMessaging()->PostMessage(PSGetInstanceId(), message.pp_var());
4681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
4691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Voronoi::Update() {
4711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  PSContext2DGetBuffer(ps_context_);
4721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (NULL == ps_context_->data)
4731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
4741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  UpdateSim();
4761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Render();
4771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  PSContext2DSwapBuffer(ps_context_);
478f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
479f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  double fps;
480f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (FpsStep(&fps_state_, &fps))
481f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PostUpdateMessage("fps", fps);
4821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
4831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Starting point for the module.  We do not use main since it would
4851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// collide with main in libppapi_cpp.
4861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)int example_main(int argc, char* argv[]) {
4871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Voronoi voronoi;
4881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  while (true) {
4891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    PSEvent* ps_event;
4901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Consume all available events.
4911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    while ((ps_event = PSEventTryAcquire()) != NULL) {
4921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      voronoi.HandleEvent(ps_event);
4931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      PSEventRelease(ps_event);
4941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
4951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Do simulation, render and present.
4961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    voronoi.Update();
4971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
4981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return 0;
5001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
5011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Register the function to call once the Instance Object is initialized.
5031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// see: pappi_simple/ps_main.h
5041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)PPAPI_SIMPLE_REGISTER_MAIN(example_main);
505