summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2020-02-22 23:33:06 +0800
committerchai <chaifix@163.com>2020-02-22 23:33:06 +0800
commitb656c9415a8e7e3b5b7d8bf1f3c8a5444f830c79 (patch)
treef4f0578d58e5f12b00d2753efef83aaedc03137e
parent9c89460e136ed6c6c43704d9a3a15105e0f006b0 (diff)
*misc
-rw-r--r--src/example/03_texture/03_texture.c77
-rw-r--r--src/extend/camera.c55
-rw-r--r--src/extend/camera.h35
-rw-r--r--src/extend/transform.c37
-rw-r--r--src/extend/transform.h15
-rw-r--r--src/extern/wog.c81
-rw-r--r--src/main.c28
-rw-r--r--src/math/math.h4
-rw-r--r--src/math/quat.c8
-rw-r--r--src/math/vec3.c12
10 files changed, 252 insertions, 100 deletions
diff --git a/src/example/03_texture/03_texture.c b/src/example/03_texture/03_texture.c
index f10c41a..352ea9c 100644
--- a/src/example/03_texture/03_texture.c
+++ b/src/example/03_texture/03_texture.c
@@ -41,9 +41,9 @@ static Texture* cyborg_albedo;
static Mesh* cyborg_mesh;
void onload_texture(void* data) {
- ssr_matrixmode(MATRIX_PROJECTION);
- ssr_loadidentity();
- ssr_perspective(90, ssr_getaspect(), 0.1, 10);
+ //ssr_matrixmode(MATRIX_PROJECTION);
+ //ssr_loadidentity();
+ //ssr_perspective(90, ssr_getaspect(), 0.1, 10);
//ssr_ortho(-5, 5, -4, 4, 0.1, 10);
ssr_bindvertices(verts, 8, cube, 12);
@@ -76,12 +76,12 @@ void onupdate_texture(void*data) {
uint dt = *(uint*)data;
_t += dt / 1000.f;
- ssr_matrixmode(MATRIX_VIEW);
- ssr_loadidentity();
- float distance = 2;
- Vec3 p = { distance * sin(_t), 5, distance * cos(_t) }, target = { 0, 0, 0 };
- //Vec3 p = { 0, 0, 700}, target = { 0, 0, 0 };
- ssr_lookat(&p, &target, &vec3up);
+ //ssr_matrixmode(MATRIX_VIEW);
+ //ssr_loadidentity();
+ //float distance = 2;
+ //Vec3 p = { 0, 0, 10 }, target = { 0, 0, 0 };
+ ////Vec3 p = { 0, 0, 700}, target = { 0, 0, 0 };
+ //ssr_lookat(&p, &target, &vec3up);
ssr_matrixmode(MATRIX_MODEL);
ssr_loadidentity();
@@ -103,33 +103,34 @@ void ondraw_texture(void*data) {
ssr_clearcolor(0xff202020);
ssr_cleardepth();
ssr_clearstencil(0);
-///*
-// ssr_enable(ENABLE_STENCILTEST);
-// ssr_setstencilfunc(STENCILFUNC_ALWAYS, 1, 0xff);
-// ssr_setstencilop(STENCILOP_KEEP, STENCILOP_KEEP, STENCILOP_REPLACE);
-//*/
-// /*render mech*/
-// ssr_setuniformtex(0, mech_albedo);
-// ssr_setuniformtex(1, mech_normal);
-// ssr_setuniformtex(2, mech_roughness);
-// ssr_setuniformtex(3, mech_metalness);
-// ssr_bindvertices(mech_mesh->vertices, mech_mesh->vert_count, mech_mesh->triangles, mech_mesh->tris_count);
-// ssr_draw(PRIMITIVE_TRIANGLE);
-///*
-// ssr_setstencilfunc(STENCILFUNC_EQUAL, 1, 0xff);
-// ssr_setstencilop(STENCILOP_KEEP, STENCILOP_KEEP, STENCILOP_KEEP);
-//*/
-// /*render yingham*/
-// ssr_setuniformtex(0, yingham_albedo);
-// ssr_bindvertices(yingham_mesh->vertices, yingham_mesh->vert_count, yingham_mesh->triangles, yingham_mesh->tris_count);
-// ssr_draw(PRIMITIVE_TRIANGLE);
-//
-// /*render ground*/
-// ssr_setuniformtex(0, ground_albedo);
-// ssr_bindvertices(ground_mesh->vertices, ground_mesh->vert_count, ground_mesh->triangles, ground_mesh->tris_count);
-// ssr_draw(PRIMITIVE_TRIANGLE);
-//
- ssr_setuniformtex(0, cyborg_albedo);
- ssr_bindvertices(cyborg_mesh->vertices, cyborg_mesh->vert_count, cyborg_mesh->triangles, cyborg_mesh->tris_count);
- ssr_draw(PRIMITIVE_TRIANGLE);
+/*
+ ssr_enable(ENABLE_STENCILTEST);
+ ssr_setstencilfunc(STENCILFUNC_ALWAYS, 1, 0xff);
+ ssr_setstencilop(STENCILOP_KEEP, STENCILOP_KEEP, STENCILOP_REPLACE);
+*/
+ /*render mech*/
+ ssr_setuniformtex(0, mech_albedo);
+ ssr_setuniformtex(1, mech_normal);
+ ssr_setuniformtex(2, mech_roughness);
+ ssr_setuniformtex(3, mech_metalness);
+ ssr_bindvertices(mech_mesh->vertices, mech_mesh->vert_count, mech_mesh->triangles, mech_mesh->tris_count);
+ ssr_draw(PRIMITIVE_TRIANGLE);
+/*
+ ssr_setstencilfunc(STENCILFUNC_EQUAL, 1, 0xff);
+ ssr_setstencilop(STENCILOP_KEEP, STENCILOP_KEEP, STENCILOP_KEEP);
+*/
+ /*render yingham*/
+ ssr_setuniformtex(0, yingham_albedo);
+ ssr_bindvertices(yingham_mesh->vertices, yingham_mesh->vert_count, yingham_mesh->triangles, yingham_mesh->tris_count);
+ ssr_draw(PRIMITIVE_TRIANGLE);
+
+ /*render ground*/
+ ssr_setuniformtex(0, ground_albedo);
+ ssr_bindvertices(ground_mesh->vertices, ground_mesh->vert_count, ground_mesh->triangles, ground_mesh->tris_count);
+ ssr_draw(PRIMITIVE_TRIANGLE);
+
+
+ //ssr_setuniformtex(0, cyborg_albedo);
+ //ssr_bindvertices(cyborg_mesh->vertices, cyborg_mesh->vert_count, cyborg_mesh->triangles, cyborg_mesh->tris_count);
+ //ssr_draw(PRIMITIVE_TRIANGLE);
}
diff --git a/src/extend/camera.c b/src/extend/camera.c
index e69de29..377a09e 100644
--- a/src/extend/camera.c
+++ b/src/extend/camera.c
@@ -0,0 +1,55 @@
+#include "camera.h"
+
+void camera_init(Camera* cam) {
+ cam->is_viewdirty = cam->is_projdirty = TRUE;
+ cam->transform.parent = NULL ;
+ cam->transform.localposition = vec3_make(0, 0, 800);
+ cam->transform.localscale = vec3_make(1, 1, 1);
+ cam->transform.localrotation = quat_make(0, 0, 0);
+ cam->near = 1;
+ cam->far = 1500;
+ cam->aspect = 600/500.f;
+ cam->fov = 90;
+ cam->zoom_speed = 20;
+}
+
+void camera_getmatrix(Camera* cam, Mat4* view, Mat4* proj) {
+ camera_getviewmatrix(cam, view);
+ camera_getprojmatrix(cam, proj);
+}
+
+void camera_getviewmatrix(Camera* cam, Mat4* out) {
+ if (!cam->is_viewdirty) {
+ if (out)*out = cam->view_matrix;
+ return;
+ }
+ transform_getinvmatrixnoscale(&cam->transform, &cam->view_matrix);
+ if(out) *out = cam->view_matrix;
+ cam->is_viewdirty = FALSE;
+}
+
+void camera_getprojmatrix(Camera* cam, Mat4* out) {
+ if (!cam->is_projdirty) {
+ if (out)*out = cam->proj_matrix;
+ return;
+ }
+ mat4_setperspective(cam->fov, cam->aspect, cam->near, cam->far, &cam->proj_matrix);
+ if(out) *out = cam->proj_matrix;
+ cam->is_projdirty = FALSE;
+}
+
+static void _onwheelscroll(Camera* cam, int wheel) {
+ Quat rot; transform_getrotation(&cam->transform, &rot);
+ Vec3 forward = {0,0,-1};
+ quat_applytovec3(&rot, &forward, &forward);
+ vec3_scale(&forward, cam->zoom_speed * wheel, &forward);
+ vec3_plus(&forward, &cam->transform.localposition, &cam->transform.localposition);
+ cam->is_viewdirty = TRUE;
+}
+
+void camera_onevent(Camera* cam, wog_Event* e) {
+ if(e == NULL) return ;
+ if (e->type == WOG_EMOUSEWHEEL) {//zoom in\zoom out
+ _onwheelscroll(cam, e->wheel);
+ }
+}
diff --git a/src/extend/camera.h b/src/extend/camera.h
index 2b7afa5..8227dbf 100644
--- a/src/extend/camera.h
+++ b/src/extend/camera.h
@@ -2,18 +2,37 @@
#define _SOFTSHADEROOM_CAMERA_H_
#include "../math/math.h"
+#include "transform.h"
+#include "../extern/wog.h"
-typedef struct Camera {
- Vec3 front;
+#undef near
+#undef far
+
+typedef struct {
+ Transform transform;
+ float fov, aspect, near, far;
+ /*matrix*/
+ Mat4 view_matrix; /*or WorldToCameraMatrix*/
+ Mat4 proj_matrix;
+ bool is_viewdirty, is_projdirty;
+ /*operations*/
+ float zoom_speed;
} Camera;
-void camera_onmousemove(float x, float y);
-void camera_onleftdown();
-void camera_onleftup();
-void camera_onrightdown();
-void camera_onrightup();
-void camera_onscroll(int amount);
+typedef struct CameraConfig {
+ float fov, aspect, near, far;
+ Vec3 pos;
+}CameraConfig;
+
+void camera_init(Camera* cam);
+
+void camera_setposition(float x, float y, float z);
+
+void camera_onevent(Camera* cam, wog_Event* e);
void camera_getmatrix(Mat4* view, Mat4* proj);
+void camera_getviewmatrix(Camera* cam, Mat4* view);
+void camera_getprojmatrix(Camera* cam, Mat4* proj);
+
#endif \ No newline at end of file
diff --git a/src/extend/transform.c b/src/extend/transform.c
index e69de29..7724614 100644
--- a/src/extend/transform.c
+++ b/src/extend/transform.c
@@ -0,0 +1,37 @@
+#include "transform.h"
+
+void transform_getpositionandrotation(Transform* trans, Vec3* pos, Quat* rot) {
+ *pos = trans->localposition;
+ *rot = trans->localrotation;
+ Transform* cur = trans->parent;
+ while (cur) {
+ /*按照srt的顺序计算pos*/
+ vec3_scale3(pos, &cur->localscale, pos);
+ quat_applytovec3(&cur->localrotation, pos, pos);
+ vec3_plus(pos, &cur->localposition, pos);
+ /*计算旋转*/
+ quat_multiply(&cur->localrotation, rot, rot);
+
+ cur = cur->parent;
+ }
+}
+
+void transform_getinvmatrixnoscale(Transform* trans, Mat4* worldToLocal) {
+ Vec3 pos; Quat rot;
+ transform_getpositionandrotation(trans, &pos, &rot);
+ quat_invert(&rot, &rot);
+ /*(TR)^-1 = R^-1T^-1*/
+ quat_tomat4(&rot, worldToLocal);
+ vec3_scale(&pos, -1, &pos);
+ mat4_translate(worldToLocal, &pos, worldToLocal);
+}
+
+void transform_getrotation(Transform* trans, Quat* rot) {
+ *rot = trans->localrotation;
+ Transform* cur = trans->parent;
+ while (cur) {
+ quat_multiply(&cur->localrotation, rot, rot);
+ }
+}
+
+
diff --git a/src/extend/transform.h b/src/extend/transform.h
index 16b7c7f..f647819 100644
--- a/src/extend/transform.h
+++ b/src/extend/transform.h
@@ -1,5 +1,7 @@
#include "../math/math.h"
+
+typedef struct Transform Transform;
/*
** Transform要注意按 scale -> rotation -> position 顺序计算
*/
@@ -13,15 +15,16 @@ typedef struct Transform {
Vec3 position;
Vec3 scale;
Quat rotation;
- bool isdirty;
} Transform;
-void transform_translate(Transform* trans, Vec4* v, Vec4* out);
-
-Vec4 transform_translate(Transform* trans, Vec4* v);
+void transform_translate(Transform* trans, Vec3* v);
-void transform_getrotation(Quat* out); /*get global rotation*/
-void transform_getposition(Vec3* out);
+void transform_getrotation(Transform* trans, Quat* out); /*get global rotation*/
+void transform_getposition(Transform* trans, Vec3* out);
void transform_getscale(Vec3* out);
+void transform_getpositionandrotation(Transform* trans, Vec3* pos, Quat* rot);
void transform_setdirty(Transform* trans);
+
+/*get world to local matrix(no scale)*/
+void transform_getinvmatrixnoscale(Transform* transform, Mat4* worldToLocal);
diff --git a/src/extern/wog.c b/src/extern/wog.c
index 7b8af8d..6cdfb6f 100644
--- a/src/extern/wog.c
+++ b/src/extern/wog.c
@@ -41,6 +41,7 @@ typedef struct wog_Window
{
HWND hwnd; // Window handler
HDC hdc; // Device Context
+ HDC mdc; // Memory Device Contexts
#if WOG_API == WOG_GDI
wog_Surface* surface; // render buffer
#endif
@@ -280,18 +281,21 @@ static int registerWindowClass()
return TRUE;
}
-static void create_surface(HWND handle, int width, int height, wog_Surface **out_surface, HDC *out_memory_dc) {
+/*
+ * for memory device context, see
+ * https://docs.microsoft.com/en-us/windows/desktop/gdi/memory-device-contexts
+ * also
+ * SDL_windowsframebuffer.c WIN_CreateWindowFramebuffer
+ */
+static void create_surface(wog_Window* wnd, int width, int height) {
BITMAPINFOHEADER bi_header;
- HDC window_dc;
HDC memory_dc;
HBITMAP dib_bitmap;
HBITMAP old_bitmap;
unsigned char *buffer; // color buffer
wog_Surface *surface;
- window_dc = GetDC(handle);
- memory_dc = CreateCompatibleDC(window_dc);
- ReleaseDC(handle, window_dc);
+ memory_dc = CreateCompatibleDC(wnd->hdc); /*memory device contexts*/
memset(&bi_header, 0, sizeof(BITMAPINFOHEADER));
bi_header.biSize = sizeof(BITMAPINFOHEADER);
@@ -300,8 +304,8 @@ static void create_surface(HWND handle, int width, int height, wog_Surface **out
bi_header.biPlanes = 1;
bi_header.biBitCount = 32;
bi_header.biCompression = BI_RGB;
- dib_bitmap = CreateDIBSection(memory_dc, (BITMAPINFO*)&bi_header,
- DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
+ /*create bitmap*/
+ dib_bitmap = CreateDIBSection(memory_dc, (BITMAPINFO*)&bi_header, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
assert(dib_bitmap != NULL);
old_bitmap = (HBITMAP)SelectObject(memory_dc, dib_bitmap);
DeleteObject(old_bitmap);
@@ -312,8 +316,8 @@ static void create_surface(HWND handle, int width, int height, wog_Surface **out
surface->channels = 4;
surface->buffer = buffer;
- *out_surface = surface;
- *out_memory_dc = memory_dc;
+ wnd->surface = surface;
+ wnd->mdc = memory_dc;
}
@@ -342,30 +346,6 @@ wog_Window* wog_createWindow(const char* title, int width, int height, int x, in
if (hasbit(flags, WOG_DISABLE)) windowStyle |= WS_DISABLED;
DWORD windowExtendedStyle = WS_EX_APPWINDOW; // Define The Window's Extended Style
-
- PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be
- {
- sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
- 1, // Version Number
- PFD_DRAW_TO_WINDOW | // Format Must Support Window
-#if WOG_API == WOG_GL
- PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
-#endif
- PFD_DOUBLEBUFFER, // Must Support Double Buffering
- PFD_TYPE_RGBA, // Request An RGBA Format
- 32, // Select Our Color Depth
- 0, 0, 0, 0, 0, 0, // Color Bits Ignored
- 0, // No Alpha Buffer
- 0, // Shift Bit Ignored
- 0, // No Accumulation Buffer
- 0, 0, 0, 0, // Accumulation Bits Ignored
- 16, // 16Bit Z-Buffer (Depth Buffer)
- 0, // No Stencil Buffer
- 0, // No Auxiliary Buffer
- PFD_MAIN_PLANE, // Main Drawing Layer
- 0, // Reserved
- 0, 0, 0 // Layer Masks Ignored
- };
RECT windowRect = { 0, 0, width, height };
AdjustWindowRectEx(&windowRect, windowStyle, 0, windowExtendedStyle);
width = windowRect.right - windowRect.left;
@@ -379,7 +359,7 @@ wog_Window* wog_createWindow(const char* title, int width, int height, int x, in
width, height,
HWND_DESKTOP,
0,
- GetModuleHandle(0),
+ GetModuleHandle(NULL),
wnd
);
@@ -398,10 +378,31 @@ wog_Window* wog_createWindow(const char* title, int width, int height, int x, in
}
#if WOG_API == WOG_GDI
- create_surface(wnd->hwnd, client_w, client_h, &wnd->surface, &wnd->hdc);
+ create_surface(wnd, client_w, client_h);
#endif
#if WOG_API == WOG_GL
+ PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
+ 1, // Version Number
+ PFD_DRAW_TO_WINDOW | // Format Must Support Window
+ PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
+ PFD_DOUBLEBUFFER, // Must Support Double Buffering
+ PFD_TYPE_RGBA, // Request An RGBA Format
+ 32, // Select Our Color Depth
+ 0, 0, 0, 0, 0, 0, // Color Bits Ignored
+ 0, // No Alpha Buffer
+ 0, // Shift Bit Ignored
+ 0, // No Accumulation Buffer
+ 0, 0, 0, 0, // Accumulation Bits Ignored
+ 16, // 16Bit Z-Buffer (Depth Buffer)
+ 0, // No Stencil Buffer
+ 0, // No Auxiliary Buffer
+ PFD_MAIN_PLANE, // Main Drawing Layer
+ 0, // Reserved
+ 0, 0, 0 // Layer Masks Ignored
+ };
// set pixel format
unsigned int pixelformat;
pixelformat = ChoosePixelFormat(wnd->hdc, &pfd);
@@ -465,13 +466,9 @@ void wog_destroyGLContext(wog_GLContext* cxt)
#endif
void wog_updateSurface(wog_Window* wnd) {
- HDC window_dc = GetDC(wnd->hwnd);
- HDC memory_dc = wnd->hdc;
- wog_Surface *surface = wnd->surface;
- int width = surface->width;
- int height = surface->height;
- BitBlt(window_dc, 0, 0, width, height, memory_dc, 0, 0, SRCCOPY);
- ReleaseDC(wnd->hwnd, window_dc);
+ if(wnd->surface == NULL) return ;
+ int width = wnd->surface->width, height = wnd->surface->height;
+ BitBlt(wnd->hdc, 0, 0, wnd->surface, height, wnd->mdc, 0, 0, SRCCOPY);
}
void wog_destroyWindow(wog_Window* wnd)
diff --git a/src/main.c b/src/main.c
index 58615d1..404b2d1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -5,9 +5,10 @@
#include "ssr.h"
#include "example/example.h"
#include "extern/wog.h"
+#include "extend/camera.h"
#define SCREEN_WIDTH 600
-#define SCREEN_HEIGHT 480
+#define SCREEN_HEIGHT 500
typedef void(*F)(void*);
F onload;
@@ -27,7 +28,7 @@ SETEXAMPLEF(onevent, i)\
SETEXAMPLEF(onupdate, i)
int main(int argc, char* argv[]) {
- wog_Window* wnd = wog_createWindow("test", SCREEN_WIDTH, SCREEN_HEIGHT, 500, 500, 0);
+ wog_Window* wnd = wog_createWindow("Soft Shader Room", SCREEN_WIDTH, SCREEN_HEIGHT, 500, 500, 0);
wog_show(wnd);
wog_Surface* surface = wog_getsurface(wnd); // ARGB format
/* init ssr */
@@ -38,7 +39,10 @@ int main(int argc, char* argv[]) {
};
ssr_init(&config);
SETEXAMPLE(EXAMPLECUR);
- onload(0);
+ onload(NULL);
+ /*set up global camera*/
+ Camera cam;
+ camera_init(&cam);
/* main loop */
uint prev = wog_tick();
uint dt = 0;
@@ -47,6 +51,7 @@ int main(int argc, char* argv[]) {
wog_Event e;
while (1) {
while (wog_pollEvent(wnd, &e)) {
+ camera_onevent(&cam, &e);
if (e.type == WOG_ECLOSE) {
goto quit;
} else {
@@ -65,14 +70,25 @@ int main(int argc, char* argv[]) {
}
onupdate(&dt);
- ondraw(0);
+
+ /*set vp matrix*/
+ ssr_matrixmode(MATRIX_PROJECTION);
+ camera_getprojmatrix(&cam, NULL);
+ ssr_loadmatrix(&cam.proj_matrix);
+ ssr_matrixmode(MATRIX_VIEW);
+ camera_getviewmatrix(&cam, NULL);
+ ssr_loadmatrix(&cam.view_matrix);
+ ssr_matrixmode(MATRIX_MODEL);
+
+ ondraw(NULL);
+
ssr_present();
wog_updateSurface(wnd);
- Sleep(1); /*reduce cpu using*/
+ //Sleep(1); /*reduce cpu using*/
}
quit:
wog_destroyWindow(wnd);
- return 1;
+ return 0;
}
diff --git a/src/math/math.h b/src/math/math.h
index 1c65c01..03e156e 100644
--- a/src/math/math.h
+++ b/src/math/math.h
@@ -159,9 +159,11 @@ extern Vec4 vec4zero; /*(0,0,0)*/
void vec3_tostring(Vec3* v, char buf[]);
void vec3_print(Vec3* v);
+Vec3 vec3_make(float x, float y, float z);
float vec3_intersection(Vec3* v1, Vec3* v2); /*夹角*/
void vec3_projection(Vec3* v1, Vec3* v2, Vec3* out);/*v1在v2上的投影*/
void vec3_scale(Vec3* v, float k, Vec3* out);
+void vec3_scale3(Vec3* v, Vec3* scalar, Vec3* out);
void vec3_plus(Vec3* v1, Vec3* v2, Vec3* out);
void vec3_offset(Vec3* v, float offset, Vec3* out);
void vec3_normalize(Vec3* v, Vec3* out);
@@ -260,6 +262,8 @@ void mat43_applytovec3(Mat43* m, Vec3* v, Vec4* out);
void quat_tostring(Quat* q, char str[]);
void quat_print(Quat* q);
+Quat quat_make(float rx, float ry, float rz);
+
void euler_toquat(Euler* e, Quat* out);
void euler_deg2rad(Euler* in, Euler* out);
void euler_rad2deg(Euler* in, Euler* out);
diff --git a/src/math/quat.c b/src/math/quat.c
index e68e254..4dedbed 100644
--- a/src/math/quat.c
+++ b/src/math/quat.c
@@ -69,6 +69,13 @@ void euler_rad2deg(Euler* in, Euler* out) {
out->z = degree(in->z);
}
+Quat quat_make(float rx, float ry, float rz) {
+ Quat rot;
+ Euler euler = {rx, ry, rz};
+ quat_fromeuler(&euler, &rot);
+ return rot;
+}
+
void euler_toquat(Euler* euler, Quat* out) {
ssr_assert(euler && out);
quat_fromeuler(euler, out);
@@ -230,6 +237,7 @@ void quat_minus(Quat* q1, Quat* q2, Quat* out) {
quat_multiply(q1, &q2i, out);
}
+/*q1*q2*/
void quat_multiply(Quat* q1, Quat* q2, Quat* out) {
ssr_assert(q1 && q2 && out);
diff --git a/src/math/vec3.c b/src/math/vec3.c
index d2fb652..5d273d8 100644
--- a/src/math/vec3.c
+++ b/src/math/vec3.c
@@ -16,6 +16,11 @@ void vec3_cross(Vec3* v1, Vec3* v2, Vec3* out) {
out->z = v1->x*v2->y - v1->y*v2->x;
}
+Vec3 vec3_make(float x, float y, float z) {
+ Vec3 v = {x, y, z};
+ return v;
+}
+
void vec3_scale(Vec3* v, float k, Vec3* out) {
ssr_assert(v && out);
out->x = v->x * k;
@@ -23,6 +28,13 @@ void vec3_scale(Vec3* v, float k, Vec3* out) {
out->z = v->z * k;
}
+void vec3_scale3(Vec3* v, Vec3* scalar, Vec3* out) {
+ ssr_assert(v && scalar && out);
+ out->x = v->x * scalar->x;
+ out->y = v->y * scalar->y;
+ out->z = v->z * scalar->z;
+}
+
void vec3_plus(Vec3* v1, Vec3* v2, Vec3* out) {
ssr_assert(v1 && v2 && out);
out->x = v1->x + v2->x;