root/native_client_sdk/src/examples/demo/flock/flock.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ResetFlock
  2. Render
  3. example_main

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>

#include <algorithm>
#include <sstream>
#include <string>
#include <vector>

#include "ppapi/c/pp_rect.h"
#include "ppapi/c/pp_size.h"

#include "ppapi_simple/ps_context_2d.h"
#include "ppapi_simple/ps_main.h"

#include "goose.h"
#include "sprite.h"
#include "vector2.h"


namespace {
  // The goose sprites rotate in increments of 5 degrees.
const double kGooseHeadingIncrement = (5.0 * M_PI) / 180.0;
}  // namespace

struct ImageFormat {
  int width;
  int height;
  int channels;
};

Sprite* g_goose_sprite;
std::vector<Goose> g_geese;
std::vector<Vector2> g_attractors;


void ResetFlock(PSContext2D_t* ctx, size_t count) {
  Vector2 center(0.5 * ctx->width, 0.5 * ctx->height);

  g_geese.resize(count);
  for (size_t i = 0; i < count; i++) {
    double dx = (double) rand() / (double) RAND_MAX;
    double dy = (double) rand() / (double) RAND_MAX;
    g_geese[i] = Goose(center, Vector2(dx, dy));
  }
}

void Render(PSContext2D_t* ctx) {
  PSContext2DGetBuffer(ctx);
  const size_t num_geese = g_geese.size();

  if (NULL == g_goose_sprite) return;
  if (NULL == ctx->data) return;

  // Clear to WHITE
  memset(ctx->data, 0xFF, ctx->stride * ctx->height);

  int32_t sprite_side_length = g_goose_sprite->size().height();
  pp::Rect sprite_src_rect(0, 0, sprite_side_length, sprite_side_length);
  pp::Rect canvas_bounds(pp::Size(ctx->width, ctx->height));


  // Run the simulation for each goose.
  for (size_t i = 0; i < num_geese; i++) {
    Goose& goose = g_geese[i];

    // Update position and orientation
    goose.SimulationTick(g_geese, g_attractors, canvas_bounds);
    pp::Point dest_point(goose.location().x() - sprite_side_length / 2,
                         goose.location().y() - sprite_side_length / 2);

    // Compute image to use
    double heading = goose.velocity().Heading();
    if (heading < 0.0)
      heading = M_PI * 2.0 + heading;

    int32_t sprite_index =
        static_cast<int32_t>(heading / kGooseHeadingIncrement);

    sprite_src_rect.set_x(sprite_index * sprite_side_length);
    g_goose_sprite->CompositeFromRectToPoint(
        sprite_src_rect,
        ctx->data, canvas_bounds, 0,
        dest_point);
  }

  PSContext2DSwapBuffer(ctx);
}

/*
 * Starting point for the module.  We do not use main since it would
 * collide with main in libppapi_cpp.
 */
int example_main(int argc, char *argv[]) {
  ImageFormat fmt;
  uint32_t* buffer;
  size_t len;

  PSEventSetFilter(PSE_ALL);

  // Mount the images directory as an HTTP resource.
  mount("images", "/images", "httpfs", 0, "");

  FILE* fp = fopen("/images/flock_green.raw", "rb");
  fread(&fmt, sizeof(fmt), 1, fp);

  len = fmt.width * fmt.height * fmt.channels;
  buffer = new uint32_t[len];
  fread(buffer, 1, len, fp);
  fclose(fp);

  g_goose_sprite = new Sprite(buffer, pp::Size(fmt.width, fmt.height), 0);

  PSContext2D_t* ctx = PSContext2DAllocate(PP_IMAGEDATAFORMAT_BGRA_PREMUL);
  ResetFlock(ctx, 50);
  while (1) {
    PSEvent* event;

    // Consume all available events
    while ((event = PSEventTryAcquire()) != NULL) {
      PSContext2DHandleEvent(ctx, event);
      PSEventRelease(event);
    }

    if (ctx->bound) {
      Render(ctx);
    } else {
      // If not bound, wait for an event which may signal a context becoming
      // available, instead of spinning.
      event = PSEventWaitAcquire();
      if (PSContext2DHandleEvent(ctx, event))
        ResetFlock(ctx, 50);
      PSEventRelease(event);
    }
  }

  return 0;
}

/*
 * Register the function to call once the Instance Object is initialized.
 * see: pappi_simple/ps_main.h
 */
PPAPI_SIMPLE_REGISTER_MAIN(example_main);

/* [<][>][^][v][top][bottom][index][help] */