- add sources.
[platform/framework/web/crosswalk.git] / src / native_client_sdk / src / examples / demo / flock / flock.cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <sys/mount.h>
9
10 #include <algorithm>
11 #include <sstream>
12 #include <string>
13 #include <vector>
14
15 #include "ppapi/c/pp_rect.h"
16 #include "ppapi/c/pp_size.h"
17
18 #include "ppapi_simple/ps_context_2d.h"
19 #include "ppapi_simple/ps_main.h"
20
21 #include "goose.h"
22 #include "sprite.h"
23 #include "vector2.h"
24
25
26 namespace {
27   // The goose sprites rotate in increments of 5 degrees.
28 const double kGooseHeadingIncrement = (5.0 * M_PI) / 180.0;
29 }  // namespace
30
31 struct ImageFormat {
32   int width;
33   int height;
34   int channels;
35 };
36
37 Sprite* g_goose_sprite;
38 std::vector<Goose> g_geese;
39 std::vector<Vector2> g_attractors;
40
41
42 void ResetFlock(PSContext2D_t* ctx, size_t count) {
43   Vector2 center(0.5 * ctx->width, 0.5 * ctx->height);
44
45   g_geese.resize(count);
46   for (size_t i = 0; i < count; i++) {
47     double dx = (double) rand() / (double) RAND_MAX;
48     double dy = (double) rand() / (double) RAND_MAX;
49     g_geese[i] = Goose(center, Vector2(dx, dy));
50   }
51 }
52
53 void Render(PSContext2D_t* ctx) {
54   PSContext2DGetBuffer(ctx);
55   const size_t num_geese = g_geese.size();
56
57   if (NULL == g_goose_sprite) return;
58   if (NULL == ctx->data) return;
59
60   // Clear to WHITE
61   memset(ctx->data, 0xFF, ctx->stride * ctx->height);
62
63   int32_t sprite_side_length = g_goose_sprite->size().height();
64   pp::Rect sprite_src_rect(0, 0, sprite_side_length, sprite_side_length);
65   pp::Rect canvas_bounds(pp::Size(ctx->width, ctx->height));
66
67
68   // Run the simulation for each goose.
69   for (size_t i = 0; i < num_geese; i++) {
70     Goose& goose = g_geese[i];
71
72     // Update position and orientation
73     goose.SimulationTick(g_geese, g_attractors, canvas_bounds);
74     pp::Point dest_point(goose.location().x() - sprite_side_length / 2,
75                          goose.location().y() - sprite_side_length / 2);
76
77     // Compute image to use
78     double heading = goose.velocity().Heading();
79     if (heading < 0.0)
80       heading = M_PI * 2.0 + heading;
81
82     int32_t sprite_index =
83         static_cast<int32_t>(heading / kGooseHeadingIncrement);
84
85     sprite_src_rect.set_x(sprite_index * sprite_side_length);
86     g_goose_sprite->CompositeFromRectToPoint(
87         sprite_src_rect,
88         ctx->data, canvas_bounds, 0,
89         dest_point);
90   }
91
92   PSContext2DSwapBuffer(ctx);
93 }
94
95 /*
96  * Starting point for the module.  We do not use main since it would
97  * collide with main in libppapi_cpp.
98  */
99 int example_main(int argc, char *argv[]) {
100   ImageFormat fmt;
101   uint32_t* buffer;
102   size_t len;
103
104   PSEventSetFilter(PSE_ALL);
105
106   // Mount the images directory as an HTTP resource.
107   mount("images", "/images", "httpfs", 0, "");
108
109   FILE* fp = fopen("/images/flock_green.raw", "rb");
110   fread(&fmt, sizeof(fmt), 1, fp);
111
112   len = fmt.width * fmt.height * fmt.channels;
113   buffer = new uint32_t[len];
114   fread(buffer, 1, len, fp);
115   fclose(fp);
116
117   g_goose_sprite = new Sprite(buffer, pp::Size(fmt.width, fmt.height), 0);
118
119   PSContext2D_t* ctx = PSContext2DAllocate(PP_IMAGEDATAFORMAT_BGRA_PREMUL);
120   ResetFlock(ctx, 50);
121   while (1) {
122     PSEvent* event;
123
124     // Consume all available events
125     while ((event = PSEventTryAcquire()) != NULL) {
126       PSContext2DHandleEvent(ctx, event);
127       PSEventRelease(event);
128     }
129
130     if (ctx->bound) {
131       Render(ctx);
132     } else {
133       // If not bound, wait for an event which may signal a context becoming
134       // available, instead of spinning.
135       event = PSEventWaitAcquire();
136       if (PSContext2DHandleEvent(ctx, event))
137         ResetFlock(ctx, 50);
138       PSEventRelease(event);
139     }
140   }
141
142   return 0;
143 }
144
145 /*
146  * Register the function to call once the Instance Object is initialized.
147  * see: pappi_simple/ps_main.h
148  */
149 PPAPI_SIMPLE_REGISTER_MAIN(example_main);