Math-3Space

 view release on metacpan or  search on metacpan

3Space.xs  view on Meta::CPAN

	m3s_space_t *space
	SV *x_or_vec
	SV *y
	SV *z
	ALIAS:
		Math::3Space::yv = 1
		Math::3Space::zv = 2
		Math::3Space::origin = 3
	INIT:
		NV *vec= space->mat + ix * 3;
	PPCODE:
		if (x_or_vec) {
			M3S_VECLOAD(vec,x_or_vec,y,z,0);
			if (ix < 3) space->is_normal= -1;
			// leave $self on stack as return value
		} else {
			ST(0)= sv_2mortal(m3s_wrap_vector(vec));
		}
		XSRETURN(1);

bool

3Space.xs  view on Meta::CPAN

		RETVAL= m3s_get_magic_space(space, OR_DIE)->n_parents;
	OUTPUT:
		RETVAL

void
reparent(space, parent)
	SV *space
	SV *parent
	INIT:
		m3s_space_t *sp3= m3s_get_magic_space(space, OR_DIE), *psp3=NULL, *cur;
	PPCODE:
		m3s_space_recache_parent(space);
		if (SvOK(parent)) {
			psp3= m3s_get_magic_space(parent, OR_DIE);
			m3s_space_recache_parent(parent);
			// Make sure this doesn't create a cycle
			for (cur= psp3; cur; cur= cur->parent)
				if (cur == sp3)
					croak("Attempt to create a cycle: new 'parent' is a child of this space");
		}
		m3s_space_reparent(sp3, psp3);

