⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpeg4_animators.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005 *					All rights reserved * *  This file is part of GPAC / Scene Graph sub-project * *  GPAC is free software; you can redistribute it and/or modify *  it under the terms of the GNU Lesser General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. *    *  GPAC is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU Lesser General Public License for more details. *    *  You should have received a copy of the GNU Lesser General Public *  License along with this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  * */#include <gpac/internal/scenegraph_dev.h>/*MPEG4 tags (for internal nodes)*/#include <gpac/nodes_mpeg4.h>/*from interpolators.c*/Fixed GetInterpolateFraction(Fixed key1, Fixed key2, Fixed fraction);Fixed Interpolate(Fixed keyValue1, Fixed keyValue2, Fixed fraction);enum{	ANIM_LINE,	ANIM_QUADRATIC,	ANIM_CUBIC,	ANIM_NURBS,	/*NOT SUPPORTED*/	ANIM_SPLINE};enum{	ANIM_DEFAULT,	ANIM_DISCRETE,	ANIM_LINEAR,	/*NOT SUPPORTED ON SPLINES*/	ANIM_PACED,	ANIM_VELOCITY};/* Bisection algorithm to find u=a*t^3+b*t^2+c*t+d */Fixed do_bisection(Fixed t, SFVec2f a, SFVec2f b, SFVec2f c, SFVec2f d){	Fixed left, right, usearch, tsearch, limit;	left = 0;	right = FIX_ONE;	limit = FIX_ONE/1000;	do {		usearch = (left+right)/2;		tsearch = gf_mulfix(usearch, c.x + gf_mulfix(usearch, b.x + gf_mulfix(usearch, a.x))) + d.x;		if (t < tsearch + limit) right = usearch;		else left = usearch;	} while ((t > tsearch + limit) || (t<tsearch - limit));	return gf_mulfix(usearch, c.y + gf_mulfix(usearch, b.y + gf_mulfix(usearch , a.y))) + d.y;}typedef struct{	Fixed *knots, *weights, *n, *left, *right;	u32 nknots, nweights, npoints;	u32 p;	u32 type;	Bool valid;} anim_nurbs;static Fixed cubic_knots[] = {0,0,0,0,FIX_ONE,FIX_ONE,FIX_ONE,FIX_ONE};static Fixed quadratic_knots[] = {0,0,0,FIX_ONE,FIX_ONE,FIX_ONE};static void anurbs_reset(anim_nurbs *nurbs){	if (nurbs->n) free(nurbs->n);	if (nurbs->left) free(nurbs->left);	if (nurbs->right) free(nurbs->right);	nurbs->n = nurbs->left = nurbs->right = NULL;}static void anurbs_init(anim_nurbs *nurbs, u32 type, u32 nCtrl, u32 nKnots, Fixed *knots, u32 nWeight, Fixed *weights){	memset(nurbs, 0, sizeof(anim_nurbs));	nurbs->type = type;	switch (type) {	case ANIM_CUBIC:		nurbs->npoints = 4;		nurbs->nknots = 8;		nurbs->knots = cubic_knots;		break;	case ANIM_QUADRATIC:		nurbs->npoints = 3;		nurbs->nknots = 6;		nurbs->knots = quadratic_knots;		break;	default:		nurbs->npoints = nCtrl;		nurbs->knots = knots;		nurbs->nknots = nKnots;		nurbs->weights = weights;		nurbs->nweights = nWeight;		break;	}	nurbs->p = nurbs->nknots - nurbs->npoints - 1;	if ((nurbs->p<=0) || (nurbs->p >= nurbs->nknots -1) 		|| ((nurbs->nweights>0) && (nurbs->npoints != nurbs->nweights)) ) {		nurbs->valid = 0;	} else {		nurbs->valid = 1;	}}static void anurbs_basis(anim_nurbs *nurbs, s32 span, Fixed t){	u32 i, j;	Fixed saved, temp;	if (!nurbs->n) {		nurbs->n = (Fixed*)malloc(sizeof(Fixed) * (nurbs->p+1));		nurbs->left = (Fixed*)malloc(sizeof(Fixed) * (nurbs->p+1));		nurbs->right = (Fixed*)malloc(sizeof(Fixed) * (nurbs->p+1));	}	nurbs->n[0] = FIX_ONE;	for(i=1; i<=nurbs->p; i++) {		nurbs->left[i] = t - nurbs->knots[span+1-i];		nurbs->right[i] = nurbs->knots[span+i]-t;		saved = 0;				for(j=0; j<i; j++) {			temp = gf_divfix(nurbs->n[j], nurbs->right[j+1] + nurbs->left[i-j]);			nurbs->n[j] = saved + gf_mulfix(nurbs->right[j+1], temp);			saved = gf_mulfix(nurbs->left[i-j], temp);		}		nurbs->n[i]=saved;	}}static s32 anurbs_find_span(anim_nurbs *nurbs, Fixed u){#if 0	s32 span;	if (u == nurbs->knots[nurbs->npoints]) return nurbs->npoints - 1;	for (span = (s32) nurbs->p; span < (s32) nurbs->nknots - (s32) nurbs->p; span++) {		if (u<nurbs->knots[span]) break;	}	span--;	return span;#else	s32 low, high, mid;		if (u == nurbs->knots[nurbs->npoints]) return nurbs->npoints - 1;	low = nurbs->p; 	high = nurbs->npoints; 	mid = (low + high)/2;		while (u < nurbs->knots[mid] || u >= nurbs->knots[mid+1]) {		if (u < nurbs->knots[mid]) high = mid; 		else low = mid;		mid = (low + high)/2;	}		return (mid); #endif}static SFVec3f anurbs_get_vec3f(anim_nurbs *nurbs, s32 span, SFVec3f *pts){	SFVec3f res, tmp;	Fixed w, wi;	u32 i;	tmp.x = tmp.y = tmp.z = 0;	res = tmp;	w=0;	for(i=0; i<=nurbs->p;i++) {		tmp = pts[span - nurbs->p + i];		if (nurbs->nweights>0) {			wi = nurbs->weights[span - nurbs->p + i];			tmp = gf_vec_scale(tmp, wi);			w += gf_mulfix(nurbs->n[i], wi);		}		res.x += gf_mulfix(nurbs->n[i], tmp.x);		res.y += gf_mulfix(nurbs->n[i], tmp.y);		res.z += gf_mulfix(nurbs->n[i], tmp.z);	}	if (nurbs->nweights>0) {		if (w) {			w = gf_invfix(w);			res = gf_vec_scale(res, w);		}	}	return res;}static SFVec2f anurbs_get_vec2f(anim_nurbs *nurbs, s32 span, SFVec2f *pts){	SFVec2f res, tmp;	Fixed w, wi;	u32 i;	tmp.x = tmp.y = 0;	res = tmp;	w=0;	for(i=0; i<=nurbs->p;i++) {		tmp = pts[span - nurbs->p + i];		if (nurbs->nweights>0) {			wi = nurbs->weights[span - nurbs->p + i];			tmp.x = gf_mulfix(tmp.x, wi);			tmp.y = gf_mulfix(tmp.y, wi);			w += gf_mulfix(nurbs->n[i], wi);		}		res.x += gf_mulfix(nurbs->n[i], tmp.x);		res.y += gf_mulfix(nurbs->n[i], tmp.y);	}	if (nurbs->nweights>0) {		if (w) {			w = gf_invfix(w);			res.x = gf_mulfix(res.x, w);			res.y = gf_mulfix(res.y, w);		}	}	return res;}static Fixed anurbs_get_float(anim_nurbs *nurbs, s32 span, Fixed *vals){	Fixed res, tmp;	Fixed w, wi;	u32 i;	res = tmp = 0;	w=0;	for(i=0; i<=nurbs->p;i++) {		tmp = vals[span - nurbs->p + i];		if (nurbs->nweights>0) {			wi = nurbs->weights[span - nurbs->p + i];			tmp = gf_mulfix(tmp, wi);			w += gf_mulfix(nurbs->n[i], wi);		}		res += gf_mulfix(nurbs->n[i], tmp);	}	if (nurbs->nweights>0) res = gf_divfix(res, w);	return res;}typedef struct{	Bool is_dirty;	u32 anim_type;	/*for paced anim*/	Fixed length;	/*for spline anim*/	SFVec2f a, b, c, d;	/*nurbs path*/	anim_nurbs anurbs;} AnimatorStack;static void Anim_Destroy(GF_Node *node, void *rs, Bool is_destroy){	if (is_destroy) {		AnimatorStack *stack = (AnimatorStack *)gf_node_get_private(node);		anurbs_reset(&stack->anurbs);		free(stack);	}}static void Animator_Update(AnimatorStack *stack, u32 keyValueType, u32 nCtrl, MFVec2f *keySpline, u32 nWeight, Fixed *weights){	if (stack->anim_type==ANIM_SPLINE) {		stack->a.x = (keySpline->vals[0].x - keySpline->vals[1].x)*3 + FIX_ONE;		stack->a.y = (keySpline->vals[0].y - keySpline->vals[1].y)*3 + FIX_ONE;		stack->b.x = (keySpline->vals[1].x - 2*keySpline->vals[0].x)*3;		stack->b.y = (keySpline->vals[1].y - 2*keySpline->vals[0].y)*3;		stack->c.x = keySpline->vals[0].x*3;		stack->c.y = keySpline->vals[0].y*3;		stack->d.x = stack->d.y = 0;	}	anurbs_reset(&stack->anurbs);	switch (keyValueType) {	case ANIM_CUBIC:		anurbs_init(&stack->anurbs, ANIM_CUBIC, 0, 0, NULL, 0, NULL);		break;	case ANIM_QUADRATIC:		anurbs_init(&stack->anurbs, ANIM_QUADRATIC, 0, 0, NULL, 0, NULL);		break;	case ANIM_NURBS:		anurbs_init(&stack->anurbs, ANIM_NURBS, nCtrl, keySpline->count, (Fixed *) &keySpline->vals[0].x, nWeight, weights);		break;	}}static Bool anim_check_frac(Fixed frac, SFVec2f *fromTo){	if (frac<0) return 0;	if (frac>FIX_ONE) return 0;	if (fromTo->x > fromTo->y) return 0;	/*not active*/	if (frac<fromTo->x) return 0;	if (frac>fromTo->y) return 0;	return 1;}static void PA_Update(M_PositionAnimator *pa, AnimatorStack *stack){	u32 i;	GF_Vec d;	stack->is_dirty = 0;	stack->anim_type = pa->keyType;	/*if empty key and default anim switch to linear*/	if (!pa->key.count && !stack->anim_type) stack->anim_type = ANIM_LINEAR;	if (stack->anim_type == ANIM_PACED) {		stack->length = 0;		for (i=0; i<pa->keyValue.count-1; i++) {			d.x = pa->keyValue.vals[i+1].x - pa->keyValue.vals[i].x;			d.y = pa->keyValue.vals[i+1].y - pa->keyValue.vals[i].y;			d.z = pa->keyValue.vals[i+1].z - pa->keyValue.vals[i].z;			stack->length += gf_vec_len(d);		}	} 	Animator_Update(stack, pa->keyValueType, pa->keyValue.count, &pa->keySpline, pa->weight.count, pa->weight.vals);}static void PA_SetFraction(GF_Node *node){	Fixed frac;	u32 nbKeys, nbVals, i;	GF_Vec d;	Fixed len, dlen, dist;	M_PositionAnimator *pa = (M_PositionAnimator *)node;	AnimatorStack *stack = (AnimatorStack *)gf_node_get_private(node);	frac = pa->set_fraction;	if (!anim_check_frac(frac, &pa->fromTo)) return;	if (stack->is_dirty) PA_Update(pa, stack);	nbKeys = pa->key.count;	nbVals = pa->keyValue.count;	i=0;	switch (pa->keyValueType) {	/*linear interpolate*/	case ANIM_LINE:		/*compute frac and segment start index*/		switch (stack->anim_type) {		case ANIM_DEFAULT:			if (nbKeys != nbVals) return;			if (frac<pa->key.vals[0]) { i=0; frac = 0; }			else if (frac>pa->key.vals[nbKeys-1]) { i=nbVals-2; frac = FIX_ONE; }			else {				for (i=0; i<nbKeys-1; i++) {					if ((frac>=pa->key.vals[i]) && (frac<pa->key.vals[i+1])) break;				}				frac = GetInterpolateFraction(pa->key.vals[i], pa->key.vals[i+1], frac);			}			break;		case ANIM_DISCRETE:			i = FIX2INT(gf_floor(frac*nbVals));			frac = 0;			break;		case ANIM_LINEAR:			i = FIX2INT(gf_floor(frac*(nbVals-1)));			frac = (frac - INT2FIX(i) / (nbVals-1) ) * (nbVals-1);			break;		case ANIM_PACED:			/*at cst speed, this is the length done*/			dist = gf_mulfix(frac, stack->length);			/*then figure out in which seg we are*/			len = 0;			dlen = 0;			for (i=0; i<nbVals-1; i++) {				d.x = pa->keyValue.vals[i+1].x - pa->keyValue.vals[i].x;				d.y = pa->keyValue.vals[i+1].y - pa->keyValue.vals[i].y;				d.z = pa->keyValue.vals[i+1].z - pa->keyValue.vals[i].z;				dlen = gf_vec_len(d);				if (len+dlen>dist) break;				len += dlen;			}			/*that's our fraction inside the seg*/			frac = gf_divfix(dist-len, dlen);			break;		case ANIM_SPLINE:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -