/* Calls multitex and copies the result to the outputs. Called by xxx_exec, which handles inputs. */ static void do_proc(float *result, TexParams *p, float *col1, float *col2, char is_normal, Tex *tex, short thread) { TexResult texres; int textype; if(is_normal) { texres.nor = result; } else texres.nor = NULL; textype = multitex_nodes(tex, p->co, p->dxt, p->dyt, p->osatex, &texres, thread, 0, p->shi, p->mtex); if(is_normal) return; if(textype & TEX_RGB) { QUATCOPY(result, &texres.tr); } else { QUATCOPY(result, col1); ramp_blend(MA_RAMP_BLEND, result, result+1, result+2, texres.tin, col2); } }
static void do_copy_split_rgba(bNode *UNUSED(node), float *out, float *in1, float *in2, float *fac) { if(*fac==0.0f) { QUATCOPY(out, in1); } else { QUATCOPY(out, in2); } }
static void do_zcombine(bNode *node, float *out, float *src1, float *z1, float *src2, float *z2) { if(*z1 <= *z2) { QUATCOPY(out, src1); } else { QUATCOPY(out, src2); if(node->custom1) *z1= *z2; } }
static void do_filter_edge(CompBuf *out, CompBuf *in, float *filter, float fac) { float *row1, *row2, *row3; float *fp, f1, f2, mfac= 1.0f-fac; int rowlen, x, y, c, pix= in->type; rowlen= in->x; for(y=0; y<in->y; y++) { /* setup rows */ if(y==0) row1= in->rect; else row1= in->rect + pix*(y-1)*rowlen; row2= in->rect + y*pix*rowlen; if(y==in->y-1) row3= row2; else row3= row2 + pix*rowlen; fp= out->rect + pix*y*rowlen; if(pix==CB_RGBA) { QUATCOPY(fp, row2); fp+= pix; for(x=2; x<rowlen; x++) { for(c=0; c<3; c++) { f1= filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8]; f2= filter[0]*row1[0] + filter[3]*row1[4] + filter[6]*row1[8] + filter[1]*row2[0] + filter[4]*row2[4] + filter[7]*row2[8] + filter[2]*row3[0] + filter[5]*row3[4] + filter[8]*row3[8]; fp[0]= mfac*row2[4] + fac*sqrt(f1*f1 + f2*f2); fp++; row1++; row2++; row3++; } fp[0]= row2[4]; /* no alpha... will clear it completely */ fp++; row1++; row2++; row3++; } QUATCOPY(fp, row2+4); } else if(pix==CB_VAL) { fp+= pix; for(x=2; x<rowlen; x++) { f1= filter[0]*row1[0] + filter[1]*row1[1] + filter[2]*row1[2] + filter[3]*row2[0] + filter[4]*row2[1] + filter[5]*row2[2] + filter[6]*row3[0] + filter[7]*row3[1] + filter[8]*row3[2]; f2= filter[0]*row1[0] + filter[3]*row1[1] + filter[6]*row1[2] + filter[1]*row2[0] + filter[4]*row2[1] + filter[7]*row2[2] + filter[2]*row3[0] + filter[5]*row3[1] + filter[8]*row3[2]; fp[0]= mfac*row2[1] + fac*sqrt(f1*f1 + f2*f2); fp++; row1++; row2++; row3++; } } } }
static void node_composit_exec_rgb(void *UNUSED(data), bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) { bNodeSocket *sock= node->outputs.first; float *col= ((bNodeSocketValueRGBA*)sock->default_value)->value; QUATCOPY(out[0]->vec, col); }
static void do_alphaover_premul(bNode *UNUSED(node), float *out, float *src, float *over, float *fac) { if(over[3]<=0.0f) { QUATCOPY(out, src); } else if(fac[0]==1.0f && over[3]>=1.0f) { QUATCOPY(out, over); } else { float mul= 1.0f - fac[0]*over[3]; out[0]= (mul*src[0]) + fac[0]*over[0]; out[1]= (mul*src[1]) + fac[0]*over[1]; out[2]= (mul*src[2]) + fac[0]*over[2]; out[3]= (mul*src[3]) + fac[0]*over[3]; } }
/* result will be still premul, but the over part is premulled */ static void do_alphaover_mixed(bNode *node, float *out, float *src, float *over, float *fac) { if(over[3]<=0.0f) { QUATCOPY(out, src); } else if(fac[0]==1.0f && over[3]>=1.0f) { QUATCOPY(out, over); } else { NodeTwoFloats *ntf= node->storage; float addfac= 1.0f - ntf->x + over[3]*ntf->x; float premul= fac[0]*addfac; float mul= 1.0f - fac[0]*over[3]; out[0]= (mul*src[0]) + premul*over[0]; out[1]= (mul*src[1]) + premul*over[1]; out[2]= (mul*src[2]) + premul*over[2]; out[3]= (mul*src[3]) + fac[0]*over[3]; } }
static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread) { Tex *nodetex = (Tex *)node->id; static float red[] = {1,0,0,1}; static float white[] = {1,1,1,1}; float co[3], dxt[3], dyt[3]; copy_v3_v3(co, p->co); copy_v3_v3(dxt, p->dxt); copy_v3_v3(dyt, p->dyt); if(node->custom2 || node->need_exec==0) { /* this node refers to its own texture tree! */ QUATCOPY(out, (fabs(co[0] - co[1]) < .01) ? white : red ); } else if(nodetex) { TexResult texres; int textype; float nor[] = {0,0,0}; float col1[4], col2[4]; tex_input_rgba(col1, in[0], p, thread); tex_input_rgba(col2, in[1], p, thread); texres.nor = nor; textype = multitex_nodes(nodetex, co, dxt, dyt, p->osatex, &texres, thread, 0, p->shi, p->mtex); if(textype & TEX_RGB) { QUATCOPY(out, &texres.tr); } else { QUATCOPY(out, col1); ramp_blend(MA_RAMP_BLEND, out, out+1, out+2, texres.tin, col2); } } }
/* helper for poseAnim_mapping_get() -> get the relevant F-Curves per PoseChannel */ static void fcurves_to_pchan_links_get (ListBase *pfLinks, Object *ob, bAction *act, bPoseChannel *pchan) { ListBase curves = {NULL, NULL}; int transFlags = action_get_item_transforms(act, ob, pchan, &curves); pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE); /* check if any transforms found... */ if (transFlags) { /* make new linkage data */ tPChanFCurveLink *pfl= MEM_callocN(sizeof(tPChanFCurveLink), "tPChanFCurveLink"); PointerRNA ptr; pfl->fcurves= curves; pfl->pchan= pchan; /* get the RNA path to this pchan - this needs to be freed! */ RNA_pointer_create((ID *)ob, &RNA_PoseBone, pchan, &ptr); pfl->pchan_path= RNA_path_from_ID_to_struct(&ptr); /* add linkage data to operator data */ BLI_addtail(pfLinks, pfl); /* set pchan's transform flags */ if (transFlags & ACT_TRANS_LOC) pchan->flag |= POSE_LOC; if (transFlags & ACT_TRANS_ROT) pchan->flag |= POSE_ROT; if (transFlags & ACT_TRANS_SCALE) pchan->flag |= POSE_SIZE; /* store current transforms */ VECCOPY(pfl->oldloc, pchan->loc); VECCOPY(pfl->oldrot, pchan->eul); VECCOPY(pfl->oldscale, pchan->size); QUATCOPY(pfl->oldquat, pchan->quat); VECCOPY(pfl->oldaxis, pchan->rotAxis); pfl->oldangle = pchan->rotAngle; /* make copy of custom properties */ if (pchan->prop && (transFlags & ACT_TRANS_PROP)) pfl->oldprops = IDP_CopyProperty(pchan->prop); } }
static void do_invert_fac(bNode *node, float *out, float *in, float *fac) { float col[4], facm; do_invert(node, col, in); /* blend inverted result against original input with fac */ facm = 1.0 - fac[0]; if(node->custom1 & CMP_CHAN_RGB) { col[0] = fac[0]*col[0] + (facm*in[0]); col[1] = fac[0]*col[1] + (facm*in[1]); col[2] = fac[0]*col[2] + (facm*in[2]); } if(node->custom1 & CMP_CHAN_A) col[3] = fac[0]*col[3] + (facm*in[3]); QUATCOPY(out, col); }
static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNUSED(in), short UNUSED(thread)) { float x = p->co[0]; float y = p->co[1]; Image *ima= (Image *)node->id; ImageUser *iuser= (ImageUser *)node->storage; if( ima ) { ImBuf *ibuf = BKE_image_get_ibuf(ima, iuser); if( ibuf ) { float xsize, ysize; float xoff, yoff; int px, py; float *result; xsize = ibuf->x / 2; ysize = ibuf->y / 2; xoff = yoff = -1; px = (int)( (x-xoff) * xsize ); py = (int)( (y-yoff) * ysize ); if( (!xsize) || (!ysize) ) return; if( !ibuf->rect_float ) { BLI_lock_thread(LOCK_IMAGE); if( !ibuf->rect_float ) IMB_float_from_rect(ibuf); BLI_unlock_thread(LOCK_IMAGE); } while( px < 0 ) px += ibuf->x; while( py < 0 ) py += ibuf->y; while( px >= ibuf->x ) px -= ibuf->x; while( py >= ibuf->y ) py -= ibuf->y; result = ibuf->rect_float + py*ibuf->x*4 + px*4; QUATCOPY( out, result ); } } }
/* note: it would be possible to use CMP version for both nodes */ static void do_hue_sat_fac(bNode *UNUSED(node), float *out, float *hue, float *sat, float *val, float *in, float *fac) { if(*fac!=0.0f && (*hue!=0.5f || *sat!=1.0f || *val!=1.0f)) { float col[3], hsv[3], mfac= 1.0f - *fac; rgb_to_hsv(in[0], in[1], in[2], hsv, hsv+1, hsv+2); hsv[0]+= (*hue - 0.5f); if(hsv[0]>1.0f) hsv[0]-=1.0f; else if(hsv[0]<0.0f) hsv[0]+= 1.0f; hsv[1]*= *sat; hsv[2]*= *val; hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col+1, col+2); out[0]= mfac*in[0] + *fac*col[0]; out[1]= mfac*in[1] + *fac*col[1]; out[2]= mfac*in[2] + *fac*col[2]; } else { QUATCOPY(out, in); } }
static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan) { bConstraint *pcon, *con; VECCOPY(pchan->loc, chan->loc); VECCOPY(pchan->size, chan->size); VECCOPY(pchan->eul, chan->eul); VECCOPY(pchan->rotAxis, chan->rotAxis); pchan->rotAngle= chan->rotAngle; QUATCOPY(pchan->quat, chan->quat); pchan->rotmode= chan->rotmode; copy_m4_m4(pchan->chan_mat, (float(*)[4])chan->chan_mat); copy_m4_m4(pchan->pose_mat, (float(*)[4])chan->pose_mat); pchan->flag= chan->flag; con= chan->constraints.first; for(pcon= pchan->constraints.first; pcon && con; pcon= pcon->next, con= con->next) { pcon->enforce= con->enforce; pcon->headtail= con->headtail; } }
static void node_composit_exec_normalize(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) { /* stack order in: valbuf */ /* stack order out: valbuf */ if(out[0]->hasoutput==0) return; /* Input has no image buffer? Then pass the value */ if(in[0]->data==NULL) { QUATCOPY(out[0]->vec, in[0]->vec); } else { float min = 1.0f+BLENDER_ZMAX; float max = -1.0f-BLENDER_ZMAX; float mult = 1.0f; float *val; /* make output size of input image */ CompBuf *cbuf= in[0]->data; int tot= cbuf->x*cbuf->y; CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */ for (val = cbuf->rect; tot; tot--, val++) { if ((*val > max) && (*val <= BLENDER_ZMAX)) { max = *val; } if ((*val < min) && (*val >= -BLENDER_ZMAX)) { min = *val; } } /* In the rare case of flat buffer, which would cause a divide by 0, just pass the input to the output */ if ((max-min) != 0.0f) { mult = 1.0f/(max-min); composit3_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, NULL, &min, NULL, &mult, do_normalize, CB_VAL, CB_VAL, CB_VAL); } else { memcpy(stackbuf->rect, cbuf->rect, sizeof(float) * cbuf->x * cbuf->y); } out[0]->data= stackbuf; } }
static void do_hue_sat_fac(bNode *UNUSED(node), float *out, float hue, float sat, float val, float *in, float fac) { if(fac != 0 && (hue != 0.5f || sat != 1 || val != 1)) { float col[3], hsv[3], mfac= 1.0f - fac; rgb_to_hsv(in[0], in[1], in[2], hsv, hsv+1, hsv+2); hsv[0]+= (hue - 0.5f); if(hsv[0]>1.0f) hsv[0]-=1.0f; else if(hsv[0]<0.0f) hsv[0]+= 1.0f; hsv[1]*= sat; if(hsv[1]>1.0f) hsv[1]= 1.0f; else if(hsv[1]<0.0f) hsv[1]= 0.0f; hsv[2]*= val; if(hsv[2]>1.0f) hsv[2]= 1.0f; else if(hsv[2]<0.0f) hsv[2]= 0.0f; hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col+1, col+2); out[0]= mfac*in[0] + fac*col[0]; out[1]= mfac*in[1] + fac*col[1]; out[2]= mfac*in[2] + fac*col[2]; } else { QUATCOPY(out, in); } }
static void do_hue_sat_fac(bNode *node, float *out, float *in, float *fac) { NodeHueSat *nhs= node->storage; if(*fac!=0.0f && (nhs->hue!=0.5f || nhs->sat!=1.0 || nhs->val!=1.0)) { float col[3], hsv[3], mfac= 1.0f - *fac; rgb_to_hsv(in[0], in[1], in[2], hsv, hsv+1, hsv+2); hsv[0]+= (nhs->hue - 0.5f); if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0; hsv[1]*= nhs->sat; hsv[2]*= nhs->val; hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col+1, col+2); out[0]= mfac*in[0] + *fac*col[0]; out[1]= mfac*in[1] + *fac*col[1]; out[2]= mfac*in[2] + *fac*col[2]; out[3]= in[3]; } else { QUATCOPY(out, in); } }
/* both poses should be in sync */ void copy_pose_result(bPose *to, bPose *from) { bPoseChannel *pchanto, *pchanfrom; if(to==NULL || from==NULL) { printf("pose result copy error to:%p from:%p\n", (void *)to, (void *)from); // debug temp return; } if (to==from) { printf("copy_pose_result source and target are the same\n"); return; } for(pchanfrom= from->chanbase.first; pchanfrom; pchanfrom= pchanfrom->next) { pchanto= get_pose_channel(to, pchanfrom->name); if(pchanto) { copy_m4_m4(pchanto->pose_mat, pchanfrom->pose_mat); copy_m4_m4(pchanto->chan_mat, pchanfrom->chan_mat); /* used for local constraints */ VECCOPY(pchanto->loc, pchanfrom->loc); QUATCOPY(pchanto->quat, pchanfrom->quat); VECCOPY(pchanto->eul, pchanfrom->eul); VECCOPY(pchanto->size, pchanfrom->size); VECCOPY(pchanto->pose_head, pchanfrom->pose_head); VECCOPY(pchanto->pose_tail, pchanfrom->pose_tail); pchanto->rotmode= pchanfrom->rotmode; pchanto->flag= pchanfrom->flag; pchanto->protectflag= pchanfrom->protectflag; } } }
/* draw grease-pencil datablock */ static void gp_draw_data (bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag) { bGPDlayer *gpl, *actlay=NULL; /* reset line drawing style (in case previous user didn't reset) */ setlinestyle(0); /* turn on smooth lines (i.e. anti-aliasing) */ glEnable(GL_LINE_SMOOTH); /* turn on alpha-blending */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); /* loop over layers, drawing them */ for (gpl= gpd->layers.first; gpl; gpl= gpl->next) { bGPDframe *gpf; short debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? 1 : 0; short lthick= gpl->thickness; float color[4], tcolor[4]; /* don't draw layer if hidden */ if (gpl->flag & GP_LAYER_HIDE) continue; /* if layer is active one, store pointer to it */ if (gpl->flag & GP_LAYER_ACTIVE) actlay= gpl; /* get frame to draw */ gpf= gpencil_layer_getframe(gpl, cfra, 0); if (gpf == NULL) continue; /* set color, stroke thickness, and point size */ glLineWidth(lthick); QUATCOPY(color, gpl->color); // just for copying 4 array elements QUATCOPY(tcolor, gpl->color); // additional copy of color (for ghosting) glColor4f(color[0], color[1], color[2], color[3]); glPointSize((float)(gpl->thickness + 2)); /* draw 'onionskins' (frame left + right) */ if (gpl->flag & GP_LAYER_ONIONSKIN) { /* drawing method - only immediately surrounding (gstep = 0), or within a frame range on either side (gstep > 0)*/ if (gpl->gstep) { bGPDframe *gf; float fac; /* draw previous frames first */ for (gf=gpf->prev; gf; gf=gf->prev) { /* check if frame is drawable */ if ((gpf->framenum - gf->framenum) <= gpl->gstep) { /* alpha decreases with distance from curframe index */ fac= (float)(gpf->framenum - gf->framenum) / (float)gpl->gstep; tcolor[3] = color[3] - fac; gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); } else break; } /* now draw next frames */ for (gf= gpf->next; gf; gf=gf->next) { /* check if frame is drawable */ if ((gf->framenum - gpf->framenum) <= gpl->gstep) { /* alpha decreases with distance from curframe index */ fac= (float)(gf->framenum - gpf->framenum) / (float)gpl->gstep; tcolor[3] = color[3] - fac; gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); } else break; } /* restore alpha */ glColor4f(color[0], color[1], color[2], color[3]); } else { /* draw the strokes for the ghost frames (at half of the alpha set by user) */ if (gpf->prev) { tcolor[3] = (color[3] / 7); gp_draw_strokes(gpf->prev, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); } if (gpf->next) { tcolor[3] = (color[3] / 4); gp_draw_strokes(gpf->next, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); } /* restore alpha */ glColor4f(color[0], color[1], color[2], color[3]); } } /* draw the strokes already in active frame */ tcolor[3]= color[3]; gp_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); /* Check if may need to draw the active stroke cache, only if this layer is the active layer * that is being edited. (Stroke buffer is currently stored in gp-data) */ if ((G.f & G_GREASEPENCIL) && (gpl->flag & GP_LAYER_ACTIVE) && (gpf->flag & GP_FRAME_PAINT)) { /* Buffer stroke needs to be drawn with a different linestyle to help differentiate them from normal strokes. */ gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag); } } /* turn off alpha blending, then smooth lines */ glDisable(GL_BLEND); // alpha blending glDisable(GL_LINE_SMOOTH); // smooth lines /* restore initial gl conditions */ glLineWidth(1.0); glPointSize(1.0); glColor4f(0, 0, 0, 1); }
/* clear rotation of object */ static void object_clear_rot(Object *ob) { /* clear rotations that aren't locked */ if (ob->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) { if (ob->protectflag & OB_LOCK_ROT4D) { /* perform clamping on a component by component basis */ if (ob->rotmode == ROT_MODE_AXISANGLE) { if ((ob->protectflag & OB_LOCK_ROTW) == 0) ob->rotAngle= ob->drotAngle= 0.0f; if ((ob->protectflag & OB_LOCK_ROTX) == 0) ob->rotAxis[0]= ob->drotAxis[0]= 0.0f; if ((ob->protectflag & OB_LOCK_ROTY) == 0) ob->rotAxis[1]= ob->drotAxis[1]= 0.0f; if ((ob->protectflag & OB_LOCK_ROTZ) == 0) ob->rotAxis[2]= ob->drotAxis[2]= 0.0f; /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */ if (IS_EQ(ob->rotAxis[0], ob->rotAxis[1]) && IS_EQ(ob->rotAxis[1], ob->rotAxis[2])) ob->rotAxis[1] = 1.0f; if (IS_EQ(ob->drotAxis[0], ob->drotAxis[1]) && IS_EQ(ob->drotAxis[1], ob->drotAxis[2])) ob->drotAxis[1]= 1.0f; } else if (ob->rotmode == ROT_MODE_QUAT) { if ((ob->protectflag & OB_LOCK_ROTW) == 0) ob->quat[0]= ob->dquat[0]= 1.0f; if ((ob->protectflag & OB_LOCK_ROTX) == 0) ob->quat[1]= ob->dquat[1]= 0.0f; if ((ob->protectflag & OB_LOCK_ROTY) == 0) ob->quat[2]= ob->dquat[2]= 0.0f; if ((ob->protectflag & OB_LOCK_ROTZ) == 0) ob->quat[3]= ob->dquat[3]= 0.0f; // TODO: does this quat need normalising now? } else { /* the flag may have been set for the other modes, so just ignore the extra flag... */ if ((ob->protectflag & OB_LOCK_ROTX) == 0) ob->rot[0]= ob->drot[0]= 0.0f; if ((ob->protectflag & OB_LOCK_ROTY) == 0) ob->rot[1]= ob->drot[1]= 0.0f; if ((ob->protectflag & OB_LOCK_ROTZ) == 0) ob->rot[2]= ob->drot[2]= 0.0f; } } else { /* perform clamping using euler form (3-components) */ // FIXME: deltas are not handled for these cases yet... float eul[3], oldeul[3], quat1[4] = {0}; if (ob->rotmode == ROT_MODE_QUAT) { QUATCOPY(quat1, ob->quat); quat_to_eul(oldeul, ob->quat); } else if (ob->rotmode == ROT_MODE_AXISANGLE) { axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, ob->rotAxis, ob->rotAngle); } else { copy_v3_v3(oldeul, ob->rot); } eul[0]= eul[1]= eul[2]= 0.0f; if (ob->protectflag & OB_LOCK_ROTX) eul[0]= oldeul[0]; if (ob->protectflag & OB_LOCK_ROTY) eul[1]= oldeul[1]; if (ob->protectflag & OB_LOCK_ROTZ) eul[2]= oldeul[2]; if (ob->rotmode == ROT_MODE_QUAT) { eul_to_quat(ob->quat, eul); /* quaternions flip w sign to accumulate rotations correctly */ if ((quat1[0]<0.0f && ob->quat[0]>0.0f) || (quat1[0]>0.0f && ob->quat[0]<0.0f)) { mul_qt_fl(ob->quat, -1.0f); } } else if (ob->rotmode == ROT_MODE_AXISANGLE) { eulO_to_axis_angle(ob->rotAxis, &ob->rotAngle,eul, EULER_ORDER_DEFAULT); } else { copy_v3_v3(ob->rot, eul); } } } // Duplicated in source/blender/editors/armature/editarmature.c else { if (ob->rotmode == ROT_MODE_QUAT) { unit_qt(ob->quat); unit_qt(ob->dquat); } else if (ob->rotmode == ROT_MODE_AXISANGLE) { unit_axis_angle(ob->rotAxis, &ob->rotAngle); unit_axis_angle(ob->drotAxis, &ob->drotAngle); } else { zero_v3(ob->rot); zero_v3(ob->drot); } } }
/* ctime is normalized range <0-1> */ int where_on_path(Object *ob, float ctime, float *vec, float *dir, float *quat, float *radius) /* returns OK */ { Curve *cu; Nurb *nu; BevList *bl; Path *path; PathPoint *pp, *p0, *p1, *p2, *p3; float fac; float data[4]; int cycl=0, s0, s1, s2, s3; if(ob==NULL || ob->type != OB_CURVE) return 0; cu= ob->data; if(cu->path==NULL || cu->path->data==NULL) { printf("no path!\n"); return 0; } path= cu->path; pp= path->data; /* test for cyclic */ bl= cu->bev.first; if (!bl) return 0; if (!bl->nr) return 0; if(bl->poly> -1) cycl= 1; ctime *= (path->len-1); s1= (int)floor(ctime); fac= (float)(s1+1)-ctime; /* path->len is corected for cyclic */ s0= interval_test(0, path->len-1-cycl, s1-1, cycl); s1= interval_test(0, path->len-1-cycl, s1, cycl); s2= interval_test(0, path->len-1-cycl, s1+1, cycl); s3= interval_test(0, path->len-1-cycl, s1+2, cycl); p0= pp + s0; p1= pp + s1; p2= pp + s2; p3= pp + s3; /* note, commented out for follow constraint */ //if(cu->flag & CU_FOLLOW) { key_curve_tangent_weights(1.0f-fac, data, KEY_BSPLINE); dir[0]= data[0]*p0->vec[0] + data[1]*p1->vec[0] + data[2]*p2->vec[0] + data[3]*p3->vec[0] ; dir[1]= data[0]*p0->vec[1] + data[1]*p1->vec[1] + data[2]*p2->vec[1] + data[3]*p3->vec[1] ; dir[2]= data[0]*p0->vec[2] + data[1]*p1->vec[2] + data[2]*p2->vec[2] + data[3]*p3->vec[2] ; /* make compatible with vectoquat */ dir[0]= -dir[0]; dir[1]= -dir[1]; dir[2]= -dir[2]; //} nu= cu->nurb.first; /* make sure that first and last frame are included in the vectors here */ if(nu->type == CU_POLY) key_curve_position_weights(1.0f-fac, data, KEY_LINEAR); else if(nu->type == CU_BEZIER) key_curve_position_weights(1.0f-fac, data, KEY_LINEAR); else if(s0==s1 || p2==p3) key_curve_position_weights(1.0f-fac, data, KEY_CARDINAL); else key_curve_position_weights(1.0f-fac, data, KEY_BSPLINE); vec[0]= data[0]*p0->vec[0] + data[1]*p1->vec[0] + data[2]*p2->vec[0] + data[3]*p3->vec[0] ; /* X */ vec[1]= data[0]*p0->vec[1] + data[1]*p1->vec[1] + data[2]*p2->vec[1] + data[3]*p3->vec[1] ; /* Y */ vec[2]= data[0]*p0->vec[2] + data[1]*p1->vec[2] + data[2]*p2->vec[2] + data[3]*p3->vec[2] ; /* Z */ vec[3]= data[0]*p0->vec[3] + data[1]*p1->vec[3] + data[2]*p2->vec[3] + data[3]*p3->vec[3] ; /* Tilt, should not be needed since we have quat still used */ /* Need to verify the quat interpolation is correct - XXX */ if (quat) { //float totfac, q1[4], q2[4]; /* checks for totfac are needed when 'fac' is 1.0 key_curve_position_weights can assign zero * to more then one index in data which can give divide by zero error */ /* totfac= data[0]+data[1]; if(totfac>0.000001) QuatInterpol(q1, p0->quat, p1->quat, data[0] / totfac); else QUATCOPY(q1, p1->quat); NormalQuat(q1); totfac= data[2]+data[3]; if(totfac>0.000001) QuatInterpol(q2, p2->quat, p3->quat, data[2] / totfac); else QUATCOPY(q1, p3->quat); NormalQuat(q2); totfac = data[0]+data[1]+data[2]+data[3]; if(totfac>0.000001) QuatInterpol(quat, q1, q2, (data[0]+data[1]) / totfac); else QUATCOPY(quat, q2); NormalQuat(quat); */ // XXX - find some way to make quat interpolation work correctly, above code fails in rare but nasty cases. QUATCOPY(quat, p1->quat); } if(radius) *radius= data[0]*p0->radius + data[1]*p1->radius + data[2]*p2->radius + data[3]*p3->radius; return 1; }
static void do_filter3(CompBuf *out, CompBuf *in, float *filter, float fac) { float *row1, *row2, *row3; float *fp, mfac= 1.0f-fac; int rowlen, x, y, c; int pixlen= in->type; rowlen= in->x; for(y=0; y<in->y; y++) { /* setup rows */ if(y==0) row1= in->rect; else row1= in->rect + pixlen*(y-1)*rowlen; row2= in->rect + y*pixlen*rowlen; if(y==in->y-1) row3= row2; else row3= row2 + pixlen*rowlen; fp= out->rect + pixlen*(y)*rowlen; if(pixlen==1) { fp[0]= row2[0]; fp+= 1; for(x=2; x<rowlen; x++) { fp[0]= mfac*row2[1] + fac*(filter[0]*row1[0] + filter[1]*row1[1] + filter[2]*row1[2] + filter[3]*row2[0] + filter[4]*row2[1] + filter[5]*row2[2] + filter[6]*row3[0] + filter[7]*row3[1] + filter[8]*row3[2]); fp++; row1++; row2++; row3++; } fp[0]= row2[1]; } else if(pixlen==2) { fp[0]= row2[0]; fp[1]= row2[1]; fp+= 2; for(x=2; x<rowlen; x++) { for(c=0; c<2; c++) { fp[0]= mfac*row2[2] + fac*(filter[0]*row1[0] + filter[1]*row1[2] + filter[2]*row1[4] + filter[3]*row2[0] + filter[4]*row2[2] + filter[5]*row2[4] + filter[6]*row3[0] + filter[7]*row3[2] + filter[8]*row3[4]); fp++; row1++; row2++; row3++; } } fp[0]= row2[2]; fp[1]= row2[3]; } else if(pixlen==3) { VECCOPY(fp, row2); fp+= 3; for(x=2; x<rowlen; x++) { for(c=0; c<3; c++) { fp[0]= mfac*row2[3] + fac*(filter[0]*row1[0] + filter[1]*row1[3] + filter[2]*row1[6] + filter[3]*row2[0] + filter[4]*row2[3] + filter[5]*row2[6] + filter[6]*row3[0] + filter[7]*row3[3] + filter[8]*row3[6]); fp++; row1++; row2++; row3++; } } VECCOPY(fp, row2+3); } else { QUATCOPY(fp, row2); fp+= 4; for(x=2; x<rowlen; x++) { for(c=0; c<4; c++) { fp[0]= mfac*row2[4] + fac*(filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8]); fp++; row1++; row2++; row3++; } } QUATCOPY(fp, row2+4); } } }
/* the main entry point for volume shading */ static void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr, int inside_volume) { float hitco[3], col[4] = {0.f,0.f,0.f,0.f}; float *startco, *endco; int trace_behind = 1; const int ztransp= ((shi->depth==0) && (shi->mat->mode & MA_TRANSP) && (shi->mat->mode & MA_ZTRANSP)); Isect is; /* check for shading an internal face a volume object directly */ if (inside_volume == VOL_SHADE_INSIDE) trace_behind = 0; else if (inside_volume == VOL_SHADE_OUTSIDE) { if (shi->flippednor) inside_volume = VOL_SHADE_INSIDE; } if (ztransp && inside_volume == VOL_SHADE_INSIDE) { MatInside *mi; int render_this=0; /* don't render the backfaces of ztransp volume materials. * volume shading renders the internal volume from between the * ' view intersection of the solid volume to the * intersection on the other side, as part of the shading of * the front face. * Because ztransp renders both front and back faces independently * this will double up, so here we prevent rendering the backface as well, * which would otherwise render the volume in between the camera and the backface * --matt */ for (mi=R.render_volumes_inside.first; mi; mi=mi->next) { /* weak... */ if (mi->ma == shi->mat) render_this=1; } if (!render_this) return; } if (inside_volume == VOL_SHADE_INSIDE) { startco = shi->camera_co; endco = shi->co; if (trace_behind) { if (!ztransp) /* trace behind the volume object */ vol_trace_behind(shi, shi->vlr, endco, col); } else { /* we're tracing through the volume between the camera * and a solid surface, so use that pre-shaded radiance */ QUATCOPY(col, shr->combined); } /* shade volume from 'camera' to 1st hit point */ volumeintegrate(shi, col, startco, endco); } /* trace to find a backface, the other side bounds of the volume */ /* (ray intersect ignores front faces here) */ else if (vol_get_bounds(shi, shi->co, shi->view, hitco, &is, VOL_BOUNDS_DEPTH)) { VlakRen *vlr = (VlakRen *)is.hit.face; startco = shi->co; endco = hitco; if (!ztransp) { /* if it's another face in the same material */ if (vlr->mat == shi->mat) { /* trace behind the 2nd (raytrace) hit point */ vol_trace_behind(shi, (VlakRen *)is.hit.face, endco, col); } else { shade_intersection(shi, col, &is); } } /* shade volume from 1st hit point to 2nd hit point */ volumeintegrate(shi, col, startco, endco); } if (ztransp) col[3] = col[3]>1.f?1.f:col[3]; else col[3] = 1.f; copy_v3_v3(shr->combined, col); shr->alpha = col[3]; VECCOPY(shr->diff, shr->combined); }