3Space.xs  view on Meta::CPAN

	m3s_space_t *space
	SV *x_or_vec
	SV *y
	SV *z
	ALIAS:
		Math::3Space::tr = 0
		Math::3Space::travel = 1
		Math::3Space::go = 1
	INIT:
		NV vec[3], *matp;
	PPCODE:
		M3S_VECLOAD(vec,x_or_vec,y,z,0);
		if (ix) {
			matp= space->mat;
			matp[9] += vec[0] * matp[0] + vec[1] * matp[3] + vec[2] * matp[6];
			++matp;
			matp[9] += vec[0] * matp[0] + vec[1] * matp[3] + vec[2] * matp[6];
			++matp;
			matp[9] += vec[0] * matp[0] + vec[1] * matp[3] + vec[2] * matp[6];
		} else {
			matp= SPACE_ORIGIN(space);

3Space.xs  view on Meta::CPAN

scale(space, xscale_or_vec, yscale=NULL, zscale=NULL)
	m3s_space_t *space
	SV *xscale_or_vec
	SV *yscale
	SV *zscale
	ALIAS:
		Math::3Space::set_scale = 1
	INIT:
		NV vec[3], s, m, *matp= SPACE_XV(space);
		size_t i;
	PPCODE:
		if (SvROK(xscale_or_vec) && yscale == NULL) {
			m3s_read_vector_from_sv(vec, xscale_or_vec, NULL, NULL);
		} else {
			vec[0]= SvNV(xscale_or_vec);
			vec[1]= yscale? SvNV(yscale) : vec[0];
			vec[2]= zscale? SvNV(zscale) : vec[0];
		}
		for (i= 0; i < 3; i++) {
			s= vec[i];
			if (ix == 1) {

3Space.xs  view on Meta::CPAN

rotate(space, angle, x_or_vec, y=NULL, z=NULL)
	m3s_space_t *space
	NV angle
	SV *x_or_vec
	SV *y
	SV *z
	INIT:
		m3s_vector_t vec;
	ALIAS:
		Math::3Space::rot = 0
	PPCODE:
		if (y) {
			if (!z) croak("Missing z coordinate in space->rotate(angle, x, y, z)");
			vec[0]= SvNV(x_or_vec);
			vec[1]= SvNV(y);
			vec[2]= SvNV(z);
		} else {
			m3s_read_vector_from_sv(vec, x_or_vec, NULL, NULL);
		}
		m3s_space_rotate(space, sin(angle * 2 * M_PI), cos(angle * 2 * M_PI), vec);
		// return $self

3Space.xs  view on Meta::CPAN

	ALIAS:
		Math::3Space::rot_y = 1
		Math::3Space::rot_z = 2
		Math::3Space::rot_xv = 3
		Math::3Space::rot_yv = 4
		Math::3Space::rot_zv = 5
	INIT:
		NV *matp, tmp1, tmp2;
		size_t ofs1, ofs2;
		NV s= sin(angle * 2 * M_PI), c= cos(angle * 2 * M_PI);
	PPCODE:
		if (ix < 3) // Rotate around axis of parent
			m2s_space_parent_axis_rotate(space, s, c, ix);
		else
			m3s_space_self_axis_rotate(space, s, c, ix - 3);
		XSRETURN(1);

void
project_vector(space, ...)
	m3s_space_t *space
	INIT:
		m3s_vector_t vec;
		int i, vectype, count;
		AV *vec_av;
		HV *vec_hv;
		SV *pdl_origin= NULL, *pdl_matrix= NULL;
		size_t pdl_dims[3];
	ALIAS:
		Math::3Space::project = 1
		Math::3Space::unproject_vector = 2
		Math::3Space::unproject = 3
	PPCODE:
		for (i= 1; i < items; i++) {
			vectype= m3s_read_vector_from_sv(vec, ST(i), pdl_dims, NULL);
			if (vectype == M3S_VECTYPE_PDLMULTI) {
				dSP;
				if (!pdl_origin) {
					pdl_origin= sv_2mortal(m3s_pdl_vector(SPACE_ORIGIN(space), 3));
					pdl_matrix= sv_2mortal(m3s_pdl_matrix(SPACE_XV(space), !(ix&2) /*transpose bool*/));
				}
				ENTER;
				SAVETMPS;

3Space.xs  view on Meta::CPAN

		size_t i, j, n;
		int vectype;
		AV *vec_av;
		SV **item, *x, *y, *z, *pdl_origin= NULL, *pdl_matrix= NULL;
		size_t pdl_dims[3];
		SV *component_sv[3];
	ALIAS:
		Math::3Space::project_inplace = 1
		Math::3Space::unproject_vector_inplace = 2
		Math::3Space::unproject_inplace = 3
	PPCODE:
		for (i= 1; i < items; i++) {
			if (!SvROK(ST(i)))
				croak("Expected vector at $_[%d]", (int)(i-1));
			vectype= m3s_read_vector_from_sv(vec, ST(i), pdl_dims, component_sv);
			switch (vectype) {
			case M3S_VECTYPE_VECOBJ:
				vecp= m3s_vector_get_array(ST(i));
				switch (ix) {
				case 0: m3s_space_project_vector(space, vecp); break;
				case 1: m3s_space_project_point(space, vecp); break;

3Space.xs  view on Meta::CPAN

		// return $self
		XSRETURN(1);

void
get_gl_matrix(space, buffer=NULL)
	m3s_space_t *space
	SV *buffer
	INIT:
		NV *src;
		double *dst;
	PPCODE:
		if (buffer) {
			dst= (double*) m3s_make_aligned_buffer(buffer, sizeof(double)*16);
			src= space->mat;
			dst[ 0] = src[ 0]; dst[ 1] = src[ 1]; dst[ 2] = src[ 2]; dst[ 3] = 0;
			dst[ 4] = src[ 3]; dst[ 5] = src[ 4]; dst[ 6] = src[ 5]; dst[ 7] = 0;
			dst[ 8] = src[ 6]; dst[ 9] = src[ 7]; dst[10] = src[ 8]; dst[11] = 0;
			dst[12] = src[ 9]; dst[13] = src[10]; dst[14] = src[11]; dst[15] = 1;
			XSRETURN(0);
		} else {
			EXTEND(SP, 16);

3Space.xs  view on Meta::CPAN

matrix_colmajor(proj, space=NULL)
	m3s_4space_projection_t *proj
	m3s_space_t *space
	ALIAS:
		get_gl_matrix      = 0
		matrix_pack_float  = 1
		matrix_pack_double = 2
	INIT:
		double dst[16];
		struct m3s_4space_frustum_projection *f= &proj->frustum;
	PPCODE:
		if (!space) { /* user just wants the matrix itself */
			dst[ 0]= f->m00; dst[ 4]= 0;      dst[ 8]= f->m20;  dst[12]= 0;
			dst[ 1]= 0;      dst[ 5]= f->m11; dst[ 9]= f->m21;  dst[13]= 0;
			dst[ 2]= 0;      dst[ 6]= 0;      dst[10]= f->m22;  dst[14]= f->m32;
			dst[ 3]= 0;      dst[ 7]= 0;      dst[11]= -1;      dst[15]= 0;
		}
		else if (proj->frustum.centered) { /* centered frustum, optimize by assuming m20 and m21 are zero */
			dst[ 0]= f->m00 * SPACE_XV(space)[0];
			dst[ 1]= f->m11 * SPACE_XV(space)[1];
			dst[ 2]= f->m22 * SPACE_XV(space)[2];

3Space.xs  view on Meta::CPAN

	OUTPUT:
		RETVAL

void
x(vec, newval=NULL)
	m3s_vector_p vec
	SV *newval
	ALIAS:
		Math::3Space::Vector::y = 1
		Math::3Space::Vector::z = 2
	PPCODE:
		if (newval) {
			vec[ix]= SvNV(newval);
		} else {
			ST(0)= sv_2mortal(newSVnv(vec[ix]));
		}
		XSRETURN(1);

void
xyz(vec)
	m3s_vector_p vec
	PPCODE:
		EXTEND(SP, 3);
		PUSHs(sv_2mortal(newSVnv(vec[0])));
		PUSHs(sv_2mortal(newSVnv(vec[1])));
		PUSHs(sv_2mortal(newSVnv(vec[2])));

void
magnitude(vec, scale=NULL)
	m3s_vector_p vec
	SV *scale
	INIT:
		NV s, m= sqrt(m3s_vector_dotprod(vec,vec));
	PPCODE:
		if (scale) {
			if (m > 0) {
				s= SvNV(scale) / m;
				vec[0] *= s;
				vec[1] *= s;
				vec[2] *= s;
			} else
				warn("can't scale magnitude=0 vector");
			// return $self
		} else {

3Space.xs  view on Meta::CPAN

set(vec1, vec2_or_x, y=NULL, z=NULL)
	m3s_vector_p vec1
	SV *vec2_or_x
	SV *y
	SV *z
	ALIAS:
		Math::3Space::Vector::add = 1
		Math::3Space::Vector::sub = 2
	INIT:
		NV vec2[3];
	PPCODE:
		M3S_VECLOAD(vec2,vec2_or_x,y,z,0);
		if (ix == 0) {
			vec1[0]= vec2[0];
			vec1[1]= vec2[1];
			vec1[2]= vec2[2];
		} else if (ix == 1) {
			vec1[0]+= vec2[0];
			vec1[1]+= vec2[1];
			vec1[2]+= vec2[2];
		} else {

3Space.xs  view on Meta::CPAN

		XSRETURN(1);

void
scale(vec1, vec2_or_x, y=NULL, z=NULL)
	m3s_vector_p vec1
	SV *vec2_or_x
	SV *y
	SV *z
	INIT:
		NV vec2[3];
	PPCODE:
		// single value should be treated as ($x,$x,$x) instead of ($x,0,0)
		if (looks_like_number(vec2_or_x)) {
			vec2[0]= SvNV(vec2_or_x);
			vec2[1]= y? SvNV(y) : vec2[0];
			vec2[2]= z? SvNV(z) : y? 1 : vec2[0];
		}
		else {
			m3s_read_vector_from_sv(vec2, vec2_or_x, NULL, NULL);
		}
		vec1[0]*= vec2[0];

3Space.xs  view on Meta::CPAN

		RETVAL

void
cross(vec1, vec2_or_x, vec3_or_y=NULL, z=NULL)
	m3s_vector_p vec1
	SV *vec2_or_x
	SV *vec3_or_y
	SV *z
	INIT:
		m3s_vector_t vec2, vec3;
	PPCODE:
		if (!vec3_or_y) { // RET = vec1->cross(vec2)
			m3s_read_vector_from_sv(vec2, vec2_or_x, NULL, NULL);
			m3s_vector_cross(vec3, vec1, vec2);
			ST(0)= sv_2mortal(m3s_wrap_vector(vec3));
		} else if (z || !SvROK(vec2_or_x) || looks_like_number(vec2_or_x)) { // RET = vec1->cross(x,y,z)
			vec2[0]= SvNV(vec2_or_x);
			vec2[1]= SvNV(vec3_or_y);
			vec2[2]= z? SvNV(z) : 0;
			m3s_vector_cross(vec3, vec1, vec2);
			ST(0)= sv_2mortal(m3s_wrap_vector(vec3));



( run in 0.804 second using v1.01-cache-2.11-cpan-5511b514fd6 )