It was kind of a pain to fill out the mission_object_t structs so I added a matrix transformation API similar to OpenGL. However, I believe it's limited to affine transformations as we don't transform the vertices ourselves but rather define a frame for the Mount&Blade engine to transform them later. Since this frame is non-homogeneous, I think all projective transformations are lost in place_object. If someone who can math better than me would clear that up though, I'd really appreciate it.

`#include <stdio.h>`

#include <stdlib.h>

#include <math.h>

#include "scoReader.h"

#include "scoWriter.h"

#include "affine.h"

int main(int argc, char **argv)

{

if(argc < 3)

{

printf("Usage: %s input heightmap output\n", argv[0]);

return EXIT_FAILURE;

}

FILE *in = fopen(argv[1], "rb");

FILE *out = fopen(argv[2], "wb");

if(!in || !out)

{

printf("ERROR: file(s) not found\n");

return EXIT_FAILURE;

}

printf("Reading %s\n", argv[1]);

sco_file_t sco_file;

read_sco_file(in, &sco_file);

stack_t *stack = affine_init();

translate(stack, 310, 277, 33.23);

rotate(stack, -11 * M_PI / 16, 0, 0, 1);

int lcv1, lcv2;

int n;

int h;

// facade

n = 57;

h = 3;

for(lcv1 = 0; lcv1 < h; ++lcv1)

{

push_affine_matrix(stack);

for(lcv2 = 0; lcv2 < n; ++lcv2)

{

push_affine_matrix(stack);

rotate(stack, 2 * M_PI * lcv2 / n, 0, 0, 1);

translate(stack, 50, 0, 9 * lcv1);

rotate(stack, -M_PI / 2, 0, 0, 1);

place_object(&sco_file, "spr_bridge_modular_a", stack);

pop_affine_matrix(stack);

}

pop_affine_matrix(stack);

}

// walls

n = 19;

for(lcv1 = 0; lcv1 < n; ++lcv1)

{

push_affine_matrix(stack);

rotate(stack, 2 * M_PI * lcv1 / n, 0, 0, 1);

for(lcv2 = 0; lcv2 < 3; ++lcv2)

{

push_affine_matrix(stack);

translate(stack, 49 - 8 * lcv2, 0, 19 - 6.4 * lcv2);

rotate(stack, -M_PI / 2, 0, 0, 1);

rotate(stack, M_PI / 2, 1, 0, 0);

scale(stack, (49 - 8 * lcv2) / 100.0f, 0.5, 0.5);

place_object(&sco_file, "spr_arena_wall_a", stack);

pop_affine_matrix(stack);

if(lcv2 == 2)

{

push_affine_matrix(stack);

translate(stack, 32.5, 5.5, 10.77);

scale(stack, 5, 5, 4);

place_object(&sco_file, "spr_barrier_capsule", stack);

pop_affine_matrix(stack);

}

if(lcv1 == 0 && lcv2 == 2)

continue;

push_affine_matrix(stack);

translate(stack, 46 - 8 * lcv2, 0, 19 - 6.4 * lcv2);

rotate(stack, -M_PI / 2, 0, 0, 1);

scale(stack, 2, 1, 1);

place_object(&sco_file, "spr_stairs_a", stack);

pop_affine_matrix(stack);

push_affine_matrix(stack);

translate(stack, 50 - 8 * lcv2, 0, 20 - 6.4 * lcv2);

rotate(stack, -M_PI / 2, 0, 0, 1);

scale(stack, (50 - 8 * lcv2) / 100.0f, 0.5, 0.4);

place_object(&sco_file, "spr_arena_wall_a", stack);

pop_affine_matrix(stack);

}

if(lcv1 == 0)

continue;

for(lcv2 = 0; lcv2 < 2; ++lcv2)

{

push_affine_matrix(stack);

translate(stack, 34, 0, 0.8 - 6.4 * lcv2);

rotate(stack, -M_PI / 2, 0, 0, 1);

scale(stack, 0.34, 0.5, 0.4);

place_object(&sco_file, "spr_arena_wall_a", stack);

pop_affine_matrix(stack);

}

pop_affine_matrix(stack);

}

// inner ring

n = 12;

for(lcv1 = 0; lcv1 < n; ++lcv1)

{

push_affine_matrix(stack);

rotate(stack, 2 * M_PI * lcv1 / n, 0, 0, 1);

translate(stack, 24, 0, 0);

rotate(stack, -M_PI / 2, 0, 0, 1);

place_object(&sco_file, "spr_arena_barrier_b", stack);

translate(stack, 3, 0, 6.27);

place_object(&sco_file, "spr_castle_f_wall_way_a", stack);

translate(stack, -6, 0, 0);

place_object(&sco_file, "spr_castle_f_wall_way_a", stack);

pop_affine_matrix(stack);

push_affine_matrix(stack);

rotate(stack, 2 * M_PI * lcv1 / n, 0, 0, 1);

translate(stack, 29, 0, 0);

rotate(stack, -M_PI / 2, 0, 0, 1);

place_object(&sco_file, "spr_arabian_wall_b", stack);

pop_affine_matrix(stack);

}

// stairs

push_affine_matrix(stack);

translate(stack, 37.5, 5, -2);

for(lcv1 = 0; lcv1 < 5; ++lcv1)

{

push_affine_matrix(stack);

translate(stack, 0, -2.5 * lcv1, 0);

rotate(stack, M_PI, 0, 0, 1);

place_object(&sco_file, "spr_arabian_castle_stairs", stack);

pop_affine_matrix(stack);

}

pop_affine_matrix(stack);

affine_free(stack);

printf("Writing %s\n", argv[2]);

write_sco_file(out, &sco_file);

return EXIT_SUCCESS;

}

