add js-c interop testing stuff
This commit is contained in:
parent
6d3fc9f0f1
commit
267fa000f6
|
@ -184,3 +184,178 @@ dist
|
||||||
.yarn/install-state.gz
|
.yarn/install-state.gz
|
||||||
.pnp.*
|
.pnp.*
|
||||||
|
|
||||||
|
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
|
||||||
|
logs
|
||||||
|
_.log
|
||||||
|
npm-debug.log_
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# Caches
|
||||||
|
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
|
||||||
|
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
|
||||||
|
pids
|
||||||
|
_.pid
|
||||||
|
_.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Snowpack dependency directory (https://snowpack.dev/)
|
||||||
|
|
||||||
|
web_modules/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional stylelint cache
|
||||||
|
|
||||||
|
.stylelintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variable files
|
||||||
|
|
||||||
|
.env
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
|
||||||
|
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||||
|
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# vuepress v2.x temp and cache directory
|
||||||
|
|
||||||
|
.temp
|
||||||
|
|
||||||
|
# Docusaurus cache and generated files
|
||||||
|
|
||||||
|
.docusaurus
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
|
||||||
|
.vscode-test
|
||||||
|
|
||||||
|
# yarn v2
|
||||||
|
|
||||||
|
.yarn/cache
|
||||||
|
.yarn/unplugged
|
||||||
|
.yarn/build-state.yml
|
||||||
|
.yarn/install-state.gz
|
||||||
|
.pnp.*
|
||||||
|
|
||||||
|
# IntelliJ based IDEs
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Finder (MacOS) folder config
|
||||||
|
.DS_Store
|
||||||
|
|
|
@ -87,7 +87,7 @@ void MainGameLoop(void) {
|
||||||
UpdateCamera(&camera, CAMERA_THIRD_PERSON);
|
UpdateCamera(&camera, CAMERA_THIRD_PERSON);
|
||||||
|
|
||||||
RayCollision collision = {0};
|
RayCollision collision = {0};
|
||||||
collision.distance = 10000000.0f; // arbitrary reasonable distance.
|
collision.distance = 100000.0f; // arbitrary reasonable distance.
|
||||||
collision.hit = false;
|
collision.hit = false;
|
||||||
|
|
||||||
// ray pointing down so we are always just above the floor.
|
// ray pointing down so we are always just above the floor.
|
||||||
|
@ -181,4 +181,4 @@ EM_BOOL onmessage(int eventType,
|
||||||
printf("Failed to emscripten_websocket_close(): %d\n", result);
|
printf("Failed to emscripten_websocket_close(): %d\n", result);
|
||||||
}
|
}
|
||||||
return EM_TRUE;
|
return EM_TRUE;
|
||||||
}
|
}
|
||||||
|
|
2528
client/raymath.h
2528
client/raymath.h
File diff suppressed because it is too large
Load Diff
550
client/rcamera.h
550
client/rcamera.h
|
@ -1,550 +0,0 @@
|
||||||
/*******************************************************************************************
|
|
||||||
*
|
|
||||||
* rcamera - Basic camera system with support for multiple camera modes
|
|
||||||
*
|
|
||||||
* CONFIGURATION:
|
|
||||||
* #define RCAMERA_IMPLEMENTATION
|
|
||||||
* Generates the implementation of the library into the included file.
|
|
||||||
* If not defined, the library is in header only mode and can be included in other headers
|
|
||||||
* or source files without problems. But only ONE file should hold the implementation.
|
|
||||||
*
|
|
||||||
* #define RCAMERA_STANDALONE
|
|
||||||
* If defined, the library can be used as standalone as a camera system but some
|
|
||||||
* functions must be redefined to manage inputs accordingly.
|
|
||||||
*
|
|
||||||
* CONTRIBUTORS:
|
|
||||||
* Ramon Santamaria: Supervision, review, update and maintenance
|
|
||||||
* Christoph Wagner: Complete redesign, using raymath (2022)
|
|
||||||
* Marc Palau: Initial implementation (2014)
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* LICENSE: zlib/libpng
|
|
||||||
*
|
|
||||||
* Copyright (c) 2022-2024 Christoph Wagner (@Crydsch) & Ramon Santamaria (@raysan5)
|
|
||||||
*
|
|
||||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
|
||||||
* will the authors be held liable for any damages arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Permission is granted to anyone to use this software for any purpose, including commercial
|
|
||||||
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
|
||||||
*
|
|
||||||
* 1. The origin of this software must not be misrepresented; you must not claim that you
|
|
||||||
* wrote the original software. If you use this software in a product, an acknowledgment
|
|
||||||
* in the product documentation would be appreciated but is not required.
|
|
||||||
*
|
|
||||||
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
|
||||||
* as being the original software.
|
|
||||||
*
|
|
||||||
* 3. This notice may not be removed or altered from any source distribution.
|
|
||||||
*
|
|
||||||
**********************************************************************************************/
|
|
||||||
|
|
||||||
#ifndef RCAMERA_H
|
|
||||||
#define RCAMERA_H
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Defines and Macros
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Function specifiers definition
|
|
||||||
|
|
||||||
// Function specifiers in case library is build/used as a shared library (Windows)
|
|
||||||
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#if defined(BUILD_LIBTYPE_SHARED)
|
|
||||||
#if defined(__TINYC__)
|
|
||||||
#define __declspec(x) __attribute__((x))
|
|
||||||
#endif
|
|
||||||
#define RLAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll)
|
|
||||||
#elif defined(USE_LIBTYPE_SHARED)
|
|
||||||
#define RLAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef RLAPI
|
|
||||||
#define RLAPI // Functions defined as 'extern' by default (implicit specifiers)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(RCAMERA_STANDALONE)
|
|
||||||
#define CAMERA_CULL_DISTANCE_NEAR 0.01
|
|
||||||
#define CAMERA_CULL_DISTANCE_FAR 1000.0
|
|
||||||
#else
|
|
||||||
#define CAMERA_CULL_DISTANCE_NEAR RL_CULL_DISTANCE_NEAR
|
|
||||||
#define CAMERA_CULL_DISTANCE_FAR RL_CULL_DISTANCE_FAR
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Types and Structures Definition
|
|
||||||
// NOTE: Below types are required for standalone usage
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
#if defined(RCAMERA_STANDALONE)
|
|
||||||
// Vector2, 2 components
|
|
||||||
typedef struct Vector2 {
|
|
||||||
float x; // Vector x component
|
|
||||||
float y; // Vector y component
|
|
||||||
} Vector2;
|
|
||||||
|
|
||||||
// Vector3, 3 components
|
|
||||||
typedef struct Vector3 {
|
|
||||||
float x; // Vector x component
|
|
||||||
float y; // Vector y component
|
|
||||||
float z; // Vector z component
|
|
||||||
} Vector3;
|
|
||||||
|
|
||||||
// Matrix, 4x4 components, column major, OpenGL style, right-handed
|
|
||||||
typedef struct Matrix {
|
|
||||||
float m0, m4, m8, m12; // Matrix first row (4 components)
|
|
||||||
float m1, m5, m9, m13; // Matrix second row (4 components)
|
|
||||||
float m2, m6, m10, m14; // Matrix third row (4 components)
|
|
||||||
float m3, m7, m11, m15; // Matrix fourth row (4 components)
|
|
||||||
} Matrix;
|
|
||||||
|
|
||||||
// Camera type, defines a camera position/orientation in 3d space
|
|
||||||
typedef struct Camera3D {
|
|
||||||
Vector3 position; // Camera position
|
|
||||||
Vector3 target; // Camera target it looks-at
|
|
||||||
Vector3 up; // Camera up vector (rotation over its axis)
|
|
||||||
float fovy; // Camera field-of-view apperture in Y (degrees) in perspective, used as near plane width in orthographic
|
|
||||||
int projection; // Camera projection type: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC
|
|
||||||
} Camera3D;
|
|
||||||
|
|
||||||
typedef Camera3D Camera; // Camera type fallback, defaults to Camera3D
|
|
||||||
|
|
||||||
// Camera projection
|
|
||||||
typedef enum {
|
|
||||||
CAMERA_PERSPECTIVE = 0, // Perspective projection
|
|
||||||
CAMERA_ORTHOGRAPHIC // Orthographic projection
|
|
||||||
} CameraProjection;
|
|
||||||
|
|
||||||
// Camera system modes
|
|
||||||
typedef enum {
|
|
||||||
CAMERA_CUSTOM = 0, // Camera custom, controlled by user (UpdateCamera() does nothing)
|
|
||||||
CAMERA_FREE, // Camera free mode
|
|
||||||
CAMERA_ORBITAL, // Camera orbital, around target, zoom supported
|
|
||||||
CAMERA_FIRST_PERSON, // Camera first person
|
|
||||||
CAMERA_THIRD_PERSON // Camera third person
|
|
||||||
} CameraMode;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Global Variables Definition
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
//...
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Module Functions Declaration
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
extern "C" { // Prevents name mangling of functions
|
|
||||||
#endif
|
|
||||||
|
|
||||||
RLAPI Vector3 GetCameraForward(Camera *camera);
|
|
||||||
RLAPI Vector3 GetCameraUp(Camera *camera);
|
|
||||||
RLAPI Vector3 GetCameraRight(Camera *camera);
|
|
||||||
|
|
||||||
// Camera movement
|
|
||||||
RLAPI void CameraMoveForward(Camera *camera, float distance, bool moveInWorldPlane);
|
|
||||||
RLAPI void CameraMoveUp(Camera *camera, float distance);
|
|
||||||
RLAPI void CameraMoveRight(Camera *camera, float distance, bool moveInWorldPlane);
|
|
||||||
RLAPI void CameraMoveToTarget(Camera *camera, float delta);
|
|
||||||
|
|
||||||
// Camera rotation
|
|
||||||
RLAPI void CameraYaw(Camera *camera, float angle, bool rotateAroundTarget);
|
|
||||||
RLAPI void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp);
|
|
||||||
RLAPI void CameraRoll(Camera *camera, float angle);
|
|
||||||
|
|
||||||
RLAPI Matrix GetCameraViewMatrix(Camera *camera);
|
|
||||||
RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // RCAMERA_H
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************************
|
|
||||||
*
|
|
||||||
* CAMERA IMPLEMENTATION
|
|
||||||
*
|
|
||||||
************************************************************************************/
|
|
||||||
|
|
||||||
#if defined(RCAMERA_IMPLEMENTATION)
|
|
||||||
|
|
||||||
#include "raymath.h" // Required for vector maths:
|
|
||||||
// Vector3Add()
|
|
||||||
// Vector3Subtract()
|
|
||||||
// Vector3Scale()
|
|
||||||
// Vector3Normalize()
|
|
||||||
// Vector3Distance()
|
|
||||||
// Vector3CrossProduct()
|
|
||||||
// Vector3RotateByAxisAngle()
|
|
||||||
// Vector3Angle()
|
|
||||||
// Vector3Negate()
|
|
||||||
// MatrixLookAt()
|
|
||||||
// MatrixPerspective()
|
|
||||||
// MatrixOrtho()
|
|
||||||
// MatrixIdentity()
|
|
||||||
|
|
||||||
// raylib required functionality:
|
|
||||||
// GetMouseDelta()
|
|
||||||
// GetMouseWheelMove()
|
|
||||||
// IsKeyDown()
|
|
||||||
// IsKeyPressed()
|
|
||||||
// GetFrameTime()
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Defines and Macros
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
#define CAMERA_MOVE_SPEED 0.09f
|
|
||||||
#define CAMERA_ROTATION_SPEED 0.03f
|
|
||||||
#define CAMERA_PAN_SPEED 0.2f
|
|
||||||
|
|
||||||
// Camera mouse movement sensitivity
|
|
||||||
#define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f // TODO: it should be independant of framerate
|
|
||||||
|
|
||||||
// Camera orbital speed in CAMERA_ORBITAL mode
|
|
||||||
#define CAMERA_ORBITAL_SPEED 0.5f // Radians per second
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Types and Structures Definition
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
//...
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Global Variables Definition
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
//...
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Module specific Functions Declaration
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
//...
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Module Functions Definition
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Returns the cameras forward vector (normalized)
|
|
||||||
Vector3 GetCameraForward(Camera *camera)
|
|
||||||
{
|
|
||||||
return Vector3Normalize(Vector3Subtract(camera->target, camera->position));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the cameras up vector (normalized)
|
|
||||||
// Note: The up vector might not be perpendicular to the forward vector
|
|
||||||
Vector3 GetCameraUp(Camera *camera)
|
|
||||||
{
|
|
||||||
return Vector3Normalize(camera->up);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the cameras right vector (normalized)
|
|
||||||
Vector3 GetCameraRight(Camera *camera)
|
|
||||||
{
|
|
||||||
Vector3 forward = GetCameraForward(camera);
|
|
||||||
Vector3 up = GetCameraUp(camera);
|
|
||||||
|
|
||||||
return Vector3Normalize(Vector3CrossProduct(forward, up));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Moves the camera in its forward direction
|
|
||||||
void CameraMoveForward(Camera *camera, float distance, bool moveInWorldPlane)
|
|
||||||
{
|
|
||||||
Vector3 forward = GetCameraForward(camera);
|
|
||||||
|
|
||||||
if (moveInWorldPlane)
|
|
||||||
{
|
|
||||||
// Project vector onto world plane
|
|
||||||
forward.y = 0;
|
|
||||||
forward = Vector3Normalize(forward);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scale by distance
|
|
||||||
forward = Vector3Scale(forward, distance);
|
|
||||||
|
|
||||||
// Move position and target
|
|
||||||
camera->position = Vector3Add(camera->position, forward);
|
|
||||||
camera->target = Vector3Add(camera->target, forward);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Moves the camera in its up direction
|
|
||||||
void CameraMoveUp(Camera *camera, float distance)
|
|
||||||
{
|
|
||||||
Vector3 up = GetCameraUp(camera);
|
|
||||||
|
|
||||||
// Scale by distance
|
|
||||||
up = Vector3Scale(up, distance);
|
|
||||||
|
|
||||||
// Move position and target
|
|
||||||
camera->position = Vector3Add(camera->position, up);
|
|
||||||
camera->target = Vector3Add(camera->target, up);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Moves the camera target in its current right direction
|
|
||||||
void CameraMoveRight(Camera *camera, float distance, bool moveInWorldPlane)
|
|
||||||
{
|
|
||||||
Vector3 right = GetCameraRight(camera);
|
|
||||||
|
|
||||||
if (moveInWorldPlane)
|
|
||||||
{
|
|
||||||
// Project vector onto world plane
|
|
||||||
right.y = 0;
|
|
||||||
right = Vector3Normalize(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scale by distance
|
|
||||||
right = Vector3Scale(right, distance);
|
|
||||||
|
|
||||||
// Move position and target
|
|
||||||
camera->position = Vector3Add(camera->position, right);
|
|
||||||
camera->target = Vector3Add(camera->target, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Moves the camera position closer/farther to/from the camera target
|
|
||||||
void CameraMoveToTarget(Camera *camera, float delta)
|
|
||||||
{
|
|
||||||
float distance = Vector3Distance(camera->position, camera->target);
|
|
||||||
|
|
||||||
// Apply delta
|
|
||||||
distance += delta;
|
|
||||||
|
|
||||||
// Distance must be greater than 0
|
|
||||||
if (distance <= 0) distance = 0.001f;
|
|
||||||
|
|
||||||
// Set new distance by moving the position along the forward vector
|
|
||||||
Vector3 forward = GetCameraForward(camera);
|
|
||||||
camera->position = Vector3Add(camera->target, Vector3Scale(forward, -distance));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rotates the camera around its up vector
|
|
||||||
// Yaw is "looking left and right"
|
|
||||||
// If rotateAroundTarget is false, the camera rotates around its position
|
|
||||||
// Note: angle must be provided in radians
|
|
||||||
void CameraYaw(Camera *camera, float angle, bool rotateAroundTarget)
|
|
||||||
{
|
|
||||||
// Rotation axis
|
|
||||||
Vector3 up = GetCameraUp(camera);
|
|
||||||
|
|
||||||
// View vector
|
|
||||||
Vector3 targetPosition = Vector3Subtract(camera->target, camera->position);
|
|
||||||
|
|
||||||
// Rotate view vector around up axis
|
|
||||||
targetPosition = Vector3RotateByAxisAngle(targetPosition, up, angle);
|
|
||||||
|
|
||||||
if (rotateAroundTarget)
|
|
||||||
{
|
|
||||||
// Move position relative to target
|
|
||||||
camera->position = Vector3Subtract(camera->target, targetPosition);
|
|
||||||
}
|
|
||||||
else // rotate around camera.position
|
|
||||||
{
|
|
||||||
// Move target relative to position
|
|
||||||
camera->target = Vector3Add(camera->position, targetPosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rotates the camera around its right vector, pitch is "looking up and down"
|
|
||||||
// - lockView prevents camera overrotation (aka "somersaults")
|
|
||||||
// - rotateAroundTarget defines if rotation is around target or around its position
|
|
||||||
// - rotateUp rotates the up direction as well (typically only usefull in CAMERA_FREE)
|
|
||||||
// NOTE: angle must be provided in radians
|
|
||||||
void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp)
|
|
||||||
{
|
|
||||||
// Up direction
|
|
||||||
Vector3 up = GetCameraUp(camera);
|
|
||||||
|
|
||||||
// View vector
|
|
||||||
Vector3 targetPosition = Vector3Subtract(camera->target, camera->position);
|
|
||||||
|
|
||||||
if (lockView)
|
|
||||||
{
|
|
||||||
// In these camera modes we clamp the Pitch angle
|
|
||||||
// to allow only viewing straight up or down.
|
|
||||||
|
|
||||||
// Clamp view up
|
|
||||||
float maxAngleUp = Vector3Angle(up, targetPosition);
|
|
||||||
maxAngleUp -= 0.001f; // avoid numerical errors
|
|
||||||
if (angle > maxAngleUp) angle = maxAngleUp;
|
|
||||||
|
|
||||||
// Clamp view down
|
|
||||||
float maxAngleDown = Vector3Angle(Vector3Negate(up), targetPosition);
|
|
||||||
maxAngleDown *= -1.0f; // downwards angle is negative
|
|
||||||
maxAngleDown += 0.001f; // avoid numerical errors
|
|
||||||
if (angle < maxAngleDown) angle = maxAngleDown;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rotation axis
|
|
||||||
Vector3 right = GetCameraRight(camera);
|
|
||||||
|
|
||||||
// Rotate view vector around right axis
|
|
||||||
targetPosition = Vector3RotateByAxisAngle(targetPosition, right, angle);
|
|
||||||
|
|
||||||
if (rotateAroundTarget)
|
|
||||||
{
|
|
||||||
// Move position relative to target
|
|
||||||
camera->position = Vector3Subtract(camera->target, targetPosition);
|
|
||||||
}
|
|
||||||
else // rotate around camera.position
|
|
||||||
{
|
|
||||||
// Move target relative to position
|
|
||||||
camera->target = Vector3Add(camera->position, targetPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rotateUp)
|
|
||||||
{
|
|
||||||
// Rotate up direction around right axis
|
|
||||||
camera->up = Vector3RotateByAxisAngle(camera->up, right, angle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rotates the camera around its forward vector
|
|
||||||
// Roll is "turning your head sideways to the left or right"
|
|
||||||
// Note: angle must be provided in radians
|
|
||||||
void CameraRoll(Camera *camera, float angle)
|
|
||||||
{
|
|
||||||
// Rotation axis
|
|
||||||
Vector3 forward = GetCameraForward(camera);
|
|
||||||
|
|
||||||
// Rotate up direction around forward axis
|
|
||||||
camera->up = Vector3RotateByAxisAngle(camera->up, forward, angle);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the camera view matrix
|
|
||||||
Matrix GetCameraViewMatrix(Camera *camera)
|
|
||||||
{
|
|
||||||
return MatrixLookAt(camera->position, camera->target, camera->up);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the camera projection matrix
|
|
||||||
Matrix GetCameraProjectionMatrix(Camera *camera, float aspect)
|
|
||||||
{
|
|
||||||
if (camera->projection == CAMERA_PERSPECTIVE)
|
|
||||||
{
|
|
||||||
return MatrixPerspective(camera->fovy*DEG2RAD, aspect, CAMERA_CULL_DISTANCE_NEAR, CAMERA_CULL_DISTANCE_FAR);
|
|
||||||
}
|
|
||||||
else if (camera->projection == CAMERA_ORTHOGRAPHIC)
|
|
||||||
{
|
|
||||||
double top = camera->fovy/2.0;
|
|
||||||
double right = top*aspect;
|
|
||||||
|
|
||||||
return MatrixOrtho(-right, right, -top, top, CAMERA_CULL_DISTANCE_NEAR, CAMERA_CULL_DISTANCE_FAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
return MatrixIdentity();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(RCAMERA_STANDALONE)
|
|
||||||
// Update camera position for selected mode
|
|
||||||
// Camera mode: CAMERA_FREE, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON, CAMERA_ORBITAL or CUSTOM
|
|
||||||
void UpdateCamera(Camera *camera, int mode)
|
|
||||||
{
|
|
||||||
Vector2 mousePositionDelta = GetMouseDelta();
|
|
||||||
|
|
||||||
bool moveInWorldPlane = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON));
|
|
||||||
bool rotateAroundTarget = ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
|
|
||||||
bool lockView = ((mode == CAMERA_FREE) || (mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
|
|
||||||
bool rotateUp = false;
|
|
||||||
|
|
||||||
if (mode == CAMERA_CUSTOM) {}
|
|
||||||
else if (mode == CAMERA_ORBITAL)
|
|
||||||
{
|
|
||||||
// Orbital can just orbit
|
|
||||||
Matrix rotation = MatrixRotate(GetCameraUp(camera), CAMERA_ORBITAL_SPEED*GetFrameTime());
|
|
||||||
Vector3 view = Vector3Subtract(camera->position, camera->target);
|
|
||||||
view = Vector3Transform(view, rotation);
|
|
||||||
camera->position = Vector3Add(camera->target, view);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Camera rotation
|
|
||||||
if (IsKeyDown(KEY_DOWN)) CameraPitch(camera, -CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp);
|
|
||||||
if (IsKeyDown(KEY_UP)) CameraPitch(camera, CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp);
|
|
||||||
if (IsKeyDown(KEY_RIGHT)) CameraYaw(camera, -CAMERA_ROTATION_SPEED, rotateAroundTarget);
|
|
||||||
if (IsKeyDown(KEY_LEFT)) CameraYaw(camera, CAMERA_ROTATION_SPEED, rotateAroundTarget);
|
|
||||||
if (IsKeyDown(KEY_Q)) CameraRoll(camera, -CAMERA_ROTATION_SPEED);
|
|
||||||
if (IsKeyDown(KEY_E)) CameraRoll(camera, CAMERA_ROTATION_SPEED);
|
|
||||||
|
|
||||||
// Camera movement
|
|
||||||
// Camera pan (for CAMERA_FREE)
|
|
||||||
if ((mode == CAMERA_FREE) && (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE)))
|
|
||||||
{
|
|
||||||
const Vector2 mouseDelta = GetMouseDelta();
|
|
||||||
if (mouseDelta.x > 0.0f) CameraMoveRight(camera, CAMERA_PAN_SPEED, moveInWorldPlane);
|
|
||||||
if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -CAMERA_PAN_SPEED, moveInWorldPlane);
|
|
||||||
if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -CAMERA_PAN_SPEED);
|
|
||||||
if (mouseDelta.y < 0.0f) CameraMoveUp(camera, CAMERA_PAN_SPEED);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Mouse support
|
|
||||||
CameraYaw(camera, -mousePositionDelta.x*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);
|
|
||||||
CameraPitch(camera, -mousePositionDelta.y*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keyboard support
|
|
||||||
if (IsKeyDown(KEY_W)) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
|
|
||||||
if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
|
|
||||||
if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
|
|
||||||
if (IsKeyDown(KEY_D)) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
|
|
||||||
|
|
||||||
// Gamepad movement
|
|
||||||
if (IsGamepadAvailable(0))
|
|
||||||
{
|
|
||||||
// Gamepad controller support
|
|
||||||
CameraYaw(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X) * 2)*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);
|
|
||||||
CameraPitch(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y) * 2)*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);
|
|
||||||
|
|
||||||
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) <= -0.25f) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
|
|
||||||
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) <= -0.25f) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
|
|
||||||
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) >= 0.25f) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
|
|
||||||
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode == CAMERA_FREE)
|
|
||||||
{
|
|
||||||
if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, CAMERA_MOVE_SPEED);
|
|
||||||
if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -CAMERA_MOVE_SPEED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL) || (mode == CAMERA_FREE))
|
|
||||||
{
|
|
||||||
// Zoom target distance
|
|
||||||
CameraMoveToTarget(camera, -GetMouseWheelMove());
|
|
||||||
if (IsKeyPressed(KEY_KP_SUBTRACT)) CameraMoveToTarget(camera, 2.0f);
|
|
||||||
if (IsKeyPressed(KEY_KP_ADD)) CameraMoveToTarget(camera, -2.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // !RCAMERA_STANDALONE
|
|
||||||
|
|
||||||
// Update camera movement, movement/rotation values should be provided by user
|
|
||||||
void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float zoom)
|
|
||||||
{
|
|
||||||
// Required values
|
|
||||||
// movement.x - Move forward/backward
|
|
||||||
// movement.y - Move right/left
|
|
||||||
// movement.z - Move up/down
|
|
||||||
// rotation.x - yaw
|
|
||||||
// rotation.y - pitch
|
|
||||||
// rotation.z - roll
|
|
||||||
// zoom - Move towards target
|
|
||||||
|
|
||||||
bool lockView = true;
|
|
||||||
bool rotateAroundTarget = false;
|
|
||||||
bool rotateUp = false;
|
|
||||||
bool moveInWorldPlane = true;
|
|
||||||
|
|
||||||
// Camera rotation
|
|
||||||
CameraPitch(camera, -rotation.y*DEG2RAD, lockView, rotateAroundTarget, rotateUp);
|
|
||||||
CameraYaw(camera, -rotation.x*DEG2RAD, rotateAroundTarget);
|
|
||||||
CameraRoll(camera, rotation.z*DEG2RAD);
|
|
||||||
|
|
||||||
// Camera movement
|
|
||||||
CameraMoveForward(camera, movement.x, moveInWorldPlane);
|
|
||||||
CameraMoveRight(camera, movement.y, moveInWorldPlane);
|
|
||||||
CameraMoveUp(camera, movement.z);
|
|
||||||
|
|
||||||
// Zoom target distance
|
|
||||||
CameraMoveToTarget(camera, zoom);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // RCAMERA_IMPLEMENTATION
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
# project-verne-server
|
||||||
|
|
||||||
|
To install dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun install
|
||||||
|
```
|
||||||
|
|
||||||
|
To run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun run index.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
This project was created using `bun init` in bun v1.1.6. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
const server = Bun.serve<{ username: string }>({
|
||||||
|
fetch(req, server) {
|
||||||
|
const url = new URL(req.url);
|
||||||
|
if (url.pathname === "/chat") {
|
||||||
|
console.log(`upgrade!`);
|
||||||
|
const username = req.text;
|
||||||
|
const success = server.upgrade(req, { data: { username } });
|
||||||
|
return success
|
||||||
|
? undefined
|
||||||
|
: new Response("WebSocket upgrade error", { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response("Hello world");
|
||||||
|
},
|
||||||
|
websocket: {
|
||||||
|
open(ws) {
|
||||||
|
const msg = `${ws.data.username} has entered the chat`;
|
||||||
|
ws.subscribe("the-group-chat");
|
||||||
|
server.publish("the-group-chat", msg);
|
||||||
|
},
|
||||||
|
message(ws, message) {
|
||||||
|
// this is a group chat
|
||||||
|
// so the server re-broadcasts incoming message to everyone
|
||||||
|
server.publish("the-group-chat", `${ws.data.username}: ${message}`);
|
||||||
|
},
|
||||||
|
close(ws) {
|
||||||
|
const msg = `${ws.data.username} has left the chat`;
|
||||||
|
ws.unsubscribe("the-group-chat");
|
||||||
|
server.publish("the-group-chat", msg);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Listening on ${server.hostname}:${server.port}`);
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"name": "project-verne-server",
|
||||||
|
"module": "index.ts",
|
||||||
|
"type": "module",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bun": "latest"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5.0.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/bash
|
||||||
|
bun run index.ts
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
// Enable latest features
|
||||||
|
"lib": ["ESNext", "DOM"],
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"allowJs": true,
|
||||||
|
|
||||||
|
// Bundler mode
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
// Best practices
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
|
||||||
|
// Some stricter flags (disabled by default)
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"noPropertyAccessFromIndexSignature": false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
emcc -lwebsocket.js -o index.html test.c
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -0,0 +1,131 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <emscripten/websocket.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
// Vector3, 3 components
|
||||||
|
typedef struct Vector3 {
|
||||||
|
float x; // Vector x component
|
||||||
|
float y; // Vector y component
|
||||||
|
float z; // Vector z component
|
||||||
|
} Vector3;
|
||||||
|
|
||||||
|
// Camera, defines position/orientation in 3d space
|
||||||
|
typedef struct Camera3D {
|
||||||
|
Vector3 position; // Camera position
|
||||||
|
Vector3 target; // Camera target it looks-at
|
||||||
|
Vector3 up; // Camera up vector (rotation over its axis)
|
||||||
|
float fovy; // Camera field-of-view aperture in Y (degrees) in perspective, used as near plane width in orthographic
|
||||||
|
int projection; // Camera projection: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC
|
||||||
|
} Camera3D;
|
||||||
|
|
||||||
|
EM_BOOL WebSocketOpen(int eventType, const EmscriptenWebSocketOpenEvent *e, void *userData) {
|
||||||
|
printf("open(eventType=%d, userData=%p)\n", eventType, userData);
|
||||||
|
|
||||||
|
Camera3D camera = {0};
|
||||||
|
camera.position = (Vector3){-9.0f, 9.0f, 4.0f};
|
||||||
|
camera.target = (Vector3){9.0f, 9.0f, 0.0f};
|
||||||
|
camera.up = (Vector3){0.0f, 1.0f, 0.0f};
|
||||||
|
camera.fovy = 60.0f;
|
||||||
|
camera.projection = 0;
|
||||||
|
|
||||||
|
emscripten_websocket_send_binary(e->socket, &camera, sizeof(camera));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
EM_BOOL WebSocketClose(int eventType, const EmscriptenWebSocketCloseEvent *e, void *userData) {
|
||||||
|
printf("close(eventType=%d, wasClean=%d, code=%d, reason=%s, userData=%p)\n", eventType, e->wasClean, e->code, e->reason, userData);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
EM_BOOL WebSocketError(int eventType, const EmscriptenWebSocketErrorEvent *e, void *userData) {
|
||||||
|
printf("error(eventType=%d, userData=%p)\n", eventType, userData);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
EM_BOOL WebSocketMessage(int eventType, const EmscriptenWebSocketMessageEvent *e, void *userData) {
|
||||||
|
printf("message(eventType=%d, userData=%p data=%p, numBytes=%d, isText=%d)\n", eventType, userData, e->data, e->numBytes, e->isText);
|
||||||
|
static int text_received = 0;
|
||||||
|
if (e->isText) {
|
||||||
|
printf("text data: \"%s\"\n", e->data);
|
||||||
|
assert(strcmp((const char*)e->data, "hello on the other side") == 0);
|
||||||
|
text_received = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Camera3D camera;
|
||||||
|
memcpy(&camera, e->data, sizeof camera);
|
||||||
|
|
||||||
|
printf("x: %f", camera.position.x);
|
||||||
|
printf(" y: %f", camera.position.y);
|
||||||
|
printf(" z: %f", camera.position.z);
|
||||||
|
printf(" fovy: %f", camera.fovy);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
emscripten_websocket_close(e->socket, 0, 0);
|
||||||
|
emscripten_websocket_delete(e->socket);
|
||||||
|
emscripten_force_exit(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
assert(emscripten_websocket_is_supported());
|
||||||
|
|
||||||
|
EmscriptenWebSocketCreateAttributes attr;
|
||||||
|
emscripten_websocket_init_create_attributes(&attr);
|
||||||
|
|
||||||
|
const char *url = "ws://localhost:8089/";
|
||||||
|
attr.url = url;
|
||||||
|
// We don't really use a special protocol on the server backend in this test,
|
||||||
|
// but check that it can be passed.
|
||||||
|
attr.protocols = "binary,base64";
|
||||||
|
|
||||||
|
EMSCRIPTEN_WEBSOCKET_T socket = emscripten_websocket_new(&attr);
|
||||||
|
assert(socket >= 0);
|
||||||
|
|
||||||
|
// URL:
|
||||||
|
int urlLength = 0;
|
||||||
|
EMSCRIPTEN_RESULT res = emscripten_websocket_get_url_length(socket, &urlLength);
|
||||||
|
assert(res == EMSCRIPTEN_RESULT_SUCCESS);
|
||||||
|
assert(urlLength == strlen(url)+1);
|
||||||
|
|
||||||
|
char *url2 = malloc(urlLength);
|
||||||
|
res = emscripten_websocket_get_url(socket, url2, urlLength);
|
||||||
|
assert(res == EMSCRIPTEN_RESULT_SUCCESS);
|
||||||
|
printf("url: %s, verified: %s, length: %d\n", url, url2, urlLength);
|
||||||
|
assert(!strcmp(url, url2));
|
||||||
|
|
||||||
|
// Protocol:
|
||||||
|
int protocolLength = 0;
|
||||||
|
res = emscripten_websocket_get_protocol_length(socket, &protocolLength);
|
||||||
|
assert(res == EMSCRIPTEN_RESULT_SUCCESS);
|
||||||
|
assert(protocolLength == 1); // Null byte
|
||||||
|
|
||||||
|
char *protocol = malloc(protocolLength);
|
||||||
|
res = emscripten_websocket_get_protocol(socket, protocol, protocolLength);
|
||||||
|
assert(res == EMSCRIPTEN_RESULT_SUCCESS);
|
||||||
|
// We don't really use a special protocol on the server backend in this test,
|
||||||
|
// but test that it comes out as an empty string at least.
|
||||||
|
assert(!strcmp(protocol, ""));
|
||||||
|
|
||||||
|
// Extensions:
|
||||||
|
int extensionsLength = 0;
|
||||||
|
res = emscripten_websocket_get_extensions_length(socket, &extensionsLength);
|
||||||
|
assert(res == EMSCRIPTEN_RESULT_SUCCESS);
|
||||||
|
assert(extensionsLength == 1); // Null byte
|
||||||
|
|
||||||
|
char *extensions = malloc(extensionsLength);
|
||||||
|
res = emscripten_websocket_get_extensions(socket, extensions, extensionsLength);
|
||||||
|
assert(res == EMSCRIPTEN_RESULT_SUCCESS);
|
||||||
|
// We don't really use any extensions on the server backend in this test, but
|
||||||
|
// test that it comes out as an empty string at least.
|
||||||
|
assert(!strcmp(extensions, ""));
|
||||||
|
|
||||||
|
emscripten_websocket_set_onopen_callback(socket, (void*)0x42, WebSocketOpen);
|
||||||
|
emscripten_websocket_set_onclose_callback(socket, (void*)0x43, WebSocketClose);
|
||||||
|
emscripten_websocket_set_onerror_callback(socket, (void*)0x44, WebSocketError);
|
||||||
|
emscripten_websocket_set_onmessage_callback(socket, (void*)0x45, WebSocketMessage);
|
||||||
|
emscripten_exit_with_live_runtime();
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
class Vector3 {
|
||||||
|
constructor(init = {}, ptr = undefined) {
|
||||||
|
this._size = 12;
|
||||||
|
this._ptr = ptr.buffer || new ArrayBuffer(this._size);
|
||||||
|
this._data = new DataView(this._ptr);
|
||||||
|
for (const i of Object.keys(init)) {
|
||||||
|
this[i] = init[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get x() {
|
||||||
|
return this._data.getFloat32(0, true);
|
||||||
|
}
|
||||||
|
get y() {
|
||||||
|
return this._data.getFloat32(4, true);
|
||||||
|
}
|
||||||
|
get z() {
|
||||||
|
return this._data.getFloat32(8, true);
|
||||||
|
}
|
||||||
|
set x(v) {
|
||||||
|
this._data.setFloat32(0, v, true);
|
||||||
|
}
|
||||||
|
set y(v) {
|
||||||
|
this._data.setFloat32(4, v, true);
|
||||||
|
}
|
||||||
|
set z(v) {
|
||||||
|
this._data.setFloat32(8, v, true);
|
||||||
|
}
|
||||||
|
get bytes() {
|
||||||
|
return new Uint8Array(this._ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Camera3D {
|
||||||
|
constructor(init = {}, ptr = undefined) {
|
||||||
|
this._size = 44;
|
||||||
|
this._ptr = ptr.buffer || new ArrayBuffer(this._size);
|
||||||
|
this._data = new DataView(this._ptr);
|
||||||
|
for (const i of Object.keys(init)) {
|
||||||
|
this[i] = init[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get position() {
|
||||||
|
return new Vector3({}, new Uint8Array(this._ptr.slice(0, 12)));
|
||||||
|
}
|
||||||
|
get target() {
|
||||||
|
return new Vector3({}, new Uint8Array(this._ptr.slice(12, 24)));
|
||||||
|
}
|
||||||
|
get up() {
|
||||||
|
return new Vector3({}, new Uint8Array(this._ptr.slice(24, 36)));
|
||||||
|
}
|
||||||
|
get fovy() {
|
||||||
|
return this._data.getFloat32(36, true);
|
||||||
|
}
|
||||||
|
get projection() {
|
||||||
|
return this._data.getInt32(40, true);
|
||||||
|
}
|
||||||
|
set position(v) {
|
||||||
|
this._data.set(v.bytes(), 0);
|
||||||
|
}
|
||||||
|
set target(v) {
|
||||||
|
this._data.set(v.bytes(), 12);
|
||||||
|
}
|
||||||
|
set up(v) {
|
||||||
|
this._data.set(v.bytes(), 24);
|
||||||
|
}
|
||||||
|
set fovy(v) {
|
||||||
|
return this._data.setFloat32(36, v, true);
|
||||||
|
}
|
||||||
|
set projection(v) {
|
||||||
|
return this._data.setInt32(40, v, true);
|
||||||
|
}
|
||||||
|
get bytes() {
|
||||||
|
return new Uint8Array(this._ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var decoder = new TextDecoder("utf-8");
|
||||||
|
var port = 8089;
|
||||||
|
var ws = require("ws");
|
||||||
|
var wss = new ws.WebSocketServer({ port: port });
|
||||||
|
console.log("WebSocket server listening on ws://localhost:" + port + "/");
|
||||||
|
wss.on("connection", function (ws) {
|
||||||
|
console.log("Client connected!");
|
||||||
|
ws.on("message", function (message, isBinary) {
|
||||||
|
if (!isBinary) {
|
||||||
|
var text = decoder.decode(new Uint8Array(message).buffer);
|
||||||
|
console.log("received TEXT: " + text.length + " characters:");
|
||||||
|
console.log(' "' + text + '"');
|
||||||
|
} else {
|
||||||
|
const camera = new Camera3D({}, new Uint8Array(message));
|
||||||
|
console.log(camera.position.x, camera.position.y, camera.position.z);
|
||||||
|
console.log(camera.target.x, camera.target.y, camera.target.z);
|
||||||
|
console.log(camera.up.x, camera.up.y, camera.up.z);
|
||||||
|
console.log(camera.fovy);
|
||||||
|
console.log(camera.projection);
|
||||||
|
console.log(camera.bytes);
|
||||||
|
|
||||||
|
ws.send(camera.bytes, { binary: true }); // Echo back the received message
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue