Source

papl_yaobi / src / yaobi_stub.c

Full commit
/*
  Copyright (c) 2012 Anders Lau Olsen.
  See LICENSE file for terms and conditions.
*/

#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/alloc.h>
#include <caml/custom.h>

#include <yaobi/c_yaobi.h>
#include <stdio.h>

typedef Yaobi_CollModel CollModel;

#define CollModel_val(v) (*((CollModel **) Data_custom_val(v)))

static void finalize(value model)
{
    /* This does work, but beware that GC isn't done before the program
       exits. */
    yaobi_freeCollModel(CollModel_val(model));
}

static struct custom_operations coll_model_ops = {
  "org.bergsoe.caml_yaobi",
  finalize,
  custom_compare_default,
  custom_hash_default,
  custom_serialize_default,
  custom_deserialize_default
};

value caml_yaobi_build(value triangles_value, value len_value)
{
    CAMLparam2(triangles_value, len_value);

    int num_vertices = Int_val(len_value);
    double* vertices = malloc(num_vertices * sizeof(double));
    int num_triangles = num_vertices / 9;
    int* triangles = malloc(num_vertices * sizeof(int));
    int own_data = 1;

    int i;
    for (i = 0; i < num_vertices; i++) {
        vertices[i] = Double_field(triangles_value, i);
        triangles[i] = i;
    }
    
    value model = alloc_custom(&coll_model_ops, sizeof(CollModel *), 0, 1);
    CollModel_val(model) =
        yaobi_buildCollModel(
            num_vertices, vertices,
            num_triangles, triangles,
            3,
            own_data);
    CAMLreturn(model);
}

void read_transform(
    value t_value,
    double t[3][4])
{
    int i;
    int j;
    int p = 0;

    for (i = 0; i < 3; i++) {
        for (j = 0; j < 4; j++)
            t[i][j] = Double_field(t_value, p++);
    }
}

value caml_yaobi_in_collision(
    value ta_value, value ma_value,
    value tb_value, value mb_value)
{
    CAMLparam4(ta_value, ma_value, tb_value, mb_value);

    double ta[3][4];
    double tb[3][4];
    read_transform(ta_value, ta);
    read_transform(tb_value, tb);

    Yaobi_CollModel* ma = CollModel_val(ma_value);
    Yaobi_CollModel* mb = CollModel_val(mb_value);

    CAMLreturn(Val_bool(yaobi_isColliding(ta, ma, tb, mb)));
}