`#include <stdio.h>`

#include <stdlib.h>

#include <math.h>

#include "scoReader.h"

#include "scoWriter.h"

#include "affine.h"

int main(int argc, char **argv)

{

if(argc < 3)

{

printf("Usage: %s input heightmap output\n", argv[0]);

return EXIT_FAILURE;

}

FILE *in = fopen(argv[1], "rb");

FILE *out = fopen(argv[2], "wb");

if(!in || !out)

{

printf("ERROR: file(s) not found\n");

return EXIT_FAILURE;

}

printf("Reading %s\n", argv[1]);

sco_file_t sco_file;

read_sco_file(in, &sco_file);

stack_t *stack = affine_init();

int w = 4;

int l = 9;

int lcv1, lcv2;

translate(stack, 40, 130, 3.1);

rotate(stack, (90 - 77) * M_PI / 180, 0, 0, 1);

rotate(stack, asin(1.2 / (8 * l)), 1, 0, 0);

// width

push_affine_matrix(stack);

translate(stack, 4, 0, 0);

for(lcv1 = 0; lcv1 < w; ++lcv1)

{

for(lcv2 = 0; lcv2 < 2; ++lcv2)

{

push_affine_matrix(stack);

translate(stack, 8 * lcv1, 8 * l * lcv2, 0);

place_object(&sco_file, "spr_railing_a", stack);

pop_affine_matrix(stack);

}

}

pop_affine_matrix(stack);

// length

push_affine_matrix(stack);

translate(stack, 0, 4, 0);

for(lcv1 = 0; lcv1 < l; ++lcv1)

{

for(lcv2 = 0; lcv2 < 2; ++lcv2)

{

push_affine_matrix(stack);

translate(stack, 8 * w * lcv2, 8 * lcv1, 0);

rotate(stack, M_PI / 2, 0, 0, 1);

place_object(&sco_file, "spr_railing_a", stack);

pop_affine_matrix(stack);

}

}

for(lcv1 = 0; lcv1 < w - 1; ++lcv1)

{

for(lcv2 = 0; lcv2 < l - 2; ++lcv2)

{

push_affine_matrix(stack);

translate(stack, 8 * (lcv1 + 1), 8 * (lcv2 + 1), 0);

rotate(stack, M_PI / 2, 0, 0, 1);

place_object(&sco_file, "spr_railing_a", stack);

pop_affine_matrix(stack);

}

}

pop_affine_matrix(stack);

affine_free(stack);

printf("Writing %s\n", argv[2]);

write_sco_file(out, &sco_file);

return EXIT_SUCCESS;